diff options
author | Thomas Gleixner <[email protected]> | 2017-07-11 23:41:52 +0200 |
---|---|---|
committer | Thomas Gleixner <[email protected]> | 2017-07-12 10:14:42 +0200 |
commit | 19d39a3810e7032f311ef83effdac40339b9d022 (patch) | |
tree | 5a7ee202d0b6eb8e8f34df2f9fb5536007acb4c1 /tools/perf/scripts/python/export-to-postgresql.py | |
parent | c5c601c4295f89368f4a304cb3ae4aebdf80db22 (diff) |
genirq: Keep chip buslock across irq_request/release_resources()
Moving the irq_request/release_resources() callbacks out of the spinlocked,
irq disabled and bus locked region, unearthed an interesting abuse of the
irq_bus_lock/irq_bus_sync_unlock() callbacks.
The OMAP GPIO driver does merily power management inside of them. The
irq_request_resources() callback of this GPIO irqchip calls a function
which reads a GPIO register. That read aborts now because the clock of the
GPIO block is not magically enabled via the irq_bus_lock() callback.
Move the callbacks under the bus lock again to prevent this. In the
free_irq() path this requires to drop the bus_lock before calling
synchronize_irq() and reaquiring it before calling the
irq_release_resources() callback.
The bus lock can't be held because:
1) The data which has been changed between bus_lock/un_lock is cached in
the irq chip driver private data and needs to go out to the irq chip
via the slow bus (usually SPI or I2C) before calling
synchronize_irq().
That's the reason why this bus_lock/unlock magic exists in the first
place, as you cannot do SPI/I2C transactions while holding desc->lock
with interrupts disabled.
2) synchronize_irq() will actually deadlock, if there is a handler on
flight. These chips use threaded handlers for obvious reasons, as
they allow to do SPI/I2C communication. When the threaded handler
returns then bus_lock needs to be taken in irq_finalize_oneshot() as
we need to talk to the actual irq chip once more. After that the
threaded handler is marked done, which makes synchronize_irq() return.
So if we hold bus_lock accross the synchronize_irq() call, the
handler cannot mark itself done because it blocks on the bus
lock. That in turn makes synchronize_irq() wait forever on the
threaded handler to complete....
Add the missing unlock of desc->request_mutex in the error path of
__free_irq() and add a bunch of comments to explain the locking and
protection rules.
Fixes: 46e48e257360 ("genirq: Move irq resource handling out of spinlocked region")
Reported-and-tested-by: Sebastian Reichel <[email protected]>
Reported-and-tested-by: Tony Lindgren <[email protected]>
Reported-by: Pavel Machek <[email protected]>
Signed-off-by: Thomas Gleixner <[email protected]>
Not-longer-ranted-at-by: Linus Torvalds <[email protected]>
Cc: Linus Walleij <[email protected]>
Cc: Grygorii Strashko <[email protected]>
Cc: Marc Zyngier <[email protected]>
Diffstat (limited to 'tools/perf/scripts/python/export-to-postgresql.py')
0 files changed, 0 insertions, 0 deletions