diff options
author | Peter Chen <peter.chen@freescale.com> | 2013-10-08 10:30:17 +0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-10-11 16:25:15 -0700 |
commit | 65b2fb32b5ce53e103e026b6f95b784c5921cd2e (patch) | |
tree | 390f132f35f870e6d87825a04f8ba0053ceeef18 | |
parent | a3aee3687d4707a96fa49da2914dcced18760c29 (diff) |
usb: chipidea: udc: Fix calling spin_lock_irqsave at sleep context
Fixing the below dump:
root@freescale ~$ modprobe g_serial
g_serial gadget: Gadget Serial v2.4
g_serial gadget: g_serial ready
BUG: sleeping function called from invalid context at /home/b29397/work/projects/upstream/usb/usb/drivers/base/power/runtime.c:952
in_atomic(): 1, irqs_disabled(): 128, pid: 805, name: modprobe
2 locks held by modprobe/805:
#0: (udc_lock){+.+.+.}, at: [<7f000a74>] usb_gadget_probe_driver+0x44/0xb4 [udc_core]
#1: (&(&ci->lock)->rlock){......}, at: [<7f033488>] ci_udc_start+0x94/0x110 [ci_hdrc]
irq event stamp: 3878
hardirqs last enabled at (3877): [<806b6720>] _raw_spin_unlock_irqrestore+0x40/0x6c
hardirqs last disabled at (3878): [<806b6474>] _raw_spin_lock_irqsave+0x2c/0xa8
softirqs last enabled at (3872): [<8002ec0c>] __do_softirq+0x1c8/0x2e8
softirqs last disabled at (3857): [<8002f180>] irq_exit+0xbc/0x110
CPU: 0 PID: 805 Comm: modprobe Not tainted 3.11.0-next-20130910+ #85
[<80016b94>] (unwind_backtrace+0x0/0xf8) from [<80012e0c>] (show_stack+0x20/0x24)
[<80012e0c>] (show_stack+0x20/0x24) from [<806af554>] (dump_stack+0x9c/0xc4)
[<806af554>] (dump_stack+0x9c/0xc4) from [<8005940c>] (__might_sleep+0xf4/0x134)
[<8005940c>] (__might_sleep+0xf4/0x134) from [<803a04a4>] (__pm_runtime_resume+0x94/0xa0)
[<803a04a4>] (__pm_runtime_resume+0x94/0xa0) from [<7f0334a4>] (ci_udc_start+0xb0/0x110 [ci_hdrc])
[<7f0334a4>] (ci_udc_start+0xb0/0x110 [ci_hdrc]) from [<7f0009b4>] (udc_bind_to_driver+0x5c/0xd8 [udc_core])
[<7f0009b4>] (udc_bind_to_driver+0x5c/0xd8 [udc_core]) from [<7f000ab0>] (usb_gadget_probe_driver+0x80/0xb4 [udc_core])
[<7f000ab0>] (usb_gadget_probe_driver+0x80/0xb4 [udc_core]) from [<7f008618>] (usb_composite_probe+0xac/0xd8 [libcomposite])
[<7f008618>] (usb_composite_probe+0xac/0xd8 [libcomposite]) from [<7f04b168>] (init+0x8c/0xb4 [g_serial])
[<7f04b168>] (init+0x8c/0xb4 [g_serial]) from [<800088e8>] (do_one_initcall+0x108/0x16c)
[<800088e8>] (do_one_initcall+0x108/0x16c) from [<8008e518>] (load_module+0x1b00/0x20a4)
[<8008e518>] (load_module+0x1b00/0x20a4) from [<8008eba8>] (SyS_init_module+0xec/0x100)
[<8008eba8>] (SyS_init_module+0xec/0x100) from [<8000ec40>] (ret_fast_syscall+0x0/0x48)
Signed-off-by: Peter Chen <peter.chen@freescale.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/usb/chipidea/udc.c | 7 |
1 files changed, 3 insertions, 4 deletions
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 5c5e9124872f..b34c81969cba 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1636,23 +1636,22 @@ static int ci_udc_start(struct usb_gadget *gadget, retval = usb_ep_enable(&ci->ep0in->ep); if (retval) return retval; - spin_lock_irqsave(&ci->lock, flags); ci->driver = driver; pm_runtime_get_sync(&ci->gadget.dev); if (ci->vbus_active) { + spin_lock_irqsave(&ci->lock, flags); hw_device_reset(ci, USBMODE_CM_DC); } else { pm_runtime_put_sync(&ci->gadget.dev); - goto done; + return retval; } retval = hw_device_state(ci, ci->ep0out->qh.dma); + spin_unlock_irqrestore(&ci->lock, flags); if (retval) pm_runtime_put_sync(&ci->gadget.dev); - done: - spin_unlock_irqrestore(&ci->lock, flags); return retval; } |