[PATCH v2] irqchip/renesas-rzg2l: Fix loss of interrupt

From: Biju

Date: Tue Aug 18 2026 - 07:09:52 EST


From: Biju Das <biju.das.jz@xxxxxxxxxxxxxx>

rzg2l_clear_irq_int() and rzg2l_clear_tint_int() perform a
read-modify-write on the ISCR/TSCR status registers to clear the bit
for the interrupt just handled. Since these registers are
write-0-to-clear per bit, this is racy: if another interrupt's status
bit gets set between the read and the write, that bit is written back
as 0 by the software-constructed value, clearing an interrupt that
hasn't been serviced yet and losing it. This can be reproduced by
triggering multiple interrupts at once, e.g.:

gpioset -c gpiochip0 355=0 353=0 328=0 352=0

Fix this by writing back only the bit being cleared, with all other
bits set to 1, instead of read-modify-writing the whole register.
Since 1-bits are left unchanged by hardware, concurrently-set status
bits for other interrupts are preserved.

Fixes: 3fed09559cd8 ("irqchip: Add RZ/G2L IA55 Interrupt Controller driver")
Signed-off-by: Biju Das <biju.das.jz@xxxxxxxxxxxxxx>
---
v1->v2:
* Updated the commit description.
---
drivers/irqchip/irq-renesas-rzg2l.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
index f6b2e69a2f4e..b3774f82855a 100644
--- a/drivers/irqchip/irq-renesas-rzg2l.c
+++ b/drivers/irqchip/irq-renesas-rzg2l.c
@@ -161,7 +161,7 @@ static void rzg2l_clear_irq_int(struct rzg2l_irqc_priv *priv, unsigned int hwirq
* falling/rising-edge.
*/
if ((iscr & bit) && (iitsr & IITSR_IITSEL_MASK(hw_irq))) {
- writel_relaxed(iscr & ~bit, priv->base + ISCR);
+ writel_relaxed(~bit, priv->base + ISCR);
/*
* Enforce that the posted write is flushed to prevent that the
* just handled interrupt is raised again.
@@ -177,7 +177,7 @@ static void rzg2l_clear_tint_int(struct rzg2l_irqc_priv *priv, unsigned int hwir

reg = readl_relaxed(priv->base + TSCR);
if (reg & bit) {
- writel_relaxed(reg & ~bit, priv->base + TSCR);
+ writel_relaxed(~bit, priv->base + TSCR);
/*
* Enforce that the posted write is flushed to prevent that the
* just handled interrupt is raised again.
--
2.43.0