]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
i2c: ocores: Use read_poll_timeout_atomic to avoid false poll timeouts
authorMartin Aberer <martin.aberer@bachmann.info>
Tue, 24 Mar 2026 14:05:56 +0000 (15:05 +0100)
committerAndi Shyti <andi.shyti@kernel.org>
Fri, 27 Mar 2026 13:53:25 +0000 (14:53 +0100)
Replace the manual polling loop in ocores_wait() with the kernel helper
read_poll_timeout_atomic(). This simplifies the code and ensures robust
timeout handling.

In particular, the helper guarantees a condition check after the
delay, even if the delay exceeds the timeout, avoiding spurious
timeout errors under load or preemption.

Signed-off-by: Martin Aberer <martin.aberer@bachmann.info>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
Link: https://lore.kernel.org/r/20260324140556.2249039-1-martin.aberer@bachmann.info
drivers/i2c/busses/i2c-ocores.c

index 0f67e57cdeff6cfcbd68522d467fcf289959f4b0..df6ebf32d6e8f318f7c015f827a8a637556c1386 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/log2.h>
 #include <linux/spinlock.h>
+#include <linux/iopoll.h>
 #include <linux/jiffies.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_us: timeout in microseconds
  *
  * Timeout is necessary to avoid to stay here forever when the chip
  * does not answer correctly.
@@ -267,21 +268,14 @@ static void ocores_process_timeout(struct ocores_i2c *i2c)
  */
 static int ocores_wait(struct ocores_i2c *i2c,
                       int reg, u8 mask, u8 val,
-                      const unsigned long timeout)
+                      unsigned long timeout_us)
 {
-       unsigned long j;
+       u8 status;
 
-       j = jiffies + timeout;
-       while (1) {
-               u8 status = oc_getreg(i2c, reg);
-
-               if ((status & mask) == val)
-                       break;
-
-               if (time_after(jiffies, j))
-                       return -ETIMEDOUT;
-       }
-       return 0;
+       return read_poll_timeout_atomic(oc_getreg, status,
+                                       (status & mask) == val,
+                                       0, timeout_us, false,
+                                       i2c, reg);
 }
 
 /**
@@ -314,7 +308,7 @@ static int ocores_poll_wait(struct ocores_i2c *i2c)
         * 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, 1000);
        if (err)
                dev_warn(i2c->adap.dev.parent,
                         "%s: STATUS timeout, bit 0x%x did not clear in 1ms\n",