Commit f1a06390 authored by Thomas Gleixner's avatar Thomas Gleixner

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: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: stable@kernel.org
parent afe8a887
...@@ -56,6 +56,7 @@ void move_masked_irq(int irq) ...@@ -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) ...@@ -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);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment