diff options
author | Pavel Emelianov <xemul@openvz.org> | 2006-11-10 12:27:56 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-11-13 07:40:43 -0800 |
commit | f72fa707604c015a6625e80f269506032d5430dc (patch) | |
tree | d7701d7a0e6fef020e78f690041486a052bc9bb3 /kernel/kexec.c | |
parent | 0130b0b32ee53dc7add773fcea984f6a26ef1da3 (diff) | |
download | linux-f72fa707604c015a6625e80f269506032d5430dc.tar.gz linux-f72fa707604c015a6625e80f269506032d5430dc.tar.bz2 linux-f72fa707604c015a6625e80f269506032d5430dc.zip |
[PATCH] Fix misrouted interrupts deadlocks
While testing kernel on machine with "irqpoll" option I've caught such a
lockup:
__do_IRQ()
spin_lock(&desc->lock);
desc->chip->ack(); /* IRQ is ACKed */
note_interrupt()
misrouted_irq()
handle_IRQ_event()
if (...)
local_irq_enable_in_hardirq();
/* interrupts are enabled from now */
...
__do_IRQ() /* same IRQ we've started from */
spin_lock(&desc->lock); /* LOCKUP */
Looking at misrouted_irq() code I've found that a potential deadlock like
this can also take place:
1CPU:
__do_IRQ()
spin_lock(&desc->lock); /* irq = A */
misrouted_irq()
for (i = 1; i < NR_IRQS; i++) {
spin_lock(&desc->lock); /* irq = B */
if (desc->status & IRQ_INPROGRESS) {
2CPU:
__do_IRQ()
spin_lock(&desc->lock); /* irq = B */
misrouted_irq()
for (i = 1; i < NR_IRQS; i++) {
spin_lock(&desc->lock); /* irq = A */
if (desc->status & IRQ_INPROGRESS) {
As the second lock on both CPUs is taken before checking that this irq is
being handled in another processor this may cause a deadlock. This issue
is only theoretical.
I propose the attached patch to fix booth problems: when trying to handle
misrouted IRQ active desc->lock may be unlocked.
Acked-by: Ingo Molnar <mingo@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/kexec.c')
0 files changed, 0 insertions, 0 deletions