Skip to content

Commit c6396b8

Browse files
ahunter6alexandrebelloni
authored andcommitted
i3c: mipi-i3c-hci: Fix handling of shared IRQs during early initialization
Shared interrupts may fire unexpectedly, including during periods when the controller is not yet fully initialized. Commit b9a1501 ("i3c: mipi-i3c-hci: Add optional Runtime PM support") addressed this issue for the runtime-suspended state, but the same problem can also occur before the bus is enabled for the first time. Ensure the IRQ handler ignores interrupts until initialization is complete by making consistent use of the existing irq_inactive flag. The flag is now set to false immediately before enabling the bus. To guarantee correct ordering with respect to the IRQ handler, protect all transitions of irq_inactive with the same spinlock used inside the handler. Fixes: b846048 ("i3c: mipi-i3c-hci: Allow for Multi-Bus Instances") Cc: stable@vger.kernel.org Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Reviewed-by: Frank Li <Frank.Li@nxp.com> Link: https://patch.msgid.link/20260306072451.11131-14-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
1 parent e44d271 commit c6396b8

1 file changed

Lines changed: 10 additions & 3 deletions

File tree

  • drivers/i3c/master/mipi-i3c-hci

drivers/i3c/master/mipi-i3c-hci/core.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ static int i3c_hci_bus_init(struct i3c_master_controller *m)
152152
if (hci->quirks & HCI_QUIRK_RESP_BUF_THLD)
153153
amd_set_resp_buf_thld(hci);
154154

155+
scoped_guard(spinlock_irqsave, &hci->lock)
156+
hci->irq_inactive = false;
157+
155158
/* Enable bus with Hot-Join disabled */
156159
reg_set(HC_CONTROL, HC_CONTROL_BUS_ENABLE | HC_CONTROL_HOT_JOIN_CTRL);
157160
dev_dbg(&hci->master.dev, "HC_CONTROL = %#x", reg_read(HC_CONTROL));
@@ -184,8 +187,9 @@ void i3c_hci_sync_irq_inactive(struct i3c_hci *hci)
184187
int irq = platform_get_irq(pdev, 0);
185188

186189
reg_write(INTR_SIGNAL_ENABLE, 0x0);
187-
hci->irq_inactive = true;
188190
synchronize_irq(irq);
191+
scoped_guard(spinlock_irqsave, &hci->lock)
192+
hci->irq_inactive = true;
189193
}
190194

191195
static void i3c_hci_bus_cleanup(struct i3c_master_controller *m)
@@ -781,10 +785,11 @@ static int i3c_hci_runtime_resume(struct device *dev)
781785

782786
mipi_i3c_hci_dat_v1.restore(hci);
783787

784-
hci->irq_inactive = false;
785-
786788
hci->io->resume(hci);
787789

790+
scoped_guard(spinlock_irqsave, &hci->lock)
791+
hci->irq_inactive = false;
792+
788793
/* Enable bus with Hot-Join disabled */
789794
reg_set(HC_CONTROL, HC_CONTROL_BUS_ENABLE | HC_CONTROL_HOT_JOIN_CTRL);
790795

@@ -975,6 +980,8 @@ static int i3c_hci_probe(struct platform_device *pdev)
975980
if (ret)
976981
return ret;
977982

983+
hci->irq_inactive = true;
984+
978985
irq = platform_get_irq(pdev, 0);
979986
ret = devm_request_irq(&pdev->dev, irq, i3c_hci_irq_handler,
980987
IRQF_SHARED, NULL, hci);

0 commit comments

Comments
 (0)