Skip to content

Commit 2fe2b96

Browse files
endeneerAndi Shyti
authored andcommitted
i2c: designware: Invoke runtime suspend on quick slave re-registration
Replaced pm_runtime_put() with pm_runtime_put_sync_suspend() to ensure the runtime suspend is invoked immediately when unregistering a slave. This prevents a race condition where suspend was skipped when unregistering and registering slave in quick succession. For example, consider the rapid sequence of `delete_device -> new_device -> delete_device -> new_device`. In this sequence, it is observed that the dw_i2c_plat_runtime_suspend() might not be invoked after `delete_device` operation. This is because after `delete_device` operation, when the pm_runtime_put() is about to trigger suspend, the following `new_device` operation might race and cancel the suspend. If that happens, during the `new_device` operation, dw_i2c_plat_runtime_resume() is skipped (since there was no suspend), which means `i_dev->init()`, i.e. i2c_dw_init_slave(), is skipped. Since i2c_dw_init_slave() is skipped, i2c_dw_configure_fifo_slave() is skipped too, which leaves `DW_IC_INTR_MASK` unconfigured. If we inspect the interrupt mask register using devmem, it will show as zero. Example shell script to reproduce the issue: ``` #!/bin/sh SLAVE_LADDR=0x1010 SLAVE_BUS=13 NEW_DEVICE=/sys/bus/i2c/devices/i2c-$SLAVE_BUS/new_device DELETE_DEVICE=/sys/bus/i2c/devices/i2c-$SLAVE_BUS/delete_device # Create initial device echo slave-24c02 $SLAVE_LADDR > $NEW_DEVICE sleep 2 # Rapid sequence of # delete_device -> new_device -> delete_device -> new_device echo $SLAVE_LADDR > $DELETE_DEVICE echo slave-24c02 $SLAVE_LADDR > $NEW_DEVICE echo $SLAVE_LADDR > $DELETE_DEVICE echo slave-24c02 $SLAVE_LADDR > $NEW_DEVICE # Using devmem to inspect IC_INTR_MASK will show as zero ``` Signed-off-by: Tan En De <ende.tan@starfivetech.com> Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Link: https://lore.kernel.org/r/20250412023303.378600-1-ende.tan@starfivetech.com Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
1 parent e981364 commit 2fe2b96

File tree

1 file changed

+1
-1
lines changed

1 file changed

+1
-1
lines changed

drivers/i2c/busses/i2c-designware-slave.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ static int i2c_dw_unreg_slave(struct i2c_client *slave)
9696
i2c_dw_disable(dev);
9797
synchronize_irq(dev->irq);
9898
dev->slave = NULL;
99-
pm_runtime_put(dev->dev);
99+
pm_runtime_put_sync_suspend(dev->dev);
100100

101101
return 0;
102102
}

0 commit comments

Comments
 (0)