Message ID | 20231031144252.2112593-4-m.szyprowski@samsung.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 187432b82173c86e0450d0e3d516b415ab2455f8 |
Headers | show |
Series | Add atomic transfers to s3c24xx i2c driver | expand |
Hi Marek, On Tue, Oct 31, 2023 at 03:42:52PM +0100, Marek Szyprowski wrote: > Add support for atomic transfers using polling mode with interrupts > intentionally disabled to get rid of the following warning introduced by > commit 63b96983a5dd ("i2c: core: introduce callbacks for atomic > transfers") during system reboot and power-off: > > ------------[ cut here ]------------ > WARNING: CPU: 0 PID: 1518 at drivers/i2c/i2c-core.h:40 i2c_transfer+0xe8/0xf4 > No atomic I2C transfer handler for 'i2c-0' > Modules linked in: > CPU: 0 PID: 1518 Comm: reboot Not tainted 6.6.0-next-20231031 #7453 > Hardware name: Samsung Exynos (Flattened Device Tree) > unwind_backtrace from show_stack+0x10/0x14 > show_stack from dump_stack_lvl+0x40/0x4c > dump_stack_lvl from __warn+0x7c/0x124 > __warn from warn_slowpath_fmt+0x110/0x178 > warn_slowpath_fmt from i2c_transfer+0xe8/0xf4 > i2c_transfer from regmap_i2c_read+0x58/0x88 > regmap_i2c_read from _regmap_raw_read+0xfc/0x260 > _regmap_raw_read from _regmap_bus_read+0x44/0x70 > _regmap_bus_read from _regmap_read+0x60/0x14c > _regmap_read from regmap_read+0x3c/0x60 > regmap_read from regulator_get_voltage_sel_regmap+0x2c/0x74 > regulator_get_voltage_sel_regmap from regulator_get_voltage_rdev+0x64/0x15c > regulator_get_voltage_rdev from _regulator_do_set_voltage+0x2c/0x5a8 > _regulator_do_set_voltage from regulator_set_voltage_rdev+0x90/0x248 > regulator_set_voltage_rdev from regulator_do_balance_voltage+0x350/0x4d0 > regulator_do_balance_voltage from regulator_set_voltage_unlocked+0xd4/0x118 > regulator_set_voltage_unlocked from regulator_set_voltage+0x40/0x74 > regulator_set_voltage from _opp_config_regulator_single+0x44/0x110 > _opp_config_regulator_single from _set_opp+0x118/0x500 > _set_opp from dev_pm_opp_set_rate+0x108/0x20c > dev_pm_opp_set_rate from __cpufreq_driver_target+0x568/0x6cc > __cpufreq_driver_target from cpufreq_generic_suspend+0x28/0x50 > cpufreq_generic_suspend from cpufreq_suspend+0xbc/0x124 > cpufreq_suspend from device_shutdown+0x18/0x230 > device_shutdown from kernel_restart+0x38/0x90 > kernel_restart from __do_sys_reboot+0x12c/0x1f8 > __do_sys_reboot from ret_fast_syscall+0x0/0x54 > Exception stack(0xf0fedfa8 to 0xf0fedff0) > ... > ---[ end trace 0000000000000000 ]--- > > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> > Reviewed-by: Chanho Park <chanho61.park@samsung.com> Thanks! Reviewed-by: Andi Shyti <andi.shyti@kernel.org> Andi
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 28114b6aadfa..cf55238fca71 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -76,6 +76,7 @@ #define QUIRK_HDMIPHY (1 << 1) #define QUIRK_NO_GPIO (1 << 2) #define QUIRK_POLL (1 << 3) +#define QUIRK_ATOMIC (1 << 4) /* Max time to wait for bus to become idle after a xfer (in us) */ #define S3C2410_IDLE_TIMEOUT 5000 @@ -174,7 +175,7 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret) if (ret) i2c->msg_idx = ret; - if (!(i2c->quirks & QUIRK_POLL)) + if (!(i2c->quirks & (QUIRK_POLL | QUIRK_ATOMIC))) wake_up(&i2c->wait); } @@ -699,7 +700,7 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, s3c24xx_i2c_enable_irq(i2c); s3c24xx_i2c_message_start(i2c, msgs); - if (i2c->quirks & QUIRK_POLL) { + if (i2c->quirks & (QUIRK_POLL | QUIRK_ATOMIC)) { while ((i2c->msg_num != 0) && is_ack(i2c)) { unsigned long stat = readl(i2c->regs + S3C2410_IICSTAT); @@ -771,6 +772,21 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, return -EREMOTEIO; } +static int s3c24xx_i2c_xfer_atomic(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + struct s3c24xx_i2c *i2c = (struct s3c24xx_i2c *)adap->algo_data; + int ret; + + disable_irq(i2c->irq); + i2c->quirks |= QUIRK_ATOMIC; + ret = s3c24xx_i2c_xfer(adap, msgs, num); + i2c->quirks &= ~QUIRK_ATOMIC; + enable_irq(i2c->irq); + + return ret; +} + /* declare our i2c functionality */ static u32 s3c24xx_i2c_func(struct i2c_adapter *adap) { @@ -781,6 +797,7 @@ static u32 s3c24xx_i2c_func(struct i2c_adapter *adap) /* i2c bus registration info */ static const struct i2c_algorithm s3c24xx_i2c_algorithm = { .master_xfer = s3c24xx_i2c_xfer, + .master_xfer_atomic = s3c24xx_i2c_xfer_atomic, .functionality = s3c24xx_i2c_func, };