diff options
author | Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | 2009-07-30 12:41:20 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-08-04 16:44:15 -0400 |
commit | 1487cd5e76337555737cbc55d7d83f41460d198f (patch) | |
tree | f6d4dbb7debf36014d25ab4b482a32683d46ede2 /drivers/net/usb | |
parent | e40cbdac0629402a4cb0c3bca0cc19ab7a00e00d (diff) |
usbnet: allow "minidriver" to prevent urb unlinking on usbnet_stop
rndis_wlan devices freeze after running usbnet_stop several times. It appears
that firmware freezes in state where it does not respond to any RNDIS commands
and device have to be physically unplugged/replugged. This patch lets
minidrivers to disable unlink_urbs on usbnet_stop through new info flag.
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/usbnet.c | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 25e435c49040..af1fe4696509 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
@@ -601,21 +601,25 @@ int usbnet_stop (struct net_device *net) | |||
601 | info->description); | 601 | info->description); |
602 | } | 602 | } |
603 | 603 | ||
604 | // ensure there are no more active urbs | 604 | if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) { |
605 | add_wait_queue (&unlink_wakeup, &wait); | 605 | /* ensure there are no more active urbs */ |
606 | dev->wait = &unlink_wakeup; | 606 | add_wait_queue(&unlink_wakeup, &wait); |
607 | temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq); | 607 | dev->wait = &unlink_wakeup; |
608 | 608 | temp = unlink_urbs(dev, &dev->txq) + | |
609 | // maybe wait for deletions to finish. | 609 | unlink_urbs(dev, &dev->rxq); |
610 | while (!skb_queue_empty(&dev->rxq) | 610 | |
611 | && !skb_queue_empty(&dev->txq) | 611 | /* maybe wait for deletions to finish. */ |
612 | && !skb_queue_empty(&dev->done)) { | 612 | while (!skb_queue_empty(&dev->rxq) |
613 | msleep(UNLINK_TIMEOUT_MS); | 613 | && !skb_queue_empty(&dev->txq) |
614 | if (netif_msg_ifdown (dev)) | 614 | && !skb_queue_empty(&dev->done)) { |
615 | devdbg (dev, "waited for %d urb completions", temp); | 615 | msleep(UNLINK_TIMEOUT_MS); |
616 | if (netif_msg_ifdown(dev)) | ||
617 | devdbg(dev, "waited for %d urb completions", | ||
618 | temp); | ||
619 | } | ||
620 | dev->wait = NULL; | ||
621 | remove_wait_queue(&unlink_wakeup, &wait); | ||
616 | } | 622 | } |
617 | dev->wait = NULL; | ||
618 | remove_wait_queue (&unlink_wakeup, &wait); | ||
619 | 623 | ||
620 | usb_kill_urb(dev->interrupt); | 624 | usb_kill_urb(dev->interrupt); |
621 | 625 | ||