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

Configure Feed

Select the types of activity you want to include in your feed.

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 b9a15012a1452
("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: b8460480f62e1 ("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>

authored by

Adrian Hunter and committed by
Alexandre Belloni
c6396b83 e44d2719

+10 -3
+10 -3
drivers/i3c/master/mipi-i3c-hci/core.c
··· 152 152 if (hci->quirks & HCI_QUIRK_RESP_BUF_THLD) 153 153 amd_set_resp_buf_thld(hci); 154 154 155 + scoped_guard(spinlock_irqsave, &hci->lock) 156 + hci->irq_inactive = false; 157 + 155 158 /* Enable bus with Hot-Join disabled */ 156 159 reg_set(HC_CONTROL, HC_CONTROL_BUS_ENABLE | HC_CONTROL_HOT_JOIN_CTRL); 157 160 dev_dbg(&hci->master.dev, "HC_CONTROL = %#x", reg_read(HC_CONTROL)); ··· 187 184 int irq = platform_get_irq(pdev, 0); 188 185 189 186 reg_write(INTR_SIGNAL_ENABLE, 0x0); 190 - hci->irq_inactive = true; 191 187 synchronize_irq(irq); 188 + scoped_guard(spinlock_irqsave, &hci->lock) 189 + hci->irq_inactive = true; 192 190 } 193 191 194 192 static void i3c_hci_bus_cleanup(struct i3c_master_controller *m) ··· 785 781 786 782 mipi_i3c_hci_dat_v1.restore(hci); 787 783 788 - hci->irq_inactive = false; 789 - 790 784 hci->io->resume(hci); 785 + 786 + scoped_guard(spinlock_irqsave, &hci->lock) 787 + hci->irq_inactive = false; 791 788 792 789 /* Enable bus with Hot-Join disabled */ 793 790 reg_set(HC_CONTROL, HC_CONTROL_BUS_ENABLE | HC_CONTROL_HOT_JOIN_CTRL); ··· 979 974 ret = i3c_hci_init(hci); 980 975 if (ret) 981 976 return ret; 977 + 978 + hci->irq_inactive = true; 982 979 983 980 irq = platform_get_irq(pdev, 0); 984 981 ret = devm_request_irq(&pdev->dev, irq, i3c_hci_irq_handler,