]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
i3c: master: svc: Fix missed IBI after false SLVSTART on NPCM845
authorStanley Chu <yschu@nuvoton.com>
Mon, 13 Apr 2026 00:50:39 +0000 (08:50 +0800)
committerAlexandre Belloni <alexandre.belloni@bootlin.com>
Thu, 30 Apr 2026 10:00:36 +0000 (12:00 +0200)
The NPCM845 I3C controller may raise a false SLVSTART interrupt. The
handler first latches MSTATUS and then clears SLVSTART. If a real IBI
request arrives after the handler latches MSTATUS but before it clears
the SLVSTART interrupt status, HW sets the SLVREQ state. However, the
handler still relies on the stale MSTATUS snapshot, returns early, and
misses the real IBI. No further interrupt is generated for this pending
IBI.

Re-read MSTATUS to obtain the latest state and avoid missing a real IBI
due to this race condition.

Fixes: 4dd12e944f07 ("i3c: master: svc: Fix npcm845 invalid slvstart event")
Signed-off-by: Stanley Chu <yschu@nuvoton.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260413005040.1211107-2-yschu@nuvoton.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
drivers/i3c/master/svc-i3c-master.c

index e2d99a3ac07da753fb3f7b2b74012fc29c2c09ed..63063741fbd12978d12483cc361ca499053761af 100644 (file)
@@ -672,10 +672,18 @@ static irqreturn_t svc_i3c_master_irq_handler(int irq, void *dev_id)
        /* Clear the interrupt status */
        writel(SVC_I3C_MINT_SLVSTART, master->regs + SVC_I3C_MSTATUS);
 
-       /* Ignore the false event */
-       if (svc_has_quirk(master, SVC_I3C_QUIRK_FALSE_SLVSTART) &&
-           !SVC_I3C_MSTATUS_STATE_SLVREQ(active))
-               return IRQ_HANDLED;
+       if (svc_has_quirk(master, SVC_I3C_QUIRK_FALSE_SLVSTART)) {
+               /*
+                * Re-read MSTATUS to obtain the latest state and avoid
+                * missing an IBI that arrives after MSTATUS is latched
+                * but before SLVSTART is cleared.
+                */
+               active = readl(master->regs + SVC_I3C_MSTATUS);
+
+               /* Ignore the false event */
+               if (!SVC_I3C_MSTATUS_STATE_SLVREQ(active))
+                       return IRQ_HANDLED;
+       }
 
        /*
         * The SDA line remains low until the request is processed.