usb: dwc3: gadget: don't request IRQs in atomic
Felipe Balbi [Thu, 27 Jun 2013 07:00:18 +0000 (10:00 +0300)]
commit b0d7ffd44ba9cd2dfbf299674418193a5f9ed21a upstream.

We cannot request an IRQ with spinlocks held
as that would trigger a sleeping inside
spinlock warning.

Reported-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

drivers/usb/dwc3/gadget.c

index f77083f..14d28d6 100644 (file)
@@ -1508,6 +1508,15 @@ static int dwc3_gadget_start(struct usb_gadget *g,
        int                     irq;
        u32                     reg;
 
+       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+       ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
+                       IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
+       if (ret) {
+               dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
+                               irq, ret);
+               goto err0;
+       }
+
        spin_lock_irqsave(&dwc->lock, flags);
 
        if (dwc->gadget_driver) {
@@ -1515,7 +1524,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
                                dwc->gadget.name,
                                dwc->gadget_driver->driver.name);
                ret = -EBUSY;
-               goto err0;
+               goto err1;
        }
 
        dwc->gadget_driver      = driver;
@@ -1551,42 +1560,38 @@ static int dwc3_gadget_start(struct usb_gadget *g,
        ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
        if (ret) {
                dev_err(dwc->dev, "failed to enable %s\n", dep->name);
-               goto err0;
+               goto err2;
        }
 
        dep = dwc->eps[1];
        ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
        if (ret) {
                dev_err(dwc->dev, "failed to enable %s\n", dep->name);
-               goto err1;
+               goto err3;
        }
 
        /* begin to receive SETUP packets */
        dwc->ep0state = EP0_SETUP_PHASE;
        dwc3_ep0_out_start(dwc);
 
-       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-       ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
-                       IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
-       if (ret) {
-               dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
-                               irq, ret);
-               goto err1;
-       }
-
        dwc3_gadget_enable_irq(dwc);
 
        spin_unlock_irqrestore(&dwc->lock, flags);
 
        return 0;
 
-err1:
+err3:
        __dwc3_gadget_ep_disable(dwc->eps[0]);
 
-err0:
+err2:
        dwc->gadget_driver = NULL;
+
+err1:
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       free_irq(irq, dwc);
+
+err0:
        return ret;
 }
 
@@ -1600,9 +1605,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
        spin_lock_irqsave(&dwc->lock, flags);
 
        dwc3_gadget_disable_irq(dwc);
-       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-       free_irq(irq, dwc);
-
        __dwc3_gadget_ep_disable(dwc->eps[0]);
        __dwc3_gadget_ep_disable(dwc->eps[1]);
 
@@ -1610,6 +1612,9 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
 
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+       free_irq(irq, dwc);
+
        return 0;
 }