aboutsummaryrefslogtreecommitdiff
path: root/tools/perf/util/trace-event-scripting.c
diff options
context:
space:
mode:
authorThomas Gleixner <[email protected]>2017-07-11 23:41:52 +0200
committerThomas Gleixner <[email protected]>2017-07-12 10:14:42 +0200
commit19d39a3810e7032f311ef83effdac40339b9d022 (patch)
tree5a7ee202d0b6eb8e8f34df2f9fb5536007acb4c1 /tools/perf/util/trace-event-scripting.c
parentc5c601c4295f89368f4a304cb3ae4aebdf80db22 (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/util/trace-event-scripting.c')
0 files changed, 0 insertions, 0 deletions