]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/xe/device: Use poll_timeout_us() to wait for lmem
authorLucas De Marchi <lucas.demarchi@intel.com>
Mon, 22 Sep 2025 19:58:29 +0000 (12:58 -0700)
committerLucas De Marchi <lucas.demarchi@intel.com>
Thu, 25 Sep 2025 04:23:18 +0000 (21:23 -0700)
Now that there's a generic poll_timeout_us(), use it to wait for
LMEM_INIT in GU_CNTL.

Reviewed-by: Maarten Lankhorst <dev@lankhorst.se>
Link: https://lore.kernel.org/r/20250922-xe-iopoll-v4-1-06438311a63f@intel.com
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
drivers/gpu/drm/xe/xe_device.c

index fdb7b7498920afba63ae522d2f0e6b26ac58bae5..09f8a66c97282dd61eef58dbf2069133e9634ccb 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/aperture.h>
 #include <linux/delay.h>
 #include <linux/fault-inject.h>
+#include <linux/iopoll.h>
 #include <linux/units.h>
 
 #include <drm/drm_atomic_helper.h>
@@ -630,16 +631,22 @@ mask_err:
        return err;
 }
 
-static bool verify_lmem_ready(struct xe_device *xe)
+static int lmem_initializing(struct xe_device *xe)
 {
-       u32 val = xe_mmio_read32(xe_root_tile_mmio(xe), GU_CNTL) & LMEM_INIT;
+       if (xe_mmio_read32(xe_root_tile_mmio(xe), GU_CNTL) & LMEM_INIT)
+               return 0;
+
+       if (signal_pending(current))
+               return -EINTR;
 
-       return !!val;
+       return 1;
 }
 
 static int wait_for_lmem_ready(struct xe_device *xe)
 {
-       unsigned long timeout, start;
+       const unsigned long TIMEOUT_SEC = 60;
+       unsigned long prev_jiffies;
+       int initializing;
 
        if (!IS_DGFX(xe))
                return 0;
@@ -647,39 +654,35 @@ static int wait_for_lmem_ready(struct xe_device *xe)
        if (IS_SRIOV_VF(xe))
                return 0;
 
-       if (verify_lmem_ready(xe))
+       if (!lmem_initializing(xe))
                return 0;
 
        drm_dbg(&xe->drm, "Waiting for lmem initialization\n");
+       prev_jiffies = jiffies;
 
-       start = jiffies;
-       timeout = start + secs_to_jiffies(60); /* 60 sec! */
-
-       do {
-               if (signal_pending(current))
-                       return -EINTR;
-
-               /*
-                * The boot firmware initializes local memory and
-                * assesses its health. If memory training fails,
-                * the punit will have been instructed to keep the GT powered
-                * down.we won't be able to communicate with it
-                *
-                * If the status check is done before punit updates the register,
-                * it can lead to the system being unusable.
-                * use a timeout and defer the probe to prevent this.
-                */
-               if (time_after(jiffies, timeout)) {
-                       drm_dbg(&xe->drm, "lmem not initialized by firmware\n");
-                       return -EPROBE_DEFER;
-               }
-
-               msleep(20);
-
-       } while (!verify_lmem_ready(xe));
+       /*
+        * The boot firmware initializes local memory and
+        * assesses its health. If memory training fails,
+        * the punit will have been instructed to keep the GT powered
+        * down.we won't be able to communicate with it
+        *
+        * If the status check is done before punit updates the register,
+        * it can lead to the system being unusable.
+        * use a timeout and defer the probe to prevent this.
+        */
+       poll_timeout_us(initializing = lmem_initializing(xe),
+                       initializing <= 0,
+                       20 * USEC_PER_MSEC, TIMEOUT_SEC * USEC_PER_SEC, true);
+       if (initializing < 0)
+               return initializing;
+
+       if (initializing) {
+               drm_dbg(&xe->drm, "lmem not initialized by firmware\n");
+               return -EPROBE_DEFER;
+       }
 
        drm_dbg(&xe->drm, "lmem ready after %ums",
-               jiffies_to_msecs(jiffies - start));
+               jiffies_to_msecs(jiffies - prev_jiffies));
 
        return 0;
 }