Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i3c: master: svc: fix ibi may not return mandatory data byte

MSTATUS[RXPEND] is only updated after the data transfer cycle started. This
creates an issue when the I3C clock is slow, and the CPU is running fast
enough that MSTATUS[RXPEND] may not be updated when the code reaches
checking point. As a result, mandatory data can be missed.

Add a wait for MSTATUS[COMPLETE] to ensure that all mandatory data is
already in FIFO. It also works without mandatory data.

Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver")
Cc: <stable@vger.kernel.org>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
Link: https://lore.kernel.org/r/20231023161658.3890811-4-Frank.Li@nxp.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>

authored by

Frank Li and committed by
Alexandre Belloni
c85e209b 5e5e3c92

+8
+8
drivers/i3c/master/svc-i3c-master.c
··· 333 333 struct i3c_ibi_slot *slot; 334 334 unsigned int count; 335 335 u32 mdatactrl; 336 + int ret, val; 336 337 u8 *buf; 337 338 338 339 slot = i3c_generic_ibi_get_free_slot(data->ibi_pool); ··· 342 341 343 342 slot->len = 0; 344 343 buf = slot->data; 344 + 345 + ret = readl_relaxed_poll_timeout(master->regs + SVC_I3C_MSTATUS, val, 346 + SVC_I3C_MSTATUS_COMPLETE(val), 0, 1000); 347 + if (ret) { 348 + dev_err(master->dev, "Timeout when polling for COMPLETE\n"); 349 + return ret; 350 + } 345 351 346 352 while (SVC_I3C_MSTATUS_RXPEND(readl(master->regs + SVC_I3C_MSTATUS)) && 347 353 slot->len < SVC_I3C_FIFO_SIZE) {