Re: [PATCH v2] irqchip/renesas-rzg2l: Fix loss of interrupt
Radu Rendec <[email protected]>
| Newsgroups | org.kernel.vger.linux-renesas-soc,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On Tue, 2026-08-18 at 12:09 +0100, Biju wrote: > From: Biju Das <[email protected]> > > 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 <[email protected]> > --- > 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. Reviewed-by: Radu Rendec <[email protected]>