Refactor the current implementation os __xe_mmio_wait32 to use
kernel poll_timeout_* helpers that scale across architecture
and max timeouts while maintaining the exponential backoff looping
to ensure no difference in latency experiened by callers.

Assisted-by: LLM
Suggested-by: Jani Nikula <[email protected]>
Signed-off-by: Alan Previn <[email protected]>
---
 drivers/gpu/drm/xe/xe_mmio.c | 64 +++++++++++++-----------------------
 1 file changed, 23 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c
index 2674146ced76..e48b1c94a82b 100644
--- a/drivers/gpu/drm/xe/xe_mmio.c
+++ b/drivers/gpu/drm/xe/xe_mmio.c
@@ -5,8 +5,8 @@
 
 #include "xe_mmio.h"
 
-#include <linux/delay.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/iopoll.h>
 #include <linux/minmax.h>
 #include <linux/pci.h>
 
@@ -324,53 +324,35 @@ u64 xe_mmio_read64_2x32(struct xe_mmio *mmio, struct 
xe_reg reg)
        return (u64)udw << 32 | ldw;
 }
 
-#define __XE_MMIO_WAIT_MAX_BACKOFF_100MS (100 * USEC_PER_MSEC)
+#define XE_MMIO_WAIT_MIN_US            10
+#define XE_MMIO_WAIT_MAX_DELAY_US      (MAX_UDELAY_MS * 1000)
+#define XE_MMIO_WAIT_MAX_SLEEP_US      (100 * 1000)
+
 static int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, 
u32 val,
                            u32 timeout_us, u32 *out_val, bool atomic, bool 
expect_match)
 {
-       ktime_t cur = ktime_get_raw();
-       const ktime_t end = ktime_add_us(cur, timeout_us);
-       int ret = -ETIMEDOUT;
-       s64 wait = 10;
+       u32 max_us = atomic ? XE_MMIO_WAIT_MAX_DELAY_US : 
XE_MMIO_WAIT_MAX_SLEEP_US;
+       /* a zero timeout means "never time out" to the iopoll helpers */
+       u32 left_us = timeout_us ?: 1;
+       u32 wait_us = XE_MMIO_WAIT_MIN_US;
+       u32 step_us;
        u32 read;
-       bool check;
-
-       for (;;) {
-               read = xe_mmio_read32(mmio, reg);
-
-               check = (read & mask) == val;
-               if (!expect_match)
-                       check = !check;
-
-               if (check) {
-                       ret = 0;
-                       break;
-               }
-
-               cur = ktime_get_raw();
-               if (!ktime_before(cur, end))
-                       break;
-
-               if (ktime_after(ktime_add_us(cur, wait), end))
-                       wait = ktime_us_delta(end, cur);
+       int ret;
 
+       /* exponential backoff: each step polls at, and lasts for, twice the 
previous interval */
+       do {
+               step_us = min(wait_us, left_us);
                if (atomic)
-                       udelay(min_t(s64, wait, (MAX_UDELAY_MS * 1000)));
+                       ret = poll_timeout_us_atomic(read = 
xe_mmio_read32(mmio, reg),
+                                                    ((read & mask) == val) == 
expect_match,
+                                                    step_us, step_us, false);
                else
-                       usleep_range(wait, wait << 1);
-               wait = min_t(s64, wait << 1, __XE_MMIO_WAIT_MAX_BACKOFF_100MS);
-       }
-
-       if (ret != 0) {
-               read = xe_mmio_read32(mmio, reg);
-
-               check = (read & mask) == val;
-               if (!expect_match)
-                       check = !check;
-
-               if (check)
-                       ret = 0;
-       }
+                       ret = poll_timeout_us(read = xe_mmio_read32(mmio, reg),
+                                             ((read & mask) == val) == 
expect_match,
+                                             step_us, step_us, false);
+               left_us -= step_us;
+               wait_us = min(wait_us << 1, max_us);
+       } while (ret && left_us);
 
        if (out_val)
                *out_val = read;

base-commit: 81fce6ce260af07e3f7a1211b6fe813941cbd17b
-- 
2.43.0

Reply via email to