usb: dwc: fix inconsistent lock state
Lockdep gives this splat during boot:
[ 4.136748] =================================
[ 4.145487] [ INFO: inconsistent lock state ]
[ 4.154157] 3.16.1+ #12 Not tainted
[ 4.161852] ---------------------------------
[ 4.170459] inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage.
[ 4.180776] khubd/18 [HC0[0]:SC0[0]:HE1:SE1] takes:
[ 4.189971] (&((spinlock_t *)hcd->lock)->rlock){?.-...}, at: [<c0351490>] dwc_otg_hcd_qh_free+0x18/0xcc
[ 4.204074] {IN-HARDIRQ-W} state was registered at:
[ 4.213359] [<c04a8680>] _raw_spin_lock+0x40/0x50
[ 4.222743] [<c033f010>] dwc_otg_handle_common_intr+0x44/0xd90
[ 4.233133] [<c03333c8>] dwc_otg_common_irq+0xc/0x18
[ 4.242739] [<c00634d4>] handle_irq_event_percpu+0x34/0x150
[ 4.252955] [<c006362c>] handle_irq_event+0x3c/0x5c
[ 4.262395] [<c0065984>] handle_level_irq+0x8c/0x130
[ 4.271972] [<c0062e40>] generic_handle_irq+0x28/0x40
[ 4.281489] [<c000e96c>] handle_IRQ+0x30/0x84
[ 4.290442] [<c04a9698>] __irq_svc+0x38/0xd0
[ 4.299164] [<c0357194>] DWC_MODIFY_REG32+0x64/0x84
[ 4.308613] [<c0333af4>] dwc_otg_driver_probe+0x720/0x7a8
[ 4.318523] [<c02daab0>] platform_drv_probe+0x18/0x48
[ 4.328141] [<c02d926c>] really_probe+0x68/0x200
[ 4.337334] [<c02d94f8>] __driver_attach+0xa0/0xa4
[ 4.346592] [<c02d7998>] bus_for_each_dev+0x60/0x94
[ 4.355998] [<c02d8b70>] bus_add_driver+0x140/0x1ec
[ 4.365262] [<c02d9b18>] driver_register+0x78/0xf8
[ 4.374561] [<c065e0f4>] dwc_otg_driver_init+0x58/0x114
[ 4.384271] [<c00086a4>] do_one_initcall+0x80/0x1cc
[ 4.393661] [<c0646c94>] kernel_init_freeable+0xf0/0x1b0
[ 4.403501] [<c049d83c>] kernel_init+0x8/0xec
[ 4.412308] [<c000e128>] ret_from_fork+0x14/0x2c
[ 4.421444] irq event stamp: 2351
[ 4.428928] hardirqs last enabled at (2351): [<c04a89b8>] _raw_spin_unlock_irqrestore+0x7c/0x94
[ 4.442100] hardirqs last disabled at (2350): [<c04a87a0>] _raw_spin_lock_irqsave+0x1c/0x64
[ 4.454802] softirqs last enabled at (2320): [<c0023b94>] __do_softirq+0x1ac/0x26c
[ 4.466739] softirqs last disabled at (2297): [<c0023f80>] irq_exit+0xac/0x100
[ 4.478260]
[ 4.478260] other info that might help us debug this:
[ 4.493215] Possible unsafe locking scenario:
[ 4.493215]
[ 4.507451] CPU0
[ 4.513932] ----
[ 4.520505] lock(&((spinlock_t *)hcd->lock)->rlock);
[ 4.529767] <Interrupt>
[ 4.536515] lock(&((spinlock_t *)hcd->lock)->rlock);
[ 4.545951]
[ 4.545951] *** DEADLOCK ***
[ 4.545951]
[ 4.564132] 3 locks held by khubd/18:
[ 4.571884] #0: (&dev->mutex){......}, at: [<c0321da8>] hub_thread+0x98/0x1000
[ 4.583536] #1: (&port_dev->status_lock){+.+.+.}, at: [<c032234c>] hub_thread+0x63c/0x1000
[ 4.596241] #2: (&bus->usb_address0_mutex){+.+.+.}, at: [<c031f164>] hub_port_init+0x5c/0xb24
[ 4.609307]
[ 4.609307] stack backtrace:
[ 4.621705] CPU: 0 PID: 18 Comm: khubd Not tainted 3.16.1+ #12
[ 4.631643] [<c00137e4>] (unwind_backtrace) from [<c0011530>] (show_stack+0x10/0x14)
[ 4.643580] [<c0011530>] (show_stack) from [<c049f650>] (print_usage_bug+0x240/0x2b0)
[ 4.655608] [<c049f650>] (print_usage_bug) from [<c0057a24>] (mark_lock+0x1d0/0x67c)
[ 4.667527] [<c0057a24>] (mark_lock) from [<c0058a10>] (__lock_acquire+0x5d4/0x1ae0)
[ 4.679551] [<c0058a10>] (__lock_acquire) from [<c005a6c8>] (lock_acquire+0x6c/0x8c)
[ 4.691610] [<c005a6c8>] (lock_acquire) from [<c04a8680>] (_raw_spin_lock+0x40/0x50)
[ 4.703584] [<c04a8680>] (_raw_spin_lock) from [<c0351490>] (dwc_otg_hcd_qh_free+0x18/0xcc)
[ 4.716305] [<c0351490>] (dwc_otg_hcd_qh_free) from [<c034a60c>] (dwc_otg_hcd_endpoint_disable+0x9c/0xb0)
[ 4.730246] [<c034a60c>] (dwc_otg_hcd_endpoint_disable) from [<c034d650>] (endpoint_disable+0x18/0x24)
[ 4.743919] [<c034d650>] (endpoint_disable) from [<c031e0d0>] (usb_ep0_reinit+0x14/0x38)
[ 4.756379] [<c031e0d0>] (usb_ep0_reinit) from [<c031f3ac>] (hub_port_init+0x2a4/0xb24)
[ 4.768652] [<c031f3ac>] (hub_port_init) from [<c0322360>] (hub_thread+0x650/0x1000)
[ 4.780824] [<c0322360>] (hub_thread) from [<c003ec3c>] (kthread+0xc8/0xe4)
[ 4.792231] [<c003ec3c>] (kthread) from [<c000e128>] (ret_from_fork+0x14/0x2c)
This splat shows that the hcd spinlock is used from hard irq context and also from
process context with irqs on.
To fix this, use spinlock_irqsave instead of spinlock in dwc_otg_hcd_qh_free.
Signed-off-by:
Kari Suvanto <karis79@gmail.com>
Loading
Please sign in to comment