From patchwork Thu Jul 30 16:41:20 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jussi Kivilinna X-Patchwork-Id: 38354 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n6UGmLET016920 for ; Thu, 30 Jul 2009 16:48:22 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751899AbZG3Qro (ORCPT ); Thu, 30 Jul 2009 12:47:44 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751441AbZG3Qrg (ORCPT ); Thu, 30 Jul 2009 12:47:36 -0400 Received: from sypressi.dnainternet.net ([83.102.40.135]:43265 "EHLO sypressi.dnainternet.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751006AbZG3Qrf (ORCPT ); Thu, 30 Jul 2009 12:47:35 -0400 X-Greylist: delayed 372 seconds by postgrey-1.27 at vger.kernel.org; Thu, 30 Jul 2009 12:47:34 EDT Received: from localhost (localhost [127.0.0.1]) by sypressi.dnainternet.net (Postfix) with ESMTP id AB842C7760; Thu, 30 Jul 2009 19:37:53 +0300 (EEST) X-Virus-Scanned: Debian amavisd-new at !change-mydomain-variable!.example.com X-Spam-Flag: NO X-Spam-Score: -2.098 X-Spam-Level: X-Spam-Status: No, score=-2.098 tagged_above=-9999 required=7 tests=[AWL=0.214, BAYES_00=-2.312] Received: from sypressi.dnainternet.net ([83.102.40.135]) by localhost (sypressi.dnainternet.net [127.0.0.1]) (amavisd-new, port 10041) with ESMTP id sUDu79yJR5Fs; Thu, 30 Jul 2009 19:37:53 +0300 (EEST) Received: from kirsikkapuu.dnainternet.net (kirsikkapuu.dnainternet.net [83.102.40.214]) by sypressi.dnainternet.net (Postfix) with ESMTP id 60229C605A; Thu, 30 Jul 2009 19:37:53 +0300 (EEST) Received: from fate.lan (dyn2-85-23-163-166.psoas.suomi.net [85.23.163.166]) by kirsikkapuu.dnainternet.net (Postfix) with ESMTP id 6CE242BAD3; Thu, 30 Jul 2009 19:41:21 +0300 (EEST) From: Jussi Kivilinna Subject: [PATCH 01/10] usbnet: allow "minidriver" to prevent urb unlinking on usbnet_stop To: linux-wireless@vger.kernel.org Cc: linville@tuxdriver.com, Jussi Kivilinna , David Brownell Date: Thu, 30 Jul 2009 19:41:20 +0300 Message-ID: <20090730164120.28317.53313.stgit@fate.lan> User-Agent: StGIT/0.14.2 MIME-Version: 1.0 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org 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 Cc: David Brownell --- drivers/net/usb/usbnet.c | 32 ++++++++++++++++++-------------- drivers/net/wireless/rndis_wlan.c | 9 ++++++--- include/linux/usb/usbnet.h | 1 + 3 files changed, 25 insertions(+), 17 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 25e435c..af1fe46 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -601,21 +601,25 @@ int usbnet_stop (struct net_device *net) info->description); } - // ensure there are no more active urbs - add_wait_queue (&unlink_wakeup, &wait); - dev->wait = &unlink_wakeup; - temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq); - - // maybe wait for deletions to finish. - while (!skb_queue_empty(&dev->rxq) - && !skb_queue_empty(&dev->txq) - && !skb_queue_empty(&dev->done)) { - msleep(UNLINK_TIMEOUT_MS); - if (netif_msg_ifdown (dev)) - devdbg (dev, "waited for %d urb completions", temp); + if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) { + /* ensure there are no more active urbs */ + add_wait_queue(&unlink_wakeup, &wait); + dev->wait = &unlink_wakeup; + temp = unlink_urbs(dev, &dev->txq) + + unlink_urbs(dev, &dev->rxq); + + /* maybe wait for deletions to finish. */ + while (!skb_queue_empty(&dev->rxq) + && !skb_queue_empty(&dev->txq) + && !skb_queue_empty(&dev->done)) { + msleep(UNLINK_TIMEOUT_MS); + if (netif_msg_ifdown(dev)) + devdbg(dev, "waited for %d urb completions", + temp); + } + dev->wait = NULL; + remove_wait_queue(&unlink_wakeup, &wait); } - dev->wait = NULL; - remove_wait_queue (&unlink_wakeup, &wait); usb_kill_urb(dev->interrupt); diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 09c0702..76c5ec6 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) static const struct driver_info bcm4320b_info = { .description = "Wireless RNDIS device, BCM4320b based", - .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, + .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT | + FLAG_AVOID_UNLINK_URBS, .bind = rndis_wlan_bind, .unbind = rndis_wlan_unbind, .status = rndis_status, @@ -2527,7 +2528,8 @@ static const struct driver_info bcm4320b_info = { static const struct driver_info bcm4320a_info = { .description = "Wireless RNDIS device, BCM4320a based", - .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, + .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT | + FLAG_AVOID_UNLINK_URBS, .bind = rndis_wlan_bind, .unbind = rndis_wlan_unbind, .status = rndis_status, @@ -2541,7 +2543,8 @@ static const struct driver_info bcm4320a_info = { static const struct driver_info rndis_wlan_info = { .description = "Wireless RNDIS device", - .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, + .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT | + FLAG_AVOID_UNLINK_URBS, .bind = rndis_wlan_bind, .unbind = rndis_wlan_unbind, .status = rndis_status, diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index 7c17b2e..c642f78 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -86,6 +86,7 @@ struct driver_info { #define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */ #define FLAG_WLAN 0x0080 /* use "wlan%d" names */ +#define FLAG_AVOID_UNLINK_URBS 0x0100 /* don't unlink urbs at usbnet_stop() */ /* init device ... can sleep, or cause probe() failure */