aboutsummaryrefslogtreecommitdiff
path: root/drivers/i3c
diff options
context:
space:
mode:
authorGravatar Jarkko Nikula <jarkko.nikula@linux.intel.com> 2023-09-21 08:56:59 +0300
committerGravatar Alexandre Belloni <alexandre.belloni@bootlin.com> 2023-09-25 23:35:14 +0200
commit4e40642cdb621c669507d7ef098c93ff98e8747c (patch)
tree79dca19ca8c84adf4b12ef78712cd68b89e1f07a /drivers/i3c
parenti3c: mipi-i3c-hci: Set ring start request together with enable (diff)
downloadlinux-4e40642cdb621c669507d7ef098c93ff98e8747c.tar.gz
linux-4e40642cdb621c669507d7ef098c93ff98e8747c.tar.bz2
linux-4e40642cdb621c669507d7ef098c93ff98e8747c.zip
i3c: mipi-i3c-hci: Fix race between bus cleanup and interrupt
If there is a transfer error during i3c_master_bus_init() and code goes doing the bus cleanup in i3c_hci_bus_cleanup() there is possibility that i3c_hci_irq_handler() is running in parallel with hci->io->cleanup() which can be racy. Prevent this by waiting there is no pending interrupt on other CPU before doing the IO cleanup. This was observed with ring headers where first transfer failed and sometimes transfer error or ring transfer abort interrupt was coming simultaneously with the bus cleanup path. Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Link: https://lore.kernel.org/r/20230921055704.1087277-8-jarkko.nikula@linux.intel.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Diffstat (limited to 'drivers/i3c')
-rw-r--r--drivers/i3c/master/mipi-i3c-hci/core.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
index 76a3e6bb3665..d7fe8e62820a 100644
--- a/drivers/i3c/master/mipi-i3c-hci/core.c
+++ b/drivers/i3c/master/mipi-i3c-hci/core.c
@@ -161,10 +161,12 @@ static int i3c_hci_bus_init(struct i3c_master_controller *m)
static void i3c_hci_bus_cleanup(struct i3c_master_controller *m)
{
struct i3c_hci *hci = to_i3c_hci(m);
+ struct platform_device *pdev = to_platform_device(m->dev.parent);
DBG("");
reg_clear(HC_CONTROL, HC_CONTROL_BUS_ENABLE);
+ synchronize_irq(platform_get_irq(pdev, 0));
hci->io->cleanup(hci);
if (hci->cmd == &mipi_i3c_hci_cmd_v1)
mipi_i3c_hci_dat_v1.cleanup(hci);