Skip to content

Commit f36f662

Browse files
nxpfranklialexandrebelloni
authored andcommitted
i3c: master: svc: use spin_lock_irqsave at svc_i3c_master_ibi_work()
According to I3C spec ver 1.1, 09-Jun-2021, section 5.1.2.5: The I3C Controller shall hold SCL low while the Bus is in ACK/NACK Phase of I3C/I2C transfer. But maximum stall time is 100us. The IRQs have to be disabled to prevent schedule during the whole I3C transaction, otherwise, the I3C bus timeout may happen if any irq or schedule happen during transaction. Replace mutex with spin_lock_irqsave() to avoid stalling SCL more than 100us. Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com> Signed-off-by: Frank Li <Frank.Li@nxp.com> Link: https://lore.kernel.org/r/20241002-svc-i3c-hj-v6-4-7e6e1d3569ae@nxp.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
1 parent 6a12f56 commit f36f662

File tree

1 file changed

+12
-4
lines changed

1 file changed

+12
-4
lines changed

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,16 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
436436
u32 status, val;
437437
int ret;
438438

439-
mutex_lock(&master->lock);
439+
/*
440+
* According to I3C spec ver 1.1, 09-Jun-2021, section 5.1.2.5:
441+
*
442+
* The I3C Controller shall hold SCL low while the Bus is in ACK/NACK Phase of I3C/I2C
443+
* transfer. But maximum stall time is 100us. The IRQs have to be disabled to prevent
444+
* schedule during the whole I3C transaction, otherwise, the I3C bus timeout may happen if
445+
* any irq or schedule happen during transaction.
446+
*/
447+
guard(spinlock_irqsave)(&master->xferqueue.lock);
448+
440449
/*
441450
* IBIWON may be set before SVC_I3C_MCTRL_REQUEST_AUTO_IBI, causing
442451
* readl_relaxed_poll_timeout() to return immediately. Consequently,
@@ -456,8 +465,8 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
456465
master->regs + SVC_I3C_MCTRL);
457466

458467
/* Wait for IBIWON, should take approximately 100us */
459-
ret = readl_relaxed_poll_timeout(master->regs + SVC_I3C_MSTATUS, val,
460-
SVC_I3C_MSTATUS_IBIWON(val), 0, 1000);
468+
ret = readl_relaxed_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS, val,
469+
SVC_I3C_MSTATUS_IBIWON(val), 0, 100);
461470
if (ret) {
462471
dev_err(master->dev, "Timeout when polling for IBIWON\n");
463472
svc_i3c_master_emit_stop(master);
@@ -529,7 +538,6 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
529538

530539
reenable_ibis:
531540
svc_i3c_master_enable_interrupts(master, SVC_I3C_MINT_SLVSTART);
532-
mutex_unlock(&master->lock);
533541
}
534542

535543
static irqreturn_t svc_i3c_master_irq_handler(int irq, void *dev_id)

0 commit comments

Comments
 (0)