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:
@@ -56,6 +56,7 @@ void move_masked_irq(int irq)
|
|||||||
void move_native_irq(int irq)
|
void move_native_irq(int irq)
|
||||||
{
|
{
|
||||||
struct irq_desc *desc = irq_to_desc(irq);
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
|
bool masked;
|
||||||
|
|
||||||
if (likely(!(desc->status & IRQ_MOVE_PENDING)))
|
if (likely(!(desc->status & IRQ_MOVE_PENDING)))
|
||||||
return;
|
return;
|
||||||
@@ -63,8 +64,15 @@ void move_native_irq(int irq)
|
|||||||
if (unlikely(desc->status & IRQ_DISABLED))
|
if (unlikely(desc->status & IRQ_DISABLED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
desc->irq_data.chip->irq_mask(&desc->irq_data);
|
||||||
move_masked_irq(irq);
|
move_masked_irq(irq);
|
||||||
|
if (!masked)
|
||||||
desc->irq_data.chip->irq_unmask(&desc->irq_data);
|
desc->irq_data.chip->irq_unmask(&desc->irq_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user