Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 38baed9

Browse files
nxpfranklialexandrebelloni
authored andcommitted
i3c: master: svc: fix invalidate IBI type and miss call client IBI handler
In an In-Band Interrupt (IBI) handle, the code logic is as follows: 1: writel(SVC_I3C_MCTRL_REQUEST_AUTO_IBI | SVC_I3C_MCTRL_IBIRESP_AUTO, master->regs + SVC_I3C_MCTRL); 2: ret = readl_relaxed_poll_timeout(master->regs + SVC_I3C_MSTATUS, val, SVC_I3C_MSTATUS_IBIWON(val), 0, 1000); ... 3: ibitype = SVC_I3C_MSTATUS_IBITYPE(status); ibiaddr = SVC_I3C_MSTATUS_IBIADDR(status); SVC_I3C_MSTATUS_IBIWON may be set before step 1. Thus, step 2 will return immediately, and the I3C controller has not sent out the 9th SCL yet. Consequently, ibitype and ibiaddr are 0, resulting in an unknown IBI type occurrence and missing call I3C client driver's IBI handler. A typical case is that SVC_I3C_MSTATUS_IBIWON is set when an IBI occurs during the controller send start frame in svc_i3c_master_xfer(). Clear SVC_I3C_MSTATUS_IBIWON before issue SVC_I3C_MCTRL_REQUEST_AUTO_IBI to fix this issue. Cc: stable@vger.kernel.org Fixes: 5e5e3c9 ("i3c: master: svc: fix wrong data return when IBI happen during start frame") Signed-off-by: Frank Li <Frank.Li@nxp.com> Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com> Link: https://lore.kernel.org/r/20240506164009.21375-3-Frank.Li@nxp.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
1 parent 7f3d633 commit 38baed9

File tree

1 file changed

+13
-3
lines changed

1 file changed

+13
-3
lines changed

drivers/i3c/master/svc-i3c-master.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,19 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
415415
int ret;
416416

417417
mutex_lock(&master->lock);
418+
/*
419+
* IBIWON may be set before SVC_I3C_MCTRL_REQUEST_AUTO_IBI, causing
420+
* readl_relaxed_poll_timeout() to return immediately. Consequently,
421+
* ibitype will be 0 since it was last updated only after the 8th SCL
422+
* cycle, leading to missed client IBI handlers.
423+
*
424+
* A typical scenario is when IBIWON occurs and bus arbitration is lost
425+
* at svc_i3c_master_priv_xfers().
426+
*
427+
* Clear SVC_I3C_MINT_IBIWON before sending SVC_I3C_MCTRL_REQUEST_AUTO_IBI.
428+
*/
429+
writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS);
430+
418431
/* Acknowledge the incoming interrupt with the AUTOIBI mechanism */
419432
writel(SVC_I3C_MCTRL_REQUEST_AUTO_IBI |
420433
SVC_I3C_MCTRL_IBIRESP_AUTO,
@@ -429,9 +442,6 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
429442
goto reenable_ibis;
430443
}
431444

432-
/* Clear the interrupt status */
433-
writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS);
434-
435445
status = readl(master->regs + SVC_I3C_MSTATUS);
436446
ibitype = SVC_I3C_MSTATUS_IBITYPE(status);
437447
ibiaddr = SVC_I3C_MSTATUS_IBIADDR(status);

0 commit comments

Comments
 (0)