summaryrefslogtreecommitdiff
path: root/kernel/irq/chip.c
diff options
context:
space:
mode:
authorMarc Zyngier <maz@kernel.org>2023-06-16 12:23:55 +0100
committerMarc Zyngier <maz@kernel.org>2023-06-16 12:23:55 +0100
commitd59b553fefa940f91aa96ff898267acc58e59e6b (patch)
treea90e8d15de4909882b67a290ac22cb33dff28535 /kernel/irq/chip.c
parent2b384e01fd12275b93ba777b40ec8b868c965e2d (diff)
parent8f4b589595d01f882d63d21efe15af4a5ad7c59b (diff)
Merge branch irq/lpi-resend into irq/irqchip-next
* irq/lpi-resend: : . : Patch series from James Gowans, working around an issue with : GICv3 LPIs that can fire concurrently on multiple CPUs. : . irqchip/gic-v3-its: Enable RESEND_WHEN_IN_PROGRESS for LPIs genirq: Allow fasteoi handler to resend interrupts on concurrent handling genirq: Expand doc for PENDING and REPLAY flags genirq: Use BIT() for the IRQD_* state flags Signed-off-by: Marc Zyngier <maz@kernel.org>
Diffstat (limited to 'kernel/irq/chip.c')
-rw-r--r--kernel/irq/chip.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 49e7bc871fec..57cd8f475302 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -692,8 +692,16 @@ void handle_fasteoi_irq(struct irq_desc *desc)
raw_spin_lock(&desc->lock);
- if (!irq_may_run(desc))
+ /*
+ * When an affinity change races with IRQ handling, the next interrupt
+ * can arrive on the new CPU before the original CPU has completed
+ * handling the previous one - it may need to be resent.
+ */
+ if (!irq_may_run(desc)) {
+ if (irqd_needs_resend_when_in_progress(&desc->irq_data))
+ desc->istate |= IRQS_PENDING;
goto out;
+ }
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
@@ -715,6 +723,12 @@ void handle_fasteoi_irq(struct irq_desc *desc)
cond_unmask_eoi_irq(desc, chip);
+ /*
+ * When the race described above happens this will resend the interrupt.
+ */
+ if (unlikely(desc->istate & IRQS_PENDING))
+ check_irq_resend(desc, false);
+
raw_spin_unlock(&desc->lock);
return;
out: