Skip to content

Commit

Permalink
usbnet: handle remote wakeup asap
Browse files Browse the repository at this point in the history
If usbnet is resumed by remote wakeup, generally there are
some packets comming to be handled, so allocate and submit
rx URBs in usbnet_resume to avoid delays introduced by tasklet.
Otherwise, usbnet may have been runtime suspended before the
usbnet_bh is executed to schedule Rx URBs.

Without the patch, usbnet can't recieve any packets from peer
in runtime suspend state if runtime PM is enabled and
autosuspend_delay is set as zero.

Signed-off-by: Ming Lei <ming.lei@canonical.com>
Acked-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ming Lei authored and David S. Miller committed Jun 23, 2012
1 parent 5eeb313 commit 65841fd
Showing 1 changed file with 26 additions and 16 deletions.
42 changes: 26 additions & 16 deletions drivers/net/usb/usbnet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1204,6 +1204,21 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(usbnet_start_xmit);

static void rx_alloc_submit(struct usbnet *dev, gfp_t flags)
{
struct urb *urb;
int i;

/* don't refill the queue all at once */
for (i = 0; i < 10 && dev->rxq.qlen < RX_QLEN(dev); i++) {
urb = usb_alloc_urb(0, flags);
if (urb != NULL) {
if (rx_submit(dev, urb, flags) == -ENOLINK)
return;
}
}
}

/*-------------------------------------------------------------------------*/

// tasklet (work deferred from completions, in_irq) or timer
Expand Down Expand Up @@ -1243,26 +1258,14 @@ static void usbnet_bh (unsigned long param)
!timer_pending (&dev->delay) &&
!test_bit (EVENT_RX_HALT, &dev->flags)) {
int temp = dev->rxq.qlen;
int qlen = RX_QLEN (dev);

if (temp < qlen) {
struct urb *urb;
int i;

// don't refill the queue all at once
for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) {
urb = usb_alloc_urb (0, GFP_ATOMIC);
if (urb != NULL) {
if (rx_submit (dev, urb, GFP_ATOMIC) ==
-ENOLINK)
return;
}
}

if (temp < RX_QLEN(dev)) {
rx_alloc_submit(dev, GFP_ATOMIC);
if (temp != dev->rxq.qlen)
netif_dbg(dev, link, dev->net,
"rxqlen %d --> %d\n",
temp, dev->rxq.qlen);
if (dev->rxq.qlen < qlen)
if (dev->rxq.qlen < RX_QLEN(dev))
tasklet_schedule (&dev->bh);
}
if (dev->txq.qlen < TX_QLEN (dev))
Expand Down Expand Up @@ -1572,6 +1575,13 @@ int usbnet_resume (struct usb_interface *intf)
spin_unlock_irq(&dev->txq.lock);

if (test_bit(EVENT_DEV_OPEN, &dev->flags)) {
/* handle remote wakeup ASAP */
if (!dev->wait &&
netif_device_present(dev->net) &&
!timer_pending(&dev->delay) &&
!test_bit(EVENT_RX_HALT, &dev->flags))
rx_alloc_submit(dev, GFP_KERNEL);

if (!(dev->txq.qlen >= TX_QLEN(dev)))
netif_tx_wake_all_queues(dev->net);
tasklet_schedule (&dev->bh);
Expand Down

0 comments on commit 65841fd

Please sign in to comment.