Skip to content

Commit f36c1f9

Browse files
Jisheng Zhangbbrezillon
authored andcommitted
i3c: master: dw: fix deadlock
In dw_i3c_master_irq_handler(), we already have gotten &master->xferqueue.lock, if we try to get the same lock again in dw_i3c_master_dequeue_xfer(), deadlock happens. We fix this issue by introduing dw_i3c_master_dequeue_xfer_locked() which does all what dw_i3c_master_dequeue_xfer() does without trying to lock &master->xferqueue.lock. Signed-off-by: Jisheng Zhang <Jisheng.Zhang@synaptics.com> Acked-by: Vitor Soares <vitor.soares@synopsys.com> Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
1 parent 093c61b commit f36c1f9

File tree

1 file changed

+12
-6
lines changed

1 file changed

+12
-6
lines changed

drivers/i3c/master/dw-i3c-master.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -419,12 +419,9 @@ static void dw_i3c_master_enqueue_xfer(struct dw_i3c_master *master,
419419
spin_unlock_irqrestore(&master->xferqueue.lock, flags);
420420
}
421421

422-
static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master,
423-
struct dw_i3c_xfer *xfer)
422+
static void dw_i3c_master_dequeue_xfer_locked(struct dw_i3c_master *master,
423+
struct dw_i3c_xfer *xfer)
424424
{
425-
unsigned long flags;
426-
427-
spin_lock_irqsave(&master->xferqueue.lock, flags);
428425
if (master->xferqueue.cur == xfer) {
429426
u32 status;
430427

@@ -439,6 +436,15 @@ static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master,
439436
} else {
440437
list_del_init(&xfer->node);
441438
}
439+
}
440+
441+
static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master,
442+
struct dw_i3c_xfer *xfer)
443+
{
444+
unsigned long flags;
445+
446+
spin_lock_irqsave(&master->xferqueue.lock, flags);
447+
dw_i3c_master_dequeue_xfer_locked(master, xfer);
442448
spin_unlock_irqrestore(&master->xferqueue.lock, flags);
443449
}
444450

@@ -494,7 +500,7 @@ static void dw_i3c_master_end_xfer_locked(struct dw_i3c_master *master, u32 isr)
494500
complete(&xfer->comp);
495501

496502
if (ret < 0) {
497-
dw_i3c_master_dequeue_xfer(master, xfer);
503+
dw_i3c_master_dequeue_xfer_locked(master, xfer);
498504
writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_RESUME,
499505
master->regs + DEVICE_CTRL);
500506
}

0 commit comments

Comments
 (0)