[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20210812222125.2161112-1-valentin.schneider@arm.com>
Date: Thu, 12 Aug 2021 23:21:25 +0100
From: Valentin Schneider <valentin.schneider@....com>
To: linux-kernel@...r.kernel.org
Cc: Marc Zyngier <maz@...nel.org>,
Thomas Gleixner <tglx@...utronix.de>,
Lorenzo Pieralisi <lorenzo.pieralisi@....com>,
Vincenzo Frascino <vincenzo.frascino@....com>
Subject: [PATCH irqchip-next] genirq: Let cond_unmask_eoi_irq() issue an EOI for non-masked IRQs
cond_unmask_eoi_irq() is invoked by the following flow handlers:
handle_fasteoi_irq()
handle_fasteoi_ack_irq()
handle_fasteoi_mask_irq()
handle_strict_flow_irq()
Unlike all the other handlers mentioned above, handle_strict_flow_irq()
is *not* guaranteed to have issued mask_irq() on a oneshot IRQ before
entering this function (it could be flow-masked instead).
If the primary handler of such an IRQ does not wake any threaded handler, we
will then fail to issue an EOI, which as per handle_strict_flow_irq() is a
big no-no.
Remove the check against irqd_irq_masked() in cond_unmask_eoi_irq(). The
handle_fasteoi_*() handlers remain unaffected as they unconditionally mask
oneshot IRQs, and handle_strict_flow_irq() will now issue an EOI for a
flow-masked IRQ which did not wake its thread.
Signed-off-by: Valentin Schneider <valentin.schneider@....com>
---
I was going through the stack again to refresh my memory when I found
this.
Force-threaded IRQs are unaffected as their primary handler is
irq_default_primary_handler() which unconditionally wakes the thread. Many
oneshot IRQs also have no primary handler, so they too get the
default. There *are* a handful out there with a primary handler that can
return something else than IRQ_WAKE_THREAD, so it does seem something we
wanna do.
If this needs a Fixes:, it would be:
32797fe1c8ee ("genirq: Don't mask IRQ within flow handler if IRQ is flow-masked")
---
kernel/irq/chip.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 099bc7e13d1b..80d6291d355d 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -686,13 +686,11 @@ static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip)
return;
}
/*
- * We need to unmask in the following cases:
- * - Oneshot irq which did not wake the thread (caused by a
- * spurious interrupt or a primary handler handling it
- * completely).
+ * We need to EOI and potentially unmask in case the oneshot irq did not
+ * wake the thread (caused by a spurious interrupt or a primary handler
+ * handling it completely).
*/
- if (!irqd_irq_disabled(&desc->irq_data) &&
- irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot) {
+ if (!irqd_irq_disabled(&desc->irq_data) && !desc->threads_oneshot) {
eoi_irq(desc);
unmask_irq(desc);
} else if (!(chip->flags & IRQCHIP_EOI_THREADED)) {
--
2.25.1
Powered by blists - more mailing lists