* [PATCH v2 1/2] i2c: ocores: increase poll timeout to total transfer timeout
@ 2025-10-09 9:19 Matthias Schiffer
2025-10-09 9:19 ` [PATCH v2 2/2] i2c: ocores: respect adapter timeout in IRQ mode Matthias Schiffer
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Matthias Schiffer @ 2025-10-09 9:19 UTC (permalink / raw)
To: Peter Korsgaard, Andrew Lunn, Andi Shyti
Cc: linux-i2c, linux-kernel, linux, Matthias Schiffer
When a target makes use of clock stretching, a timeout of 1ms may not be
enough. One extreme example is the NXP PTN3460 eDP to LVDS bridge, which
takes ~320ms to send its ACK after a flash command has been
submitted.
The behavior in the regular case is unchanged, spinning for up to 1ms,
but the open-coded poll loop is replaced with read_poll_timeout_atomic()
as suggested by Andrew Lunn. In cases where 1ms is not sufficient,
read_poll_timeout() is used, allowing a total transfer time up to the
timeout set in struct i2c_adapter (defaulting to 1s, configurable through
the I2C_TIMEOUT ioctl).
Signed-off-by: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
---
v2: avoid spinning for a whole second, switch to
read_poll_timeout[_atomic]()
drivers/i2c/busses/i2c-ocores.c | 44 ++++++++++++++++-----------------
1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index 482b37c8a1297..c4587194d46be 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -18,6 +18,7 @@
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
+#include <linux/iopoll.h>
#include <linux/wait.h>
#include <linux/platform_data/i2c-ocores.h>
#include <linux/slab.h>
@@ -258,7 +259,7 @@ static void ocores_process_timeout(struct ocores_i2c *i2c)
* @reg: register to query
* @mask: bitmask to apply on register value
* @val: expected result
- * @timeout: timeout in jiffies
+ * @timeout: absolute timeout in jiffies
*
* Timeout is necessary to avoid to stay here forever when the chip
* does not answer correctly.
@@ -269,30 +270,32 @@ static int ocores_wait(struct ocores_i2c *i2c,
int reg, u8 mask, u8 val,
const unsigned long timeout)
{
- unsigned long j;
-
- j = jiffies + timeout;
- while (1) {
- u8 status = oc_getreg(i2c, reg);
+ unsigned long max_wait;
+ u8 status;
+ int ret;
- if ((status & mask) == val)
- break;
+ /* In most cases the wait is short, so we spin for up to 1ms. */
+ ret = read_poll_timeout_atomic(oc_getreg, status,
+ (status & mask) == val,
+ 0, 1000, false, i2c, reg);
+ if (ret != -ETIMEDOUT)
+ return ret;
- if (time_after(jiffies, j))
- return -ETIMEDOUT;
- }
- return 0;
+ max_wait = jiffies_to_usecs(max(0L, timeout - jiffies)) + 1;
+ return read_poll_timeout(oc_getreg, status, (status & mask) == val,
+ 10000, max_wait, false, i2c, reg);
}
/**
* ocores_poll_wait() - Wait until is possible to process some data
* @i2c: ocores I2C device instance
+ * @timeout: absolute timeout in jiffies
*
* Used when the device is in polling mode (interrupts disabled).
*
* Return: 0 on success, -ETIMEDOUT on timeout
*/
-static int ocores_poll_wait(struct ocores_i2c *i2c)
+static int ocores_poll_wait(struct ocores_i2c *i2c, unsigned long timeout)
{
u8 mask;
int err;
@@ -310,15 +313,11 @@ static int ocores_poll_wait(struct ocores_i2c *i2c)
udelay((8 * 1000) / i2c->bus_clock_khz);
}
- /*
- * once we are here we expect to get the expected result immediately
- * so if after 1ms we timeout then something is broken.
- */
- err = ocores_wait(i2c, OCI2C_STATUS, mask, 0, msecs_to_jiffies(1));
+ err = ocores_wait(i2c, OCI2C_STATUS, mask, 0, timeout);
if (err)
- dev_warn(i2c->adap.dev.parent,
- "%s: STATUS timeout, bit 0x%x did not clear in 1ms\n",
- __func__, mask);
+ dev_dbg(i2c->adap.dev.parent,
+ "%s: STATUS timeout, bit 0x%x did not clear\n",
+ __func__, mask);
return err;
}
@@ -336,11 +335,12 @@ static int ocores_poll_wait(struct ocores_i2c *i2c)
*/
static int ocores_process_polling(struct ocores_i2c *i2c)
{
+ unsigned long timeout = jiffies + i2c->adap.timeout;
irqreturn_t ret;
int err = 0;
while (1) {
- err = ocores_poll_wait(i2c);
+ err = ocores_poll_wait(i2c, timeout);
if (err)
break; /* timeout */
--
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
https://www.tq-group.com/
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 2/2] i2c: ocores: respect adapter timeout in IRQ mode
2025-10-09 9:19 [PATCH v2 1/2] i2c: ocores: increase poll timeout to total transfer timeout Matthias Schiffer
@ 2025-10-09 9:19 ` Matthias Schiffer
2025-10-09 13:21 ` Andrew Lunn
2025-10-09 13:20 ` [PATCH v2 1/2] i2c: ocores: increase poll timeout to total transfer timeout Andrew Lunn
2026-01-13 13:02 ` Wolfram Sang
2 siblings, 1 reply; 10+ messages in thread
From: Matthias Schiffer @ 2025-10-09 9:19 UTC (permalink / raw)
To: Peter Korsgaard, Andrew Lunn, Andi Shyti
Cc: linux-i2c, linux-kernel, linux, Matthias Schiffer
While the timeout field of the i2c_adapter defaults to 1s, it can be
changed, for example using the I2C_TIMEOUT ioctl. Change the ocores
driver to use this timeout instead of hardcoding 1s, also making it
consistent with polling mode.
Signed-off-by: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
Acked-by: Peter Korsgaard <peter@korsgaard.com>
---
v2: collect acked-by
drivers/i2c/busses/i2c-ocores.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index c4587194d46be..4a8ce167a3d9f 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -383,7 +383,8 @@ static int ocores_xfer_core(struct ocores_i2c *i2c,
} else {
if (wait_event_timeout(i2c->wait,
(i2c->state == STATE_ERROR) ||
- (i2c->state == STATE_DONE), HZ) == 0)
+ (i2c->state == STATE_DONE),
+ i2c->adap.timeout) == 0)
ret = -ETIMEDOUT;
}
if (ret) {
--
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
https://www.tq-group.com/
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] i2c: ocores: increase poll timeout to total transfer timeout
2025-10-09 9:19 [PATCH v2 1/2] i2c: ocores: increase poll timeout to total transfer timeout Matthias Schiffer
2025-10-09 9:19 ` [PATCH v2 2/2] i2c: ocores: respect adapter timeout in IRQ mode Matthias Schiffer
@ 2025-10-09 13:20 ` Andrew Lunn
2025-10-09 13:26 ` Matthias Schiffer
2026-01-13 13:02 ` Wolfram Sang
2 siblings, 1 reply; 10+ messages in thread
From: Andrew Lunn @ 2025-10-09 13:20 UTC (permalink / raw)
To: Matthias Schiffer
Cc: Peter Korsgaard, Andi Shyti, linux-i2c, linux-kernel, linux
On Thu, Oct 09, 2025 at 11:19:49AM +0200, Matthias Schiffer wrote:
> When a target makes use of clock stretching, a timeout of 1ms may not be
> enough. One extreme example is the NXP PTN3460 eDP to LVDS bridge, which
> takes ~320ms to send its ACK after a flash command has been
> submitted.
>
> The behavior in the regular case is unchanged, spinning for up to 1ms,
> but the open-coded poll loop is replaced with read_poll_timeout_atomic()
> as suggested by Andrew Lunn. In cases where 1ms is not sufficient,
> read_poll_timeout() is used, allowing a total transfer time up to the
> timeout set in struct i2c_adapter (defaulting to 1s, configurable through
> the I2C_TIMEOUT ioctl).
Thanks
Did you test with CONFIG_DEBUG_ATOMIC_SLEEP enabled? I don't think it
is an issue, but the old code could be used in atomic context because
it never slept.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 2/2] i2c: ocores: respect adapter timeout in IRQ mode
2025-10-09 9:19 ` [PATCH v2 2/2] i2c: ocores: respect adapter timeout in IRQ mode Matthias Schiffer
@ 2025-10-09 13:21 ` Andrew Lunn
0 siblings, 0 replies; 10+ messages in thread
From: Andrew Lunn @ 2025-10-09 13:21 UTC (permalink / raw)
To: Matthias Schiffer
Cc: Peter Korsgaard, Andi Shyti, linux-i2c, linux-kernel, linux
On Thu, Oct 09, 2025 at 11:19:50AM +0200, Matthias Schiffer wrote:
> While the timeout field of the i2c_adapter defaults to 1s, it can be
> changed, for example using the I2C_TIMEOUT ioctl. Change the ocores
> driver to use this timeout instead of hardcoding 1s, also making it
> consistent with polling mode.
>
> Signed-off-by: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
> Acked-by: Peter Korsgaard <peter@korsgaard.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] i2c: ocores: increase poll timeout to total transfer timeout
2025-10-09 13:20 ` [PATCH v2 1/2] i2c: ocores: increase poll timeout to total transfer timeout Andrew Lunn
@ 2025-10-09 13:26 ` Matthias Schiffer
2025-12-10 8:51 ` Matthias Schiffer
0 siblings, 1 reply; 10+ messages in thread
From: Matthias Schiffer @ 2025-10-09 13:26 UTC (permalink / raw)
To: Andrew Lunn; +Cc: Peter Korsgaard, Andi Shyti, linux-i2c, linux-kernel, linux
On Thu, 2025-10-09 at 15:20 +0200, Andrew Lunn wrote:
> On Thu, Oct 09, 2025 at 11:19:49AM +0200, Matthias Schiffer wrote:
> > When a target makes use of clock stretching, a timeout of 1ms may not be
> > enough. One extreme example is the NXP PTN3460 eDP to LVDS bridge, which
> > takes ~320ms to send its ACK after a flash command has been
> > submitted.
> >
> > The behavior in the regular case is unchanged, spinning for up to 1ms,
> > but the open-coded poll loop is replaced with read_poll_timeout_atomic()
> > as suggested by Andrew Lunn. In cases where 1ms is not sufficient,
> > read_poll_timeout() is used, allowing a total transfer time up to the
> > timeout set in struct i2c_adapter (defaulting to 1s, configurable through
> > the I2C_TIMEOUT ioctl).
>
> Thanks
>
> Did you test with CONFIG_DEBUG_ATOMIC_SLEEP enabled? I don't think it
> is an issue, but the old code could be used in atomic context because
> it never slept.
I did not, but there is only one call chain ocores_xfer_core ->
ocores_process_polling -> ocores_poll_wait -> ocores_wait, which is definitely
not used in atomic context (in IRQ mode, ocores_xfer_core calls
wait_event_timeout, which might_sleep()).
Best,
Matthias
>
> Reviewed-by: Andrew Lunn <andrew@lunn.ch>
>
> Andrew
--
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
https://www.tq-group.com/
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] i2c: ocores: increase poll timeout to total transfer timeout
2025-10-09 13:26 ` Matthias Schiffer
@ 2025-12-10 8:51 ` Matthias Schiffer
0 siblings, 0 replies; 10+ messages in thread
From: Matthias Schiffer @ 2025-12-10 8:51 UTC (permalink / raw)
To: Andrew Lunn; +Cc: Peter Korsgaard, Andi Shyti, linux-i2c, linux-kernel, linux
On Thu, 2025-10-09 at 15:26 +0200, Matthias Schiffer wrote:
> On Thu, 2025-10-09 at 15:20 +0200, Andrew Lunn wrote:
> > On Thu, Oct 09, 2025 at 11:19:49AM +0200, Matthias Schiffer wrote:
> > > When a target makes use of clock stretching, a timeout of 1ms may not be
> > > enough. One extreme example is the NXP PTN3460 eDP to LVDS bridge, which
> > > takes ~320ms to send its ACK after a flash command has been
> > > submitted.
> > >
> > > The behavior in the regular case is unchanged, spinning for up to 1ms,
> > > but the open-coded poll loop is replaced with read_poll_timeout_atomic()
> > > as suggested by Andrew Lunn. In cases where 1ms is not sufficient,
> > > read_poll_timeout() is used, allowing a total transfer time up to the
> > > timeout set in struct i2c_adapter (defaulting to 1s, configurable through
> > > the I2C_TIMEOUT ioctl).
> >
> > Thanks
> >
> > Did you test with CONFIG_DEBUG_ATOMIC_SLEEP enabled? I don't think it
> > is an issue, but the old code could be used in atomic context because
> > it never slept.
>
> I did not, but there is only one call chain ocores_xfer_core ->
> ocores_process_polling -> ocores_poll_wait -> ocores_wait, which is definitely
> not used in atomic context (in IRQ mode, ocores_xfer_core calls
> wait_event_timeout, which might_sleep()).
>
> Best,
> Matthias
>
>
>
> >
> > Reviewed-by: Andrew Lunn <andrew@lunn.ch>
> >
> > Andrew
>
Hi everyone,
are these patches still missing anything?
Best,
Matthias
--
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
https://www.tq-group.com/
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] i2c: ocores: increase poll timeout to total transfer timeout
2025-10-09 9:19 [PATCH v2 1/2] i2c: ocores: increase poll timeout to total transfer timeout Matthias Schiffer
2025-10-09 9:19 ` [PATCH v2 2/2] i2c: ocores: respect adapter timeout in IRQ mode Matthias Schiffer
2025-10-09 13:20 ` [PATCH v2 1/2] i2c: ocores: increase poll timeout to total transfer timeout Andrew Lunn
@ 2026-01-13 13:02 ` Wolfram Sang
2026-01-13 14:21 ` Andrew Lunn
2 siblings, 1 reply; 10+ messages in thread
From: Wolfram Sang @ 2026-01-13 13:02 UTC (permalink / raw)
To: Matthias Schiffer
Cc: Peter Korsgaard, Andrew Lunn, Andi Shyti, linux-i2c, linux-kernel,
linux
[-- Attachment #1: Type: text/plain, Size: 411 bytes --]
> The behavior in the regular case is unchanged, spinning for up to 1ms,
> but the open-coded poll loop is replaced with read_poll_timeout_atomic()
> as suggested by Andrew Lunn.
Hmm, spinning 1ms is still a lot. Can't we just use read_poll_timeout()
for the whole timeout? I can't see that it will cause a regression. But
please correct me if I am wrong.
The series looks good for me apart from the above.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] i2c: ocores: increase poll timeout to total transfer timeout
2026-01-13 13:02 ` Wolfram Sang
@ 2026-01-13 14:21 ` Andrew Lunn
2026-01-14 8:28 ` Matthias Schiffer
0 siblings, 1 reply; 10+ messages in thread
From: Andrew Lunn @ 2026-01-13 14:21 UTC (permalink / raw)
To: Wolfram Sang
Cc: Matthias Schiffer, Peter Korsgaard, Andi Shyti, linux-i2c,
linux-kernel, linux
On Tue, Jan 13, 2026 at 02:02:07PM +0100, Wolfram Sang wrote:
>
> > The behavior in the regular case is unchanged, spinning for up to 1ms,
> > but the open-coded poll loop is replaced with read_poll_timeout_atomic()
> > as suggested by Andrew Lunn.
>
> Hmm, spinning 1ms is still a lot. Can't we just use read_poll_timeout()
> for the whole timeout? I can't see that it will cause a regression. But
> please correct me if I am wrong.
I've forgotten the context, but
/**
* ocores_poll_wait() - Wait until is possible to process some data
* @i2c: ocores I2C device instance
*
* Used when the device is in polling mode (interrupts disabled).
If interrupts are disabled, you cannot use read_poll_timeout(). You
have to use read_poll_timeout_atomic(). And that spins anyway.
Andrew
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] i2c: ocores: increase poll timeout to total transfer timeout
2026-01-13 14:21 ` Andrew Lunn
@ 2026-01-14 8:28 ` Matthias Schiffer
2026-01-14 9:34 ` Wolfram Sang
0 siblings, 1 reply; 10+ messages in thread
From: Matthias Schiffer @ 2026-01-14 8:28 UTC (permalink / raw)
To: Andrew Lunn
Cc: Peter Korsgaard, Andi Shyti, linux-i2c, linux-kernel, linux,
Wolfram Sang
On Tue, 2026-01-13 at 15:21 +0100, Andrew Lunn wrote:
> On Tue, Jan 13, 2026 at 02:02:07PM +0100, Wolfram Sang wrote:
> >
> > > The behavior in the regular case is unchanged, spinning for up to 1ms,
> > > but the open-coded poll loop is replaced with read_poll_timeout_atomic()
> > > as suggested by Andrew Lunn.
> >
> > Hmm, spinning 1ms is still a lot. Can't we just use read_poll_timeout()
> > for the whole timeout? I can't see that it will cause a regression. But
> > please correct me if I am wrong.
>
> I've forgotten the context, but
>
> /**
> * ocores_poll_wait() - Wait until is possible to process some data
> * @i2c: ocores I2C device instance
> *
> * Used when the device is in polling mode (interrupts disabled).
>
> If interrupts are disabled, you cannot use read_poll_timeout(). You
> have to use read_poll_timeout_atomic(). And that spins anyway.
>
> Andrew
This code does not have interrupts disabled, we could not fall back from
read_poll_timeout_atomic() to read_poll_timeout() otherwise. My understanding is
that a sleeping wait would make it more likely for a switch to a different task
to happen after every byte, negatively impacting I2C performance; this is not
something I have verified however.
It is spinning for 1ms because that's what the old code did (which only spun
without fallback to sleeping). Reducing this to the time needed to transfer 1
byte in the absence of clock stretching should not cause issues (200us for
50kHz; could also be made to depend on the clock rate, so it would be even less
spinning at higher frequencies).
Best,
Matthias
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/2] i2c: ocores: increase poll timeout to total transfer timeout
2026-01-14 8:28 ` Matthias Schiffer
@ 2026-01-14 9:34 ` Wolfram Sang
0 siblings, 0 replies; 10+ messages in thread
From: Wolfram Sang @ 2026-01-14 9:34 UTC (permalink / raw)
To: Matthias Schiffer
Cc: Andrew Lunn, Peter Korsgaard, Andi Shyti, linux-i2c, linux-kernel,
linux
[-- Attachment #1: Type: text/plain, Size: 946 bytes --]
Hi Matthias,
> This code does not have interrupts disabled, we could not fall back from
> read_poll_timeout_atomic() to read_poll_timeout() otherwise.
Yes, that's what I thought as well.
> that a sleeping wait would make it more likely for a switch to a different task
> to happen after every byte, negatively impacting I2C performance; this is not
> something I have verified however.
Quite some prominent controller drivers use readX_poll_timeout(), so it
really seems there is no huge penalty in practice. Especially not with
cores so fast these days that tasks can be served even in 100us.
> It is spinning for 1ms because that's what the old code did (which only spun
> without fallback to sleeping).
I understand. Yet, I think the spinning is legacy behaviour and I would
prefer plain readX_poll_timeout(). Unless there is something I
overlooked. Makes the code simpler and easier to maintain.
Thanks and happy hacking,
Wolfram
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-01-14 9:35 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-09 9:19 [PATCH v2 1/2] i2c: ocores: increase poll timeout to total transfer timeout Matthias Schiffer
2025-10-09 9:19 ` [PATCH v2 2/2] i2c: ocores: respect adapter timeout in IRQ mode Matthias Schiffer
2025-10-09 13:21 ` Andrew Lunn
2025-10-09 13:20 ` [PATCH v2 1/2] i2c: ocores: increase poll timeout to total transfer timeout Andrew Lunn
2025-10-09 13:26 ` Matthias Schiffer
2025-12-10 8:51 ` Matthias Schiffer
2026-01-13 13:02 ` Wolfram Sang
2026-01-13 14:21 ` Andrew Lunn
2026-01-14 8:28 ` Matthias Schiffer
2026-01-14 9:34 ` Wolfram Sang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox