diff options
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/asix_devices.c | 6 | ||||
-rw-r--r-- | drivers/net/usb/ax88179_178a.c | 12 | ||||
-rw-r--r-- | drivers/net/usb/cdc_ether.c | 5 | ||||
-rw-r--r-- | drivers/net/usb/cdc_mbim.c | 4 | ||||
-rw-r--r-- | drivers/net/usb/cdc_ncm.c | 18 | ||||
-rw-r--r-- | drivers/net/usb/dm9601.c | 7 | ||||
-rw-r--r-- | drivers/net/usb/mcs7830.c | 6 | ||||
-rw-r--r-- | drivers/net/usb/sierra_net.c | 3 | ||||
-rw-r--r-- | drivers/net/usb/usbnet.c | 45 |
9 files changed, 63 insertions, 43 deletions
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index 709753469099..ad5d1e4384db 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -55,11 +55,7 @@ static void asix_status(struct usbnet *dev, struct urb *urb) event = urb->transfer_buffer; link = event->link & 0x01; if (netif_carrier_ok(dev->net) != link) { - if (link) { - netif_carrier_on(dev->net); - usbnet_defer_kevent (dev, EVENT_LINK_RESET ); - } else - netif_carrier_off(dev->net); + usbnet_link_change(dev, link, 1); netdev_dbg(dev->net, "Link Status is: %d\n", link); } } diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 71c27d8d214f..bd8758fa38c1 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -352,11 +352,7 @@ static void ax88179_status(struct usbnet *dev, struct urb *urb) link = (((__force u32)event->intdata1) & AX_INT_PPLS_LINK) >> 16; if (netif_carrier_ok(dev->net) != link) { - if (link) - usbnet_defer_kevent(dev, EVENT_LINK_RESET); - else - netif_carrier_off(dev->net); - + usbnet_link_change(dev, link, 1); netdev_info(dev->net, "ax88179 - Link status is: %d\n", link); } } @@ -455,7 +451,7 @@ static int ax88179_resume(struct usb_interface *intf) u16 tmp16; u8 tmp8; - netif_carrier_off(dev->net); + usbnet_link_change(dev, 0, 0); /* Power up ethernet PHY */ tmp16 = 0; @@ -1068,7 +1064,7 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf) /* Restart autoneg */ mii_nway_restart(&dev->mii); - netif_carrier_off(dev->net); + usbnet_link_change(dev, 0, 0); return 0; } @@ -1356,7 +1352,7 @@ static int ax88179_reset(struct usbnet *dev) /* Restart autoneg */ mii_nway_restart(&dev->mii); - netif_carrier_off(dev->net); + usbnet_link_change(dev, 0, 0); return 0; } diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 57136dc1b887..4ff71d619cd8 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -406,10 +406,7 @@ void usbnet_cdc_status(struct usbnet *dev, struct urb *urb) case USB_CDC_NOTIFY_NETWORK_CONNECTION: netif_dbg(dev, timer, dev->net, "CDC: carrier %s\n", event->wValue ? "on" : "off"); - if (event->wValue) - netif_carrier_on(dev->net); - else - netif_carrier_off(dev->net); + usbnet_link_change(dev, !!event->wValue, 0); break; case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */ netif_dbg(dev, timer, dev->net, "CDC: speed change (len %d)\n", diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index 6bd91676d2cb..c96454434f7b 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c @@ -101,7 +101,7 @@ static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->flags |= IFF_NOARP; /* no need to put the VLAN tci in the packet headers */ - dev->net->features |= NETIF_F_HW_VLAN_TX; + dev->net->features |= NETIF_F_HW_VLAN_CTAG_TX; err: return ret; } @@ -221,7 +221,7 @@ static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_ /* map MBIM session to VLAN */ if (tci) - vlan_put_tag(skb, tci); + vlan_put_tag(skb, htons(ETH_P_8021Q), tci); err: return skb; } diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 4709fa3497cf..43afde8f48d2 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -362,8 +362,8 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_ u8 iface_no; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (ctx == NULL) - return -ENODEV; + if (!ctx) + return -ENOMEM; hrtimer_init(&ctx->tx_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ctx->tx_timer.function = &cdc_ncm_tx_timer_cb; @@ -610,7 +610,7 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf) * (carrier is OFF) during attach, so the IP network stack does not * start IPv6 negotiation and more. */ - netif_carrier_off(dev->net); + usbnet_link_change(dev, 0, 0); return ret; } @@ -1106,12 +1106,9 @@ static void cdc_ncm_status(struct usbnet *dev, struct urb *urb) " %sconnected\n", ctx->netdev->name, ctx->connected ? "" : "dis"); - if (ctx->connected) - netif_carrier_on(dev->net); - else { - netif_carrier_off(dev->net); + usbnet_link_change(dev, ctx->connected, 0); + if (!ctx->connected) ctx->tx_speed = ctx->rx_speed = 0; - } break; case USB_CDC_NOTIFY_SPEED_CHANGE: @@ -1124,8 +1121,9 @@ static void cdc_ncm_status(struct usbnet *dev, struct urb *urb) break; default: - dev_err(&dev->udev->dev, "NCM: unexpected " - "notification 0x%02x!\n", event->bNotificationType); + dev_dbg(&dev->udev->dev, + "NCM: unexpected notification 0x%02x!\n", + event->bNotificationType); break; } } diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 174e5ecea4cc..2dbb9460349d 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -524,12 +524,7 @@ static void dm9601_status(struct usbnet *dev, struct urb *urb) link = !!(buf[0] & 0x40); if (netif_carrier_ok(dev->net) != link) { - if (link) { - netif_carrier_on(dev->net); - usbnet_defer_kevent (dev, EVENT_LINK_RESET); - } - else - netif_carrier_off(dev->net); + usbnet_link_change(dev, link, 1); netdev_dbg(dev->net, "Link Status is: %d\n", link); } } diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index 3f3f566afa0b..03832d3780aa 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -576,11 +576,7 @@ static void mcs7830_status(struct usbnet *dev, struct urb *urb) */ if (data->link_counter > 20) { data->link_counter = 0; - if (link) { - netif_carrier_on(dev->net); - usbnet_defer_kevent(dev, EVENT_LINK_RESET); - } else - netif_carrier_off(dev->net); + usbnet_link_change(dev, link, 0); netdev_dbg(dev->net, "Link Status is: %d\n", link); } } else diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index 79ab2435d9d3..a923d61c6fc5 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -413,11 +413,10 @@ static void sierra_net_handle_lsi(struct usbnet *dev, char *data, if (link_up) { sierra_net_set_ctx_index(priv, hh->msgspecific.byte); priv->link_up = 1; - netif_carrier_on(dev->net); } else { priv->link_up = 0; - netif_carrier_off(dev->net); } + usbnet_link_change(dev, link_up, 0); } static void sierra_net_dosync(struct usbnet *dev) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 51f3192f3931..1e5a9b72650e 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -938,6 +938,27 @@ static const struct ethtool_ops usbnet_ethtool_ops = { /*-------------------------------------------------------------------------*/ +static void __handle_link_change(struct usbnet *dev) +{ + if (!test_bit(EVENT_DEV_OPEN, &dev->flags)) + return; + + if (!netif_carrier_ok(dev->net)) { + /* kill URBs for reading packets to save bus bandwidth */ + unlink_urbs(dev, &dev->rxq); + + /* + * tx_timeout will unlink URBs for sending packets and + * tx queue is stopped by netcore after link becomes off + */ + } else { + /* submitting URBs for reading packets */ + tasklet_schedule(&dev->bh); + } + + clear_bit(EVENT_LINK_CHANGE, &dev->flags); +} + /* work that cannot be done in interrupt context uses keventd. * * NOTE: with 2.5 we could do more of this using completion callbacks, @@ -1035,8 +1056,14 @@ skip_reset: } else { usb_autopm_put_interface(dev->intf); } + + /* handle link change from link resetting */ + __handle_link_change(dev); } + if (test_bit (EVENT_LINK_CHANGE, &dev->flags)) + __handle_link_change(dev); + if (dev->flags) netdev_dbg(dev->net, "kevent done, flags = 0x%lx\n", dev->flags); } @@ -1286,6 +1313,7 @@ static void usbnet_bh (unsigned long param) // or are we maybe short a few urbs? } else if (netif_running (dev->net) && netif_device_present (dev->net) && + netif_carrier_ok(dev->net) && !timer_pending (&dev->delay) && !test_bit (EVENT_RX_HALT, &dev->flags)) { int temp = dev->rxq.qlen; @@ -1521,7 +1549,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) netif_device_attach (net); if (dev->driver_info->flags & FLAG_LINK_INTR) - netif_carrier_off(net); + usbnet_link_change(dev, 0, 0); return 0; @@ -1653,6 +1681,21 @@ int usbnet_manage_power(struct usbnet *dev, int on) } EXPORT_SYMBOL(usbnet_manage_power); +void usbnet_link_change(struct usbnet *dev, bool link, bool need_reset) +{ + /* update link after link is reseted */ + if (link && !need_reset) + netif_carrier_on(dev->net); + else + netif_carrier_off(dev->net); + + if (need_reset && link) + usbnet_defer_kevent(dev, EVENT_LINK_RESET); + else + usbnet_defer_kevent(dev, EVENT_LINK_CHANGE); +} +EXPORT_SYMBOL(usbnet_link_change); + /*-------------------------------------------------------------------------*/ static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, u16 value, u16 index, void *data, u16 size) |