net: usb: Define waitqueue head as static global variable
usbnet_terminate_urbs() defines waitqueue head as local variable.
There is a possibility that wake_up is called on this queue head
in workqueue context and usbnet_terminate_urbs() already returned
or dev->wait pointer becomes NULL while calling wake_up() from
workqueue context. Hence call wake_up() using waitqueue head
defined as static global variable.
Change-Id: I672460533d25589912a847acad2df01f193a120d
CRs-Fixed: 388724
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
Signed-off-by: Neha Pandey <nehap@codeaurora.org>
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index d26c845..1867fe2 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -89,6 +89,8 @@
static struct workqueue_struct *usbnet_wq;
+static DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup);
+
/* use ethtool to change the level for any given device */
static int msg_level = -1;
module_param (msg_level, int, 0);
@@ -664,7 +666,6 @@
// precondition: never called in_interrupt
static void usbnet_terminate_urbs(struct usbnet *dev)
{
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(unlink_wakeup);
DECLARE_WAITQUEUE(wait, current);
int temp;
@@ -1240,7 +1241,7 @@
// waiting for all pending urbs to complete?
if (dev->wait) {
if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) {
- wake_up (dev->wait);
+ wake_up(&unlink_wakeup);
}
// or are we maybe short a few urbs?