aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/net/usb/usbnet.c32
-rw-r--r--drivers/net/wireless/rndis_wlan.c9
-rw-r--r--include/linux/usb/usbnet.h1
3 files changed, 25 insertions, 17 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
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 09c0702ae645..76c5ec6bbbc5 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -2513,7 +2513,8 @@ static int rndis_wlan_stop(struct usbnet *usbdev)
2513 2513
2514static const struct driver_info bcm4320b_info = { 2514static const struct driver_info bcm4320b_info = {
2515 .description = "Wireless RNDIS device, BCM4320b based", 2515 .description = "Wireless RNDIS device, BCM4320b based",
2516 .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, 2516 .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT |
2517 FLAG_AVOID_UNLINK_URBS,
2517 .bind = rndis_wlan_bind, 2518 .bind = rndis_wlan_bind,
2518 .unbind = rndis_wlan_unbind, 2519 .unbind = rndis_wlan_unbind,
2519 .status = rndis_status, 2520 .status = rndis_status,
@@ -2527,7 +2528,8 @@ static const struct driver_info bcm4320b_info = {
2527 2528
2528static const struct driver_info bcm4320a_info = { 2529static const struct driver_info bcm4320a_info = {
2529 .description = "Wireless RNDIS device, BCM4320a based", 2530 .description = "Wireless RNDIS device, BCM4320a based",
2530 .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, 2531 .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT |
2532 FLAG_AVOID_UNLINK_URBS,
2531 .bind = rndis_wlan_bind, 2533 .bind = rndis_wlan_bind,
2532 .unbind = rndis_wlan_unbind, 2534 .unbind = rndis_wlan_unbind,
2533 .status = rndis_status, 2535 .status = rndis_status,
@@ -2541,7 +2543,8 @@ static const struct driver_info bcm4320a_info = {
2541 2543
2542static const struct driver_info rndis_wlan_info = { 2544static const struct driver_info rndis_wlan_info = {
2543 .description = "Wireless RNDIS device", 2545 .description = "Wireless RNDIS device",
2544 .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, 2546 .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT |
2547 FLAG_AVOID_UNLINK_URBS,
2545 .bind = rndis_wlan_bind, 2548 .bind = rndis_wlan_bind,
2546 .unbind = rndis_wlan_unbind, 2549 .unbind = rndis_wlan_unbind,
2547 .status = rndis_status, 2550 .status = rndis_status,
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index 7c17b2efba86..c642f78dd9cf 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -86,6 +86,7 @@ struct driver_info {
86 86
87#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */ 87#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
88#define FLAG_WLAN 0x0080 /* use "wlan%d" names */ 88#define FLAG_WLAN 0x0080 /* use "wlan%d" names */
89#define FLAG_AVOID_UNLINK_URBS 0x0100 /* don't unlink urbs at usbnet_stop() */
89 90
90 91
91 /* init device ... can sleep, or cause probe() failure */ 92 /* init device ... can sleep, or cause probe() failure */