diff options
Diffstat (limited to 'drivers/net/usb/usbnet.c')
| -rw-r--r-- | drivers/net/usb/usbnet.c | 53 |
1 files changed, 33 insertions, 20 deletions
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 9f58330f1312..aba769d77459 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
| @@ -796,11 +796,13 @@ int usbnet_open (struct net_device *net) | |||
| 796 | if (info->manage_power) { | 796 | if (info->manage_power) { |
| 797 | retval = info->manage_power(dev, 1); | 797 | retval = info->manage_power(dev, 1); |
| 798 | if (retval < 0) | 798 | if (retval < 0) |
| 799 | goto done; | 799 | goto done_manage_power_error; |
| 800 | usb_autopm_put_interface(dev->intf); | 800 | usb_autopm_put_interface(dev->intf); |
| 801 | } | 801 | } |
| 802 | return retval; | 802 | return retval; |
| 803 | 803 | ||
| 804 | done_manage_power_error: | ||
| 805 | clear_bit(EVENT_DEV_OPEN, &dev->flags); | ||
| 804 | done: | 806 | done: |
| 805 | usb_autopm_put_interface(dev->intf); | 807 | usb_autopm_put_interface(dev->intf); |
| 806 | done_nopm: | 808 | done_nopm: |
| @@ -876,9 +878,9 @@ void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info) | |||
| 876 | { | 878 | { |
| 877 | struct usbnet *dev = netdev_priv(net); | 879 | struct usbnet *dev = netdev_priv(net); |
| 878 | 880 | ||
| 879 | strncpy (info->driver, dev->driver_name, sizeof info->driver); | 881 | strlcpy (info->driver, dev->driver_name, sizeof info->driver); |
| 880 | strncpy (info->version, DRIVER_VERSION, sizeof info->version); | 882 | strlcpy (info->version, DRIVER_VERSION, sizeof info->version); |
| 881 | strncpy (info->fw_version, dev->driver_info->description, | 883 | strlcpy (info->fw_version, dev->driver_info->description, |
| 882 | sizeof info->fw_version); | 884 | sizeof info->fw_version); |
| 883 | usb_make_path (dev->udev, info->bus_info, sizeof info->bus_info); | 885 | usb_make_path (dev->udev, info->bus_info, sizeof info->bus_info); |
| 884 | } | 886 | } |
| @@ -1202,6 +1204,21 @@ deferred: | |||
| 1202 | } | 1204 | } |
| 1203 | EXPORT_SYMBOL_GPL(usbnet_start_xmit); | 1205 | EXPORT_SYMBOL_GPL(usbnet_start_xmit); |
| 1204 | 1206 | ||
| 1207 | static void rx_alloc_submit(struct usbnet *dev, gfp_t flags) | ||
| 1208 | { | ||
| 1209 | struct urb *urb; | ||
| 1210 | int i; | ||
| 1211 | |||
| 1212 | /* don't refill the queue all at once */ | ||
| 1213 | for (i = 0; i < 10 && dev->rxq.qlen < RX_QLEN(dev); i++) { | ||
| 1214 | urb = usb_alloc_urb(0, flags); | ||
| 1215 | if (urb != NULL) { | ||
| 1216 | if (rx_submit(dev, urb, flags) == -ENOLINK) | ||
| 1217 | return; | ||
| 1218 | } | ||
| 1219 | } | ||
| 1220 | } | ||
| 1221 | |||
| 1205 | /*-------------------------------------------------------------------------*/ | 1222 | /*-------------------------------------------------------------------------*/ |
| 1206 | 1223 | ||
| 1207 | // tasklet (work deferred from completions, in_irq) or timer | 1224 | // tasklet (work deferred from completions, in_irq) or timer |
| @@ -1241,26 +1258,14 @@ static void usbnet_bh (unsigned long param) | |||
| 1241 | !timer_pending (&dev->delay) && | 1258 | !timer_pending (&dev->delay) && |
| 1242 | !test_bit (EVENT_RX_HALT, &dev->flags)) { | 1259 | !test_bit (EVENT_RX_HALT, &dev->flags)) { |
| 1243 | int temp = dev->rxq.qlen; | 1260 | int temp = dev->rxq.qlen; |
| 1244 | int qlen = RX_QLEN (dev); | 1261 | |
| 1245 | 1262 | if (temp < RX_QLEN(dev)) { | |
| 1246 | if (temp < qlen) { | 1263 | rx_alloc_submit(dev, GFP_ATOMIC); |
| 1247 | struct urb *urb; | ||
| 1248 | int i; | ||
| 1249 | |||
| 1250 | // don't refill the queue all at once | ||
| 1251 | for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) { | ||
| 1252 | urb = usb_alloc_urb (0, GFP_ATOMIC); | ||
| 1253 | if (urb != NULL) { | ||
| 1254 | if (rx_submit (dev, urb, GFP_ATOMIC) == | ||
| 1255 | -ENOLINK) | ||
| 1256 | return; | ||
| 1257 | } | ||
| 1258 | } | ||
| 1259 | if (temp != dev->rxq.qlen) | 1264 | if (temp != dev->rxq.qlen) |
| 1260 | netif_dbg(dev, link, dev->net, | 1265 | netif_dbg(dev, link, dev->net, |
| 1261 | "rxqlen %d --> %d\n", | 1266 | "rxqlen %d --> %d\n", |
| 1262 | temp, dev->rxq.qlen); | 1267 | temp, dev->rxq.qlen); |
| 1263 | if (dev->rxq.qlen < qlen) | 1268 | if (dev->rxq.qlen < RX_QLEN(dev)) |
| 1264 | tasklet_schedule (&dev->bh); | 1269 | tasklet_schedule (&dev->bh); |
| 1265 | } | 1270 | } |
| 1266 | if (dev->txq.qlen < TX_QLEN (dev)) | 1271 | if (dev->txq.qlen < TX_QLEN (dev)) |
| @@ -1513,6 +1518,7 @@ int usbnet_suspend (struct usb_interface *intf, pm_message_t message) | |||
| 1513 | spin_lock_irq(&dev->txq.lock); | 1518 | spin_lock_irq(&dev->txq.lock); |
| 1514 | /* don't autosuspend while transmitting */ | 1519 | /* don't autosuspend while transmitting */ |
| 1515 | if (dev->txq.qlen && PMSG_IS_AUTO(message)) { | 1520 | if (dev->txq.qlen && PMSG_IS_AUTO(message)) { |
| 1521 | dev->suspend_count--; | ||
| 1516 | spin_unlock_irq(&dev->txq.lock); | 1522 | spin_unlock_irq(&dev->txq.lock); |
| 1517 | return -EBUSY; | 1523 | return -EBUSY; |
| 1518 | } else { | 1524 | } else { |
| @@ -1569,6 +1575,13 @@ int usbnet_resume (struct usb_interface *intf) | |||
| 1569 | spin_unlock_irq(&dev->txq.lock); | 1575 | spin_unlock_irq(&dev->txq.lock); |
| 1570 | 1576 | ||
| 1571 | if (test_bit(EVENT_DEV_OPEN, &dev->flags)) { | 1577 | if (test_bit(EVENT_DEV_OPEN, &dev->flags)) { |
| 1578 | /* handle remote wakeup ASAP */ | ||
| 1579 | if (!dev->wait && | ||
| 1580 | netif_device_present(dev->net) && | ||
| 1581 | !timer_pending(&dev->delay) && | ||
| 1582 | !test_bit(EVENT_RX_HALT, &dev->flags)) | ||
| 1583 | rx_alloc_submit(dev, GFP_KERNEL); | ||
| 1584 | |||
| 1572 | if (!(dev->txq.qlen >= TX_QLEN(dev))) | 1585 | if (!(dev->txq.qlen >= TX_QLEN(dev))) |
| 1573 | netif_tx_wake_all_queues(dev->net); | 1586 | netif_tx_wake_all_queues(dev->net); |
| 1574 | tasklet_schedule (&dev->bh); | 1587 | tasklet_schedule (&dev->bh); |
