| From b0d7ffd44ba9cd2dfbf299674418193a5f9ed21a Mon Sep 17 00:00:00 2001 |
| From: Felipe Balbi <balbi@ti.com> |
| Date: Thu, 27 Jun 2013 10:00:18 +0300 |
| Subject: usb: dwc3: gadget: don't request IRQs in atomic |
| |
| From: Felipe Balbi <balbi@ti.com> |
| |
| 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 | 39 ++++++++++++++++++++++----------------- |
| 1 file changed, 22 insertions(+), 17 deletions(-) |
| |
| --- a/drivers/usb/dwc3/gadget.c |
| +++ b/drivers/usb/dwc3/gadget.c |
| @@ -1508,6 +1508,15 @@ static int dwc3_gadget_start(struct usb_ |
| 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_ |
| 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_ |
| 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_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_g |
| |
| spin_unlock_irqrestore(&dwc->lock, flags); |
| |
| + irq = platform_get_irq(to_platform_device(dwc->dev), 0); |
| + free_irq(irq, dwc); |
| + |
| return 0; |
| } |
| |