[PATCH] irqchip/renesas-rzg2l: Fix loss of interrupt
Biju <[email protected]>
| Newsgroups | org.kernel.vger.linux-renesas-soc,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Biju Das <[email protected]> Read modify write on rzg2l_clear_{tint,irq}_int() is causing loss of interrupts when multiple interrupts are triggered, for example with: gpioset -c gpiochip0 355=0 353=0 328=0 352=0 The ISCR/TSCR status registers are write-1-to-clear per bit, so any bit written as 0 is left unchanged by hardware. The current code reads the register, clears only the handled bit in software, and writes back the whole value. If another interrupt's status bit gets set between the read and the write, that set bit is written back as 1, clearing an interrupt that hasn't been serviced yet, so it gets lost. Fix this by writing back only the bit being cleared (all other bits as 0) instead of read-modify-writing the whole register, so that concurrently-set status bits for other interrupts are left intact. Fixes: 3fed09559cd8 ("irqchip: Add RZ/G2L IA55 Interrupt Controller driver") Signed-off-by: Biju Das <[email protected]> --- 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