aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/usbnet.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2009-07-30 12:41:20 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-04 16:44:15 -0400
commit1487cd5e76337555737cbc55d7d83f41460d198f (patch)
treef6d4dbb7debf36014d25ab4b482a32683d46ede2 /drivers/net/usb/usbnet.c
parente40cbdac0629402a4cb0c3bca0cc19ab7a00e00d (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/usbnet.c')
-rw-r--r--drivers/net/usb/usbnet.c32
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