diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/usb/usbnet.c | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 1e46f693eb47..aba769d77459 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
@@ -1204,6 +1204,21 @@ deferred: | |||
1204 | } | 1204 | } |
1205 | EXPORT_SYMBOL_GPL(usbnet_start_xmit); | 1205 | EXPORT_SYMBOL_GPL(usbnet_start_xmit); |
1206 | 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 | |||
1207 | /*-------------------------------------------------------------------------*/ | 1222 | /*-------------------------------------------------------------------------*/ |
1208 | 1223 | ||
1209 | // tasklet (work deferred from completions, in_irq) or timer | 1224 | // tasklet (work deferred from completions, in_irq) or timer |
@@ -1243,26 +1258,14 @@ static void usbnet_bh (unsigned long param) | |||
1243 | !timer_pending (&dev->delay) && | 1258 | !timer_pending (&dev->delay) && |
1244 | !test_bit (EVENT_RX_HALT, &dev->flags)) { | 1259 | !test_bit (EVENT_RX_HALT, &dev->flags)) { |
1245 | int temp = dev->rxq.qlen; | 1260 | int temp = dev->rxq.qlen; |
1246 | int qlen = RX_QLEN (dev); | 1261 | |
1247 | 1262 | if (temp < RX_QLEN(dev)) { | |
1248 | if (temp < qlen) { | 1263 | rx_alloc_submit(dev, GFP_ATOMIC); |
1249 | struct urb *urb; | ||
1250 | int i; | ||
1251 | |||
1252 | // don't refill the queue all at once | ||
1253 | for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) { | ||
1254 | urb = usb_alloc_urb (0, GFP_ATOMIC); | ||
1255 | if (urb != NULL) { | ||
1256 | if (rx_submit (dev, urb, GFP_ATOMIC) == | ||
1257 | -ENOLINK) | ||
1258 | return; | ||
1259 | } | ||
1260 | } | ||
1261 | if (temp != dev->rxq.qlen) | 1264 | if (temp != dev->rxq.qlen) |
1262 | netif_dbg(dev, link, dev->net, | 1265 | netif_dbg(dev, link, dev->net, |
1263 | "rxqlen %d --> %d\n", | 1266 | "rxqlen %d --> %d\n", |
1264 | temp, dev->rxq.qlen); | 1267 | temp, dev->rxq.qlen); |
1265 | if (dev->rxq.qlen < qlen) | 1268 | if (dev->rxq.qlen < RX_QLEN(dev)) |
1266 | tasklet_schedule (&dev->bh); | 1269 | tasklet_schedule (&dev->bh); |
1267 | } | 1270 | } |
1268 | if (dev->txq.qlen < TX_QLEN (dev)) | 1271 | if (dev->txq.qlen < TX_QLEN (dev)) |
@@ -1572,6 +1575,13 @@ int usbnet_resume (struct usb_interface *intf) | |||
1572 | spin_unlock_irq(&dev->txq.lock); | 1575 | spin_unlock_irq(&dev->txq.lock); |
1573 | 1576 | ||
1574 | 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 | |||
1575 | if (!(dev->txq.qlen >= TX_QLEN(dev))) | 1585 | if (!(dev->txq.qlen >= TX_QLEN(dev))) |
1576 | netif_tx_wake_all_queues(dev->net); | 1586 | netif_tx_wake_all_queues(dev->net); |
1577 | tasklet_schedule (&dev->bh); | 1587 | tasklet_schedule (&dev->bh); |