i2c: sh_mobile: request IRQs after mapping registers

The managed IRQ handlers are acquired before the managed register
mapping, so devres unmaps the registers before freeing the IRQs. A
transfer wakes its waiter before the ISR's final register read, and
unregistering the adapter does not synchronize these IRQs. An in-flight
handler can therefore still access the mapping when it is released
during driver detach.

With forced-threaded IRQs, the handler can be preempted after waking the
transfer waiter and before its final ICSR read.

Map the registers before requesting the IRQs so that managed cleanup
frees and synchronizes all handlers before unmapping their registers.
Keep IRQs available while unregistering the adapter because client
removal may perform transfers.

This issue was identified as part of our ongoing research while
reviewing kernel code.

Co-developed-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
Link: https://patch.msgid.link/20261017233416.47b09ffff48f.i2c-sh-mobile@gmail.com
This commit is contained in:
Myeonghun Pak 2026-10-17 23:35:16 -04:00 committed by Andi Shyti
parent f0e53c16b1
commit f7b70efba2
No known key found for this signature in database
GPG Key ID: DA78056626D32D6E

View File

@ -880,10 +880,6 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
return PTR_ERR(pd->clk);
}
ret = sh_mobile_i2c_hook_irqs(dev, pd);
if (ret)
return ret;
pd->dev = &dev->dev;
platform_set_drvdata(dev, pd);
@ -891,6 +887,10 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
if (IS_ERR(pd->reg))
return PTR_ERR(pd->reg);
ret = sh_mobile_i2c_hook_irqs(dev, pd);
if (ret)
return ret;
ret = of_property_read_u32(dev->dev.of_node, "clock-frequency", &bus_speed);
pd->bus_speed = (ret || !bus_speed) ? I2C_MAX_STANDARD_MODE_FREQ : bus_speed;
pd->clks_per_count = 1;