genirq: Prevent irq storm on migration

move_native_irq() masks and unmasks the interrupt line
unconditionally, but the interrupt line might be masked due to a
threaded oneshot handler in progress. Unmasking the line in that case
can lead to interrupt storms. Observed on PREEMPT_RT.

Originally-from: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@kernel.org
This commit is contained in:
Thomas Gleixner 2011-01-28 08:47:15 +01:00
parent afe8a88755
commit f1a06390d0

View file

@ -56,6 +56,7 @@ void move_masked_irq(int irq)
void move_native_irq(int irq)
{
struct irq_desc *desc = irq_to_desc(irq);
bool masked;
if (likely(!(desc->status & IRQ_MOVE_PENDING)))
return;
@ -63,8 +64,15 @@ void move_native_irq(int irq)
if (unlikely(desc->status & IRQ_DISABLED))
return;
desc->irq_data.chip->irq_mask(&desc->irq_data);
/*
* Be careful vs. already masked interrupts. If this is a
* threaded interrupt with ONESHOT set, we can end up with an
* interrupt storm.
*/
masked = desc->status & IRQ_MASKED;
if (!masked)
desc->irq_data.chip->irq_mask(&desc->irq_data);
move_masked_irq(irq);
desc->irq_data.chip->irq_unmask(&desc->irq_data);
if (!masked)
desc->irq_data.chip->irq_unmask(&desc->irq_data);
}