Message ID | 20231006150804.4113844-1-m.szyprowski@samsung.com |
---|---|
State | New |
Headers | show |
Series | [v3] i2c: exynos5: add support for atomic transfers | expand |
Hi Marek, ... > +static bool exynos5_i2c_poll_irqs_timeout(struct exynos5_i2c *i2c, > + unsigned long timeout) > +{ > + unsigned long time_left = jiffies + timeout; > + > + while (time_before(jiffies, time_left) && > + !((i2c->trans_done && (i2c->msg->len == i2c->msg_ptr)) || > + (i2c->state < 0))) { > + while (readl(i2c->regs + HSI2C_INT_ENABLE) & > + readl(i2c->regs + HSI2C_INT_STATUS)) > + exynos5_i2c_irq(i2c->irq, i2c); > + usleep_range(100, 200); > + } > + return time_before(jiffies, time_left); > +} > + > static int exynos5_i2c_xfer_msg(struct exynos5_i2c *i2c, > struct i2c_msg *msgs, int stop) > { > @@ -725,8 +746,13 @@ static int exynos5_i2c_xfer_msg(struct exynos5_i2c *i2c, > > exynos5_i2c_message_start(i2c, stop); > > - timeout = wait_for_completion_timeout(&i2c->msg_complete, > - EXYNOS5_I2C_TIMEOUT); > + if (!i2c->atomic) > + timeout = wait_for_completion_timeout(&i2c->msg_complete, > + EXYNOS5_I2C_TIMEOUT); > + else > + timeout = exynos5_i2c_poll_irqs_timeout(i2c, > + EXYNOS5_I2C_TIMEOUT); what's a bit bothering here is that one function returns a boolean while the other returns a timeout stored in an unsigned long. Anyway, exynos5_i2c_poll_irqs_timeout() is used only here as a boolean, so that I guess it's fine. Reviewed-by: Andi Shyti <andi.shyti@kernel.org> Andi
On Fri, Oct 06, 2023 at 05:08:03PM +0200, Marek Szyprowski wrote: > Add support for atomic transfers using polling mode with interrupts > intentionally disabled. This removes the warning introduced by commit > 63b96983a5dd ("i2c: core: introduce callbacks for atomic transfers") > during system reboot and power-off. > > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Applied to for-next, thanks!
On Sat, Oct 21, 2023 at 08:44:55PM +0200, Wolfram Sang wrote: > On Fri, Oct 06, 2023 at 05:08:03PM +0200, Marek Szyprowski wrote: > > Add support for atomic transfers using polling mode with interrupts > > intentionally disabled. This removes the warning introduced by commit > > 63b96983a5dd ("i2c: core: introduce callbacks for atomic transfers") > > during system reboot and power-off. > > > > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> > > Applied to for-next, thanks! Marek, since you have hardware, are you maybe interested in reviewing / testing this patch? http://patchwork.ozlabs.org/project/linux-i2c/patch/20220912085943.1098651-1-camel.guo@axis.com/
diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index 2b0b9cdffa86..65cb06ec3804 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -194,6 +194,11 @@ struct exynos5_i2c { */ int trans_done; + /* + * Called from atomic context, don't use interrupts. + */ + unsigned int atomic; + /* Controller operating frequency */ unsigned int op_clock; @@ -711,6 +716,22 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop) spin_unlock_irqrestore(&i2c->lock, flags); } +static bool exynos5_i2c_poll_irqs_timeout(struct exynos5_i2c *i2c, + unsigned long timeout) +{ + unsigned long time_left = jiffies + timeout; + + while (time_before(jiffies, time_left) && + !((i2c->trans_done && (i2c->msg->len == i2c->msg_ptr)) || + (i2c->state < 0))) { + while (readl(i2c->regs + HSI2C_INT_ENABLE) & + readl(i2c->regs + HSI2C_INT_STATUS)) + exynos5_i2c_irq(i2c->irq, i2c); + usleep_range(100, 200); + } + return time_before(jiffies, time_left); +} + static int exynos5_i2c_xfer_msg(struct exynos5_i2c *i2c, struct i2c_msg *msgs, int stop) { @@ -725,8 +746,13 @@ static int exynos5_i2c_xfer_msg(struct exynos5_i2c *i2c, exynos5_i2c_message_start(i2c, stop); - timeout = wait_for_completion_timeout(&i2c->msg_complete, - EXYNOS5_I2C_TIMEOUT); + if (!i2c->atomic) + timeout = wait_for_completion_timeout(&i2c->msg_complete, + EXYNOS5_I2C_TIMEOUT); + else + timeout = exynos5_i2c_poll_irqs_timeout(i2c, + EXYNOS5_I2C_TIMEOUT); + if (timeout == 0) ret = -ETIMEDOUT; else @@ -777,6 +803,21 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap, return ret ?: num; } +static int exynos5_i2c_xfer_atomic(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + struct exynos5_i2c *i2c = adap->algo_data; + int ret; + + disable_irq(i2c->irq); + i2c->atomic = true; + ret = exynos5_i2c_xfer(adap, msgs, num); + i2c->atomic = false; + enable_irq(i2c->irq); + + return ret; +} + static u32 exynos5_i2c_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); @@ -784,6 +825,7 @@ static u32 exynos5_i2c_func(struct i2c_adapter *adap) static const struct i2c_algorithm exynos5_i2c_algorithm = { .master_xfer = exynos5_i2c_xfer, + .master_xfer_atomic = exynos5_i2c_xfer_atomic, .functionality = exynos5_i2c_func, };
Add support for atomic transfers using polling mode with interrupts intentionally disabled. This removes the warning introduced by commit 63b96983a5dd ("i2c: core: introduce callbacks for atomic transfers") during system reboot and power-off. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> --- v3: - simplified timeout calculations, adjusted some names even more v2: - adjusted some names as pointed by Andi --- drivers/i2c/busses/i2c-exynos5.c | 46 ++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-)