diff options
Diffstat (limited to 'drivers/net/usb/r8152.c')
| -rw-r--r-- | drivers/net/usb/r8152.c | 68 |
1 files changed, 59 insertions, 9 deletions
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 18e12a3f7fc..3eab74c7c55 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -282,7 +282,7 @@ /* USB_DEV_STAT */ #define STAT_SPEED_MASK 0x0006 #define STAT_SPEED_HIGH 0x0000 -#define STAT_SPEED_FULL 0x0001 +#define STAT_SPEED_FULL 0x0002 /* USB_TX_AGG */ #define TX_AGG_MAX_THRESHOLD 0x03 @@ -630,12 +630,10 @@ int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) int ret; void *tmp; - tmp = kmalloc(size, GFP_KERNEL); + tmp = kmemdup(data, size, GFP_KERNEL); if (!tmp) return -ENOMEM; - memcpy(tmp, data, size); - ret = usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0), RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE, value, index, tmp, size, 500); @@ -929,6 +927,9 @@ static int read_mii_word(struct net_device *netdev, int phy_id, int reg) struct r8152 *tp = netdev_priv(netdev); int ret; + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return -ENODEV; + if (phy_id != R8152_PHY_ID) return -EINVAL; @@ -949,6 +950,9 @@ void write_mii_word(struct net_device *netdev, int phy_id, int reg, int val) { struct r8152 *tp = netdev_priv(netdev); + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return; + if (phy_id != R8152_PHY_ID) return; @@ -1355,7 +1359,7 @@ static void r8152_csum_workaround(struct r8152 *tp, struct sk_buff *skb, struct sk_buff_head seg_list; struct sk_buff *segs, *nskb; - features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO); + features &= ~(NETIF_F_SG | NETIF_F_IPV6_CSUM | NETIF_F_TSO6); segs = skb_gso_segment(skb, features); if (IS_ERR(segs) || !segs) goto drop; @@ -1962,6 +1966,9 @@ static int rtl_enable(struct r8152 *tp) static int rtl8152_enable(struct r8152 *tp) { + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return -ENODEV; + set_tx_qlen(tp); rtl_set_eee_plus(tp); @@ -1994,6 +2001,9 @@ static void r8153_set_rx_agg(struct r8152 *tp) static int rtl8153_enable(struct r8152 *tp) { + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return -ENODEV; + set_tx_qlen(tp); rtl_set_eee_plus(tp); r8153_set_rx_agg(tp); @@ -2006,6 +2016,11 @@ static void rtl8152_disable(struct r8152 *tp) u32 ocp_data; int i; + if (test_bit(RTL8152_UNPLUG, &tp->flags)) { + rtl_drop_queued_tx(tp); + return; + } + ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); ocp_data &= ~RCR_ACPT_ALL; ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); @@ -2232,6 +2247,9 @@ static void r8152b_exit_oob(struct r8152 *tp) u32 ocp_data; int i; + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return; + ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); ocp_data &= ~RCR_ACPT_ALL; ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); @@ -2274,9 +2292,8 @@ static void r8152b_exit_oob(struct r8152 *tp) /* rx share fifo credit full threshold */ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL); - ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_DEV_STAT); - ocp_data &= STAT_SPEED_MASK; - if (ocp_data == STAT_SPEED_FULL) { + if (tp->udev->speed == USB_SPEED_FULL || + tp->udev->speed == USB_SPEED_LOW) { /* rx share fifo credit near full threshold */ ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_FULL); @@ -2460,6 +2477,9 @@ static void r8153_first_init(struct r8152 *tp) u32 ocp_data; int i; + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return; + rxdy_gated_en(tp, true); r8153_teredo_off(tp); @@ -2687,6 +2707,11 @@ out: static void rtl8152_down(struct r8152 *tp) { + if (test_bit(RTL8152_UNPLUG, &tp->flags)) { + rtl_drop_queued_tx(tp); + return; + } + r8152_power_cut_en(tp, false); r8152b_disable_aldps(tp); r8152b_enter_oob(tp); @@ -2695,6 +2720,11 @@ static void rtl8152_down(struct r8152 *tp) static void rtl8153_down(struct r8152 *tp) { + if (test_bit(RTL8152_UNPLUG, &tp->flags)) { + rtl_drop_queued_tx(tp); + return; + } + r8153_u1u2en(tp, false); r8153_power_cut_en(tp, false); r8153_disable_aldps(tp); @@ -2904,6 +2934,9 @@ static void r8152b_init(struct r8152 *tp) { u32 ocp_data; + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return; + if (tp->version == RTL_VER_01) { ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE); ocp_data &= ~LED_MODE_MASK; @@ -2939,6 +2972,9 @@ static void r8153_init(struct r8152 *tp) u32 ocp_data; int i; + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return; + r8153_u1u2en(tp, false); for (i = 0; i < 500; i++) { @@ -3167,8 +3203,13 @@ static void rtl8152_get_ethtool_stats(struct net_device *dev, struct r8152 *tp = netdev_priv(dev); struct tally_counter tally; + if (usb_autopm_get_interface(tp->intf) < 0) + return; + generic_ocp_read(tp, PLA_TALLYCNT, sizeof(tally), &tally, MCU_TYPE_PLA); + usb_autopm_put_interface(tp->intf); + data[0] = le64_to_cpu(tally.tx_packets); data[1] = le64_to_cpu(tally.rx_packets); data[2] = le64_to_cpu(tally.tx_errors); @@ -3213,6 +3254,9 @@ static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) struct mii_ioctl_data *data = if_mii(rq); int res; + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return -ENODEV; + res = usb_autopm_get_interface(tp->intf); if (res < 0) goto out; @@ -3293,12 +3337,18 @@ static void r8152b_get_version(struct r8152 *tp) static void rtl8152_unload(struct r8152 *tp) { + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return; + if (tp->version != RTL_VER_01) r8152_power_cut_en(tp, true); } static void rtl8153_unload(struct r8152 *tp) { + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return; + r8153_power_cut_en(tp, true); } @@ -3404,7 +3454,7 @@ static int rtl8152_probe(struct usb_interface *intf, NETIF_F_TSO | NETIF_F_FRAGLIST | NETIF_F_IPV6_CSUM | NETIF_F_TSO6; - SET_ETHTOOL_OPS(netdev, &ops); + netdev->ethtool_ops = &ops; netif_set_gso_max_size(netdev, RTL_LIMITED_TSO_SIZE); tp->mii.dev = netdev; |
