All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/xe/mmio: Fix xe_mmio_wait32() to honor delay/sleep maximums
@ 2026-09-29 15:25 Alan Previn
  2026-09-29 16:18 ` sashiko-bot
                   ` (3 more replies)
  0 siblings, 4 replies; 28+ messages in thread
From: Alan Previn @ 2026-09-29 15:25 UTC (permalink / raw)
  To: intel-xe; +Cc: Alan Previn, dri-devel, Matt Roper, Jani Nikula, Rodrigo Vivi

Check for overflow in udelay/usleep_range use in __xe_mmio_wait32
and pick the correct helper according to the wait time and atomic.
Implement a similar helper to replace DIV_ROUND_UP for 32-bit CPUs.
Avoid growing delays becoming intollerably large by capping the
in-loop wait time.

v6: - Fix commit message to remove items dropped in v5. Fix the
      use of MAX_UDELAY_MS for microsecond unit. (Shasiko review).
v5: - Simplify: don't introduce additional redesign and
      use min_t with a backoff to cap wait. (Rodrigo).
v4: - Simplify using poll_timeout_us and poll_timeout_us_atomic and
      update all callers to never use a param for atomic (Jani)
v3: - Use div64_s64 kernel API for 32-bit vs 64-bit division.
v2: - Fixed checkpatch failure.
    - Added helper for 64-bit DIV_ROUND_UP on 32-bit CPU (Shasiko
      review). Fixed bug max range in usleep_range(Shasiko review)

Fixes: 5c09bd6ccd41 ("drm/xe/mmio: Move xe_mmio_wait32() to xe_mmio.c")
Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
Assisted-by: Github-Copilot:Claude-Sonnet-5-0
---
 drivers/gpu/drm/xe/xe_mmio.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c
index 7fa18dfcb5a2..5a03698729ce 100644
--- a/drivers/gpu/drm/xe/xe_mmio.c
+++ b/drivers/gpu/drm/xe/xe_mmio.c
@@ -350,10 +350,11 @@ static int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u
 			wait = ktime_us_delta(end, cur);
 
 		if (atomic)
-			udelay(wait);
+			udelay(min_t(s64, wait, (MAX_UDELAY_MS * 1000)));
 		else
 			usleep_range(wait, wait << 1);
-		wait <<= 1;
+#define __XE_MMIO_WAIT_MAX_BACKOFF_100MS (100 * USEC_PER_MSEC)
+		wait = min_t(s64, wait << 1, __XE_MMIO_WAIT_MAX_BACKOFF_100MS);
 	}
 
 	if (ret != 0) {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread
* [PATCH] drm/xe/mmio: Fix xe_mmio_wait32() to honor delay/sleep maximums
@ 2026-09-29 19:20 Alan Previn
  2026-09-30  3:51 ` Rodrigo Vivi
  0 siblings, 1 reply; 28+ messages in thread
From: Alan Previn @ 2026-09-29 19:20 UTC (permalink / raw)
  To: intel-xe; +Cc: Alan Previn, dri-devel, Matt Roper, Jani Nikula, Rodrigo Vivi

Check for overflow in udelay use in __xe_mmio_wait32 and
avoid growing delays becoming intollerably large by capping the
in-loop wait time.

v7: - Change assisted-by to "LLM" (Rodrigo).
    - Move the max-wait macro to outside the function (Rodrigo).
v6: - Fix commit message to remove items dropped in v5. Fix the
      use of MAX_UDELAY_MS for microsecond unit. (Shasiko review).
v5: - Simplify: don't introduce additional redesign and
      use min_t with a backoff to cap wait. (Rodrigo).
v4: - Simplify using poll_timeout_us and poll_timeout_us_atomic and
      update all callers to never use a param for atomic (Jani)
v3: - Use div64_s64 kernel API for 32-bit vs 64-bit division.
v2: - Fixed checkpatch failure.
    - Added helper for 64-bit DIV_ROUND_UP on 32-bit CPU (Shasiko
      review). Fixed bug max range in usleep_range(Shasiko review)

Fixes: 5c09bd6ccd41 ("drm/xe/mmio: Move xe_mmio_wait32() to xe_mmio.c")
Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Assisted-by: LLM
---
 drivers/gpu/drm/xe/xe_mmio.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c
index 7fa18dfcb5a2..455a07d79cd9 100644
--- a/drivers/gpu/drm/xe/xe_mmio.c
+++ b/drivers/gpu/drm/xe/xe_mmio.c
@@ -320,6 +320,7 @@ 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)
 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)
 {
@@ -350,10 +351,10 @@ static int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u
 			wait = ktime_us_delta(end, cur);
 
 		if (atomic)
-			udelay(wait);
+			udelay(min_t(s64, wait, (MAX_UDELAY_MS * 1000)));
 		else
 			usleep_range(wait, wait << 1);
-		wait <<= 1;
+		wait = min_t(s64, wait << 1, __XE_MMIO_WAIT_MAX_BACKOFF_100MS);
 	}
 
 	if (ret != 0) {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread
* [PATCH] drm/xe/mmio: Fix xe_mmio_wait32() to honor delay/sleep maximums
@ 2026-09-29  5:44 Alan Previn
  2026-09-29  5:49 ` sashiko-bot
  2026-09-29 17:51 ` Rodrigo Vivi
  0 siblings, 2 replies; 28+ messages in thread
From: Alan Previn @ 2026-09-29  5:44 UTC (permalink / raw)
  To: intel-xe; +Cc: Alan Previn, dri-devel, Matt Roper, Jani Nikula, Rodrigo Vivi

Check for overflow in udelay/usleep_range use in __xe_mmio_wait32
and pick the correct helper according to the wait time and atomic.
Implement a similar helper to replace DIV_ROUND_UP for 32-bit CPUs.
Avoid growing delays becoming intollerably large by capping the
in-loop wait time.

v5: - Simplify: don't introduce additional redesign and
      use min_t with a backoff to cap wait. (Rodrigo).
v4: - Simplify using poll_timeout_us and poll_timeout_us_atopmic and
      update all callstack to never use a param for atomic (Jani)
v3: - Use div64_s64 kernel API for 32-bit vs 64-bit division.
v2: - Fixed checkpatch failure.
    - Added helper for 64-bit DIV_ROUND_UP on 32-bit CPU (Shasiko
      review). Fixed bug max range in usleep_range(Shasiko review)

Fixes: 5c09bd6ccd41 ("drm/xe/mmio: Move xe_mmio_wait32() to xe_mmio.c")
Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
Assisted-by: Github-Copilot:Claude-Sonnet-5-0
---
 drivers/gpu/drm/xe/xe_mmio.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c
index 7fa18dfcb5a2..c7c37e59dab0 100644
--- a/drivers/gpu/drm/xe/xe_mmio.c
+++ b/drivers/gpu/drm/xe/xe_mmio.c
@@ -350,10 +350,11 @@ static int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u
 			wait = ktime_us_delta(end, cur);
 
 		if (atomic)
-			udelay(wait);
+			udelay(min_t(s64, wait, MAX_UDELAY_MS));
 		else
 			usleep_range(wait, wait << 1);
-		wait <<= 1;
+#define __XE_MMIO_WAIT_MAX_BACKOFF_100MS (100 * USEC_PER_MSEC)
+		wait = min_t(s64, wait << 1, __XE_MMIO_WAIT_MAX_BACKOFF_100MS);
 	}
 
 	if (ret != 0) {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread
* [PATCH] drm/xe/mmio: Fix xe_mmio_wait32() to honor delay/sleep maximums
@ 2026-09-14 21:57 Alan Previn
  2026-09-14 22:16 ` sashiko-bot
  2026-09-15  7:34 ` Jani Nikula
  0 siblings, 2 replies; 28+ messages in thread
From: Alan Previn @ 2026-09-14 21:57 UTC (permalink / raw)
  To: intel-xe; +Cc: Alan Previn, dri-devel, Matt Roper, Jani Nikula

Check for overflow in udelay/usleep_range use in __xe_mmio_wait32
and pick the correct helper according to the wait time and atomic.
Implement a similar helper to replace DIV_ROUND_UP for 32-bit CPUs.
Avoid growing delays becoming intollerably large by capping the
in-loop wait time.

v4: - Simplify using poll_timeout_us and poll_timeout_us_atopmic and
      update all callstack to never use a param for atomic (Jani)
v3: - Use div64_s64 kernel API for 32-bit vs 64-bit division.
v2: - Fixed checkpatch failure.
    - Added helper for 64-bit DIV_ROUND_UP on 32-bit CPU (Shasiko
      review). Fixed bug max range in usleep_range(Shasiko review)

Fixes: 5c09bd6ccd41 ("drm/xe/mmio: Move xe_mmio_wait32() to xe_mmio.c")
Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
Assisted-by: Github-Copilot:Claude-Sonnet-5-0
---
 drivers/gpu/drm/xe/xe_device.c          |  10 +-
 drivers/gpu/drm/xe/xe_eu_stall.c        |   4 +-
 drivers/gpu/drm/xe/xe_force_wake.c      |   7 +-
 drivers/gpu/drm/xe/xe_gsc.c             |   2 +-
 drivers/gpu/drm/xe/xe_gsc_proxy.c       |   2 +-
 drivers/gpu/drm/xe/xe_gt.c              |   2 +-
 drivers/gpu/drm/xe/xe_gt_mcr.c          |   4 +-
 drivers/gpu/drm/xe/xe_guc.c             |  10 +-
 drivers/gpu/drm/xe/xe_huc.c             |   2 +-
 drivers/gpu/drm/xe/xe_mmio.c            | 118 ++++++++++--------------
 drivers/gpu/drm/xe/xe_mmio.h            |   8 +-
 drivers/gpu/drm/xe/xe_oa.c              |   4 +-
 drivers/gpu/drm/xe/xe_pcode.c           |   8 +-
 drivers/gpu/drm/xe/xe_pxp.c             |   2 +-
 drivers/gpu/drm/xe/xe_sysctrl_mailbox.c |   4 +-
 drivers/gpu/drm/xe/xe_uc_fw.c           |   3 +-
 16 files changed, 90 insertions(+), 100 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 205cb4e7f9e8..8fb044331e62 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -573,7 +573,7 @@ static void __xe_driver_flr(struct xe_device *xe)
 	 * is still pending (unless the HW is totally dead), but better to be
 	 * safe in case something unexpected happens
 	 */
-	ret = xe_mmio_wait32(mmio, GU_CNTL, DRIVERFLR, 0, flr_timeout, NULL, false);
+	ret = xe_mmio_wait32(mmio, GU_CNTL, DRIVERFLR, 0, flr_timeout, NULL);
 	if (ret) {
 		drm_err(&xe->drm, "Driver-FLR-prepare wait for ready failed! %d\n", ret);
 		return;
@@ -584,7 +584,7 @@ static void __xe_driver_flr(struct xe_device *xe)
 	xe_mmio_rmw32(mmio, GU_CNTL, 0, DRIVERFLR);
 
 	/* Wait for hardware teardown to complete */
-	ret = xe_mmio_wait32(mmio, GU_CNTL, DRIVERFLR, 0, flr_timeout, NULL, false);
+	ret = xe_mmio_wait32(mmio, GU_CNTL, DRIVERFLR, 0, flr_timeout, NULL);
 	if (ret) {
 		drm_err(&xe->drm, "Driver-FLR-teardown wait completion failed! %d\n", ret);
 		return;
@@ -592,7 +592,7 @@ static void __xe_driver_flr(struct xe_device *xe)
 
 	/* Wait for hardware/firmware re-init to complete */
 	ret = xe_mmio_wait32(mmio, GU_DEBUG, DRIVERFLR_STATUS, DRIVERFLR_STATUS,
-			     flr_timeout, NULL, false);
+			     flr_timeout, NULL);
 	if (ret) {
 		drm_err(&xe->drm, "Driver-FLR-reinit wait completion failed! %d\n", ret);
 		return;
@@ -1168,7 +1168,7 @@ static void tdf_request_sync(struct xe_device *xe)
 		 * transient and need to be flushed..
 		 */
 		if (xe_mmio_wait32(&gt->mmio, XE2_TDF_CTRL, TRANSIENT_FLUSH_REQUEST, 0,
-				   300, NULL, false))
+					    300, NULL))
 			xe_gt_err_once(gt, "TD flush timeout\n");
 	}
 }
@@ -1214,7 +1214,7 @@ void xe_device_l2_flush(struct xe_device *xe, bool force)
 	spin_lock(&gt->global_invl_lock);
 
 	xe_mmio_write32(&gt->mmio, XE2_GLOBAL_INVAL, 0x1);
-	if (xe_mmio_wait32(&gt->mmio, XE2_GLOBAL_INVAL, 0x1, 0x0, 1000, NULL, true))
+	if (xe_mmio_wait32_atomic(&gt->mmio, XE2_GLOBAL_INVAL, 0x1, 0x0, 1000, NULL))
 		xe_gt_err_once(gt, "Global invalidation timeout\n");
 
 	spin_unlock(&gt->global_invl_lock);
diff --git a/drivers/gpu/drm/xe/xe_eu_stall.c b/drivers/gpu/drm/xe/xe_eu_stall.c
index 8a7c1b5d5ab9..865e08b75c29 100644
--- a/drivers/gpu/drm/xe/xe_eu_stall.c
+++ b/drivers/gpu/drm/xe/xe_eu_stall.c
@@ -707,7 +707,7 @@ static int xe_eu_stall_stream_enable(struct xe_eu_stall_data_stream *stream)
 		/* Request the firmware to apply the workaround and wait for an ACK */
 		xe_mmio_write32(&gt->mmio, SWF_SCRATCHPAD(0), REQ_EUSTALL_ENABLE);
 		ret = xe_mmio_wait32(&gt->mmio, SWF_SCRATCHPAD(0), SWF_EUSTALL_MASK,
-				     ACK_EUSTALL_ENABLE, FW_WA_WAIT_TIMEOUT_US, NULL, false);
+					     ACK_EUSTALL_ENABLE, FW_WA_WAIT_TIMEOUT_US, NULL);
 		if (ret) {
 			xe_gt_err(gt, "Timeout polling for EU stall enable ACK from firmware\n");
 			xe_force_wake_put(gt_to_fw(gt), stream->fw_ref);
@@ -880,7 +880,7 @@ static int xe_eu_stall_disable_locked(struct xe_eu_stall_data_stream *stream)
 		/* Request the firmware to revert the workaround and wait for an ACK */
 		xe_mmio_write32(&gt->mmio, SWF_SCRATCHPAD(0), REQ_EUSTALL_DISABLE);
 		ret = xe_mmio_wait32(&gt->mmio, SWF_SCRATCHPAD(0), SWF_EUSTALL_MASK,
-				     ACK_EUSTALL_DISABLE, FW_WA_WAIT_TIMEOUT_US, NULL, false);
+					     ACK_EUSTALL_DISABLE, FW_WA_WAIT_TIMEOUT_US, NULL);
 		if (ret)
 			xe_gt_err(gt, "Timeout polling for EU stall disable ACK from firmware\n");
 	}
diff --git a/drivers/gpu/drm/xe/xe_force_wake.c b/drivers/gpu/drm/xe/xe_force_wake.c
index 197e2197bd0a..12ab0304509c 100644
--- a/drivers/gpu/drm/xe/xe_force_wake.c
+++ b/drivers/gpu/drm/xe/xe_force_wake.c
@@ -109,9 +109,10 @@ static int __domain_wait(struct xe_gt *gt, struct xe_force_wake_domain *domain,
 	if (IS_SRIOV_VF(gt_to_xe(gt)))
 		return 0;
 
-	ret = xe_mmio_wait32(&gt->mmio, domain->reg_ack, domain->val, wake ? domain->val : 0,
-			     XE_FORCE_WAKE_ACK_TIMEOUT_MS * USEC_PER_MSEC,
-			     &value, true);
+	ret = xe_mmio_wait32_atomic(&gt->mmio, domain->reg_ack, domain->val,
+				    wake ? domain->val : 0,
+				    XE_FORCE_WAKE_ACK_TIMEOUT_MS * USEC_PER_MSEC,
+				    &value);
 	if (ret)
 		xe_gt_err(gt, "Force wake domain %d failed to ack %s (%pe) reg[%#x] = %#x\n",
 			  domain->id, str_wake_sleep(wake), ERR_PTR(ret),
diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c
index 524ac56bdcc7..a43d3739d213 100644
--- a/drivers/gpu/drm/xe/xe_gsc.c
+++ b/drivers/gpu/drm/xe/xe_gsc.c
@@ -196,7 +196,7 @@ static int gsc_fw_wait(struct xe_gt *gt)
 	return xe_mmio_wait32(&gt->mmio, HECI_FWSTS1(MTL_GSC_HECI1_BASE),
 			      HECI1_FWSTS1_INIT_COMPLETE,
 			      HECI1_FWSTS1_INIT_COMPLETE,
-			      500 * USEC_PER_MSEC, NULL, false);
+			   500 * USEC_PER_MSEC, NULL);
 }
 
 static int gsc_upload(struct xe_gsc *gsc)
diff --git a/drivers/gpu/drm/xe/xe_gsc_proxy.c b/drivers/gpu/drm/xe/xe_gsc_proxy.c
index 707db650a2ae..63f72ca28ed4 100644
--- a/drivers/gpu/drm/xe/xe_gsc_proxy.c
+++ b/drivers/gpu/drm/xe/xe_gsc_proxy.c
@@ -80,7 +80,7 @@ int xe_gsc_wait_for_proxy_init_done(struct xe_gsc *gsc)
 	return xe_mmio_wait32(&gt->mmio, HECI_FWSTS1(MTL_GSC_HECI1_BASE),
 			      HECI1_FWSTS1_CURRENT_STATE,
 			      HECI1_FWSTS1_PROXY_STATE_NORMAL,
-			      USEC_PER_SEC, NULL, false);
+			   USEC_PER_SEC, NULL);
 }
 
 static void __gsc_proxy_irq_rmw(struct xe_gsc *gsc, u32 clr, u32 set)
diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
index 775c826b68b4..9edcc54ad4bf 100644
--- a/drivers/gpu/drm/xe/xe_gt.c
+++ b/drivers/gpu/drm/xe/xe_gt.c
@@ -832,7 +832,7 @@ static int do_gt_reset(struct xe_gt *gt)
 	xe_mmio_write32(&gt->mmio, GDRST, GRDOM_FULL);
 	err = xe_mmio_wait32(&gt->mmio, GDRST, GRDOM_FULL, 0,
 			     GRDOM_RESET_TIMEOUT_MS * USEC_PER_MSEC,
-			     NULL, false);
+			   NULL);
 	if (err)
 		xe_log_err(gt, GT, err,
 			   "full graphics reset not completed in %u ms\n",
diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.c b/drivers/gpu/drm/xe/xe_gt_mcr.c
index 1949bf7d370a..a08585f082d3 100644
--- a/drivers/gpu/drm/xe/xe_gt_mcr.c
+++ b/drivers/gpu/drm/xe/xe_gt_mcr.c
@@ -711,8 +711,8 @@ static void mcr_lock(struct xe_gt *gt) __acquires(&gt->mcr_lock)
 	 * when a read to the relevant register returns 1.
 	 */
 	if (GRAPHICS_VERx100(xe) >= 1270)
-		ret = xe_mmio_wait32(&gt->mmio, STEER_SEMAPHORE, 0x1, 0x1, 10, NULL,
-				     true);
+		ret = xe_mmio_wait32_atomic(&gt->mmio, STEER_SEMAPHORE, 0x1, 0x1, 10,
+					    NULL);
 
 	xe_gt_WARN_ON_ONCE(gt, ret == -ETIMEDOUT);
 }
diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c
index c7f8bbd4cb92..670140e1aa36 100644
--- a/drivers/gpu/drm/xe/xe_guc.c
+++ b/drivers/gpu/drm/xe/xe_guc.c
@@ -967,13 +967,13 @@ static void guc_prevent_fw_dma_failure_on_reset(struct xe_guc *guc)
 
 	ret = xe_mmio_wait32(&gt->mmio, GUC_STATUS, GS_UKERNEL_MASK,
 			     FIELD_PREP(GS_UKERNEL_MASK, XE_GUC_LOAD_STATUS_READY),
-			     100000, &guc_status, false);
+				      100000, &guc_status);
 	if (ret)
 		xe_gt_warn(gt, "GuC not ready after disabling idle flow (GUC_STATUS: 0x%x)\n",
 			   guc_status);
 
 	ret = xe_mmio_wait32(&gt->mmio, GUC_SRAM_STATUS, GUC_SRAM_HANDLING_MASK,
-			     0, 5000, &sram_status, false);
+				      0, 5000, &sram_status);
 	if (ret)
 		xe_gt_warn(gt, "SRAM handling not complete (GUC_SRAM_STATUS: 0x%x)\n",
 			   sram_status);
@@ -996,7 +996,7 @@ int xe_guc_reset(struct xe_guc *guc)
 
 	xe_mmio_write32(mmio, GDRST, GRDOM_GUC);
 
-	ret = xe_mmio_wait32(mmio, GDRST, GRDOM_GUC, 0, 5000, &gdrst, false);
+	ret = xe_mmio_wait32(mmio, GDRST, GRDOM_GUC, 0, 5000, &gdrst);
 	if (ret) {
 		xe_gt_err(gt, "GuC reset timed out, GDRST=%#x\n", gdrst);
 		goto err_out;
@@ -1538,7 +1538,7 @@ int xe_guc_mmio_send_recv(struct xe_guc *guc, const u32 *request,
 
 	ret = xe_mmio_wait32(mmio, reply_reg, GUC_HXG_MSG_0_ORIGIN,
 			     FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_GUC),
-			     50000, &header, false);
+				     50000, &header);
 	if (ret) {
 		/* scratch registers might be cleared during FLR, try once more */
 		if (!header) {
@@ -1574,7 +1574,7 @@ int xe_guc_mmio_send_recv(struct xe_guc *guc, const u32 *request,
 		BUILD_BUG_ON((GUC_HXG_TYPE_RESPONSE_SUCCESS ^ GUC_HXG_TYPE_RESPONSE_FAILURE) != 1);
 
 		ret = xe_mmio_wait32(mmio, reply_reg, resp_mask, resp_mask,
-				     2000000, &header, false);
+					     2000000, &header);
 
 		if (unlikely(FIELD_GET(GUC_HXG_MSG_0_ORIGIN, header) !=
 			     GUC_HXG_ORIGIN_GUC))
diff --git a/drivers/gpu/drm/xe/xe_huc.c b/drivers/gpu/drm/xe/xe_huc.c
index 57afe21444b1..3517bba09399 100644
--- a/drivers/gpu/drm/xe/xe_huc.c
+++ b/drivers/gpu/drm/xe/xe_huc.c
@@ -272,7 +272,7 @@ int xe_huc_auth(struct xe_huc *huc, enum xe_huc_auth_types type)
 	}
 
 	ret = xe_mmio_wait32(&gt->mmio, huc_auth_modes[type].reg, huc_auth_modes[type].val,
-			     huc_auth_modes[type].val, 100000, NULL, false);
+			     huc_auth_modes[type].val, 100000, NULL);
 	if (ret) {
 		xe_gt_err(gt, "HuC: firmware not verified: %pe\n", ERR_PTR(ret));
 		goto fail;
diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c
index 7fa18dfcb5a2..fc0509aa384b 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>
 
@@ -320,82 +320,44 @@ u64 xe_mmio_read64_2x32(struct xe_mmio *mmio, struct xe_reg reg)
 	return (u64)udw << 32 | ldw;
 }
 
-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 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);
-
-		if (atomic)
-			udelay(wait);
-		else
-			usleep_range(wait, wait << 1);
-		wait <<= 1;
-	}
-
-	if (ret != 0) {
-		read = xe_mmio_read32(mmio, reg);
-
-		check = (read & mask) == val;
-		if (!expect_match)
-			check = !check;
-
-		if (check)
-			ret = 0;
-	}
-
-	if (out_val)
-		*out_val = read;
-
-	return ret;
-}
-
 /**
  * xe_mmio_wait32() - Wait for a register to match the desired masked value
  * @mmio: MMIO target
  * @reg: register to read value from
  * @mask: mask to be applied to the value read from the register
  * @val: desired value after applying the mask
- * @timeout_us: time out after this period of time. Wait logic tries to be
- * smart, applying an exponential backoff until @timeout_us is reached.
+ * @timeout_us: time out after this period of time
  * @out_val: if not NULL, points where to store the last unmasked value
- * @atomic: needs to be true if calling from an atomic context
  *
  * This function polls for the desired masked value and returns zero on success
  * or -ETIMEDOUT if timed out.
- *
- * Note that @timeout_us represents the minimum amount of time to wait before
- * giving up. The actual time taken by this function can be a little more than
- * @timeout_us for different reasons, specially in non-atomic contexts. Thus,
- * it is possible that this function succeeds even after @timeout_us has passed.
  */
 int xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us,
-		   u32 *out_val, bool atomic)
+		   u32 *out_val)
 {
-	return __xe_mmio_wait32(mmio, reg, mask, val, timeout_us, out_val, atomic, true);
+	u32 read;
+	int ret;
+
+	ret = poll_timeout_us(read = xe_mmio_read32(mmio, reg), (read & mask) == val,
+			      10, timeout_us, false);
+	if (out_val)
+		*out_val = read;
+
+	return ret;
+}
+
+int xe_mmio_wait32_atomic(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val,
+			  u32 timeout_us, u32 *out_val)
+{
+	u32 read;
+	int ret;
+
+	ret = poll_timeout_us_atomic(read = xe_mmio_read32(mmio, reg), (read & mask) == val,
+				     10, timeout_us, false);
+	if (out_val)
+		*out_val = read;
+
+	return ret;
 }
 
 /**
@@ -406,15 +368,35 @@ int xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val, u
  * @val: value not to be matched after applying the mask
  * @timeout_us: time out after this period of time
  * @out_val: if not NULL, points where to store the last unmasked value
- * @atomic: needs to be true if calling from an atomic context
- *
  * This function works exactly like xe_mmio_wait32() with the exception that
  * @val is expected not to be matched.
  */
 int xe_mmio_wait32_not(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us,
-		       u32 *out_val, bool atomic)
+		       u32 *out_val)
 {
-	return __xe_mmio_wait32(mmio, reg, mask, val, timeout_us, out_val, atomic, false);
+	u32 read;
+	int ret;
+
+	ret = poll_timeout_us(read = xe_mmio_read32(mmio, reg), (read & mask) != val,
+			      10, timeout_us, false);
+	if (out_val)
+		*out_val = read;
+
+	return ret;
+}
+
+int xe_mmio_wait32_not_atomic(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val,
+			      u32 timeout_us, u32 *out_val)
+{
+	u32 read;
+	int ret;
+
+	ret = poll_timeout_us_atomic(read = xe_mmio_read32(mmio, reg), (read & mask) != val,
+				     10, timeout_us, false);
+	if (out_val)
+		*out_val = read;
+
+	return ret;
 }
 
 #ifdef CONFIG_PCI_IOV
diff --git a/drivers/gpu/drm/xe/xe_mmio.h b/drivers/gpu/drm/xe/xe_mmio.h
index befe021f2215..6391f0fd6507 100644
--- a/drivers/gpu/drm/xe/xe_mmio.h
+++ b/drivers/gpu/drm/xe/xe_mmio.h
@@ -27,9 +27,13 @@ bool xe_mmio_in_range(const struct xe_mmio *mmio, const struct xe_mmio_range *ra
 
 u64 xe_mmio_read64_2x32(struct xe_mmio *mmio, struct xe_reg reg);
 int xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val,
-		   u32 timeout_us, u32 *out_val, bool atomic);
+		   u32 timeout_us, u32 *out_val);
+int xe_mmio_wait32_atomic(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val,
+			  u32 timeout_us, u32 *out_val);
 int xe_mmio_wait32_not(struct xe_mmio *mmio, struct xe_reg reg, u32 mask,
-		       u32 val, u32 timeout_us, u32 *out_val, bool atomic);
+		       u32 val, u32 timeout_us, u32 *out_val);
+int xe_mmio_wait32_not_atomic(struct xe_mmio *mmio, struct xe_reg reg, u32 mask,
+			      u32 val, u32 timeout_us, u32 *out_val);
 
 static inline u32 xe_mmio_adjusted_addr(const struct xe_mmio *mmio, u32 addr)
 {
diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c
index a3484e943c55..98a6f57701e4 100644
--- a/drivers/gpu/drm/xe/xe_oa.c
+++ b/drivers/gpu/drm/xe/xe_oa.c
@@ -513,14 +513,14 @@ static void xe_oa_disable(struct xe_oa_stream *stream)
 
 	xe_mmio_rmw32(mmio, __oa_regs(stream)->oa_ctrl, __oactrl_used_bits(stream), 0);
 	if (xe_mmio_wait32(mmio, __oa_regs(stream)->oa_ctrl,
-			   OAG_OACONTROL_OA_COUNTER_ENABLE, 0, 50000, NULL, false))
+			   OAG_OACONTROL_OA_COUNTER_ENABLE, 0, 50000, NULL))
 		drm_err(&stream->oa->xe->drm,
 			"wait for OA to be disabled timed out\n");
 
 	if (GRAPHICS_VERx100(stream->oa->xe) <= 1270 && GRAPHICS_VERx100(stream->oa->xe) != 1260) {
 		/* <= XE_METEORLAKE except XE_PVC */
 		xe_mmio_write32(mmio, OA_TLB_INV_CR, 1);
-		if (xe_mmio_wait32(mmio, OA_TLB_INV_CR, 1, 0, 50000, NULL, false))
+		if (xe_mmio_wait32(mmio, OA_TLB_INV_CR, 1, 0, 50000, NULL))
 			drm_err(&stream->oa->xe->drm,
 				"wait for OA tlb invalidate timed out\n");
 	}
diff --git a/drivers/gpu/drm/xe/xe_pcode.c b/drivers/gpu/drm/xe/xe_pcode.c
index 266deecbb100..9b3487c8b07a 100644
--- a/drivers/gpu/drm/xe/xe_pcode.c
+++ b/drivers/gpu/drm/xe/xe_pcode.c
@@ -87,8 +87,12 @@ static int __pcode_mailbox_rw(struct xe_tile *tile, u32 mbox, u32 *data0, u32 *d
 	xe_mmio_write32(mmio, PCODE_DATA1, data1 ? *data1 : 0);
 	xe_mmio_write32(mmio, PCODE_MAILBOX, PCODE_READY | mbox);
 
-	err = xe_mmio_wait32(mmio, PCODE_MAILBOX, PCODE_READY, 0,
-			     timeout_ms * USEC_PER_MSEC, NULL, atomic);
+	if (atomic)
+		err = xe_mmio_wait32_atomic(mmio, PCODE_MAILBOX, PCODE_READY, 0,
+					    timeout_ms * USEC_PER_MSEC, NULL);
+	else
+		err = xe_mmio_wait32(mmio, PCODE_MAILBOX, PCODE_READY, 0,
+				     timeout_ms * USEC_PER_MSEC, NULL);
 	if (err)
 		return err;
 
diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c
index 2fef274a585e..d6b820c47c09 100644
--- a/drivers/gpu/drm/xe/xe_pxp.c
+++ b/drivers/gpu/drm/xe/xe_pxp.c
@@ -136,7 +136,7 @@ static int pxp_wait_for_session_state(struct xe_pxp *pxp, u32 id, bool in_play)
 	u32 mask = BIT(id);
 
 	return xe_mmio_wait32(&gt->mmio, KCR_SIP, mask, in_play ? mask : 0,
-			      250, NULL, false);
+			   250, NULL);
 }
 
 static void pxp_invalidate_queues(struct xe_pxp *pxp);
diff --git a/drivers/gpu/drm/xe/xe_sysctrl_mailbox.c b/drivers/gpu/drm/xe/xe_sysctrl_mailbox.c
index 72baf1aa4b3a..269ec70aa22a 100644
--- a/drivers/gpu/drm/xe/xe_sysctrl_mailbox.c
+++ b/drivers/gpu/drm/xe/xe_sysctrl_mailbox.c
@@ -40,7 +40,7 @@ static bool sysctrl_wait_bit_clear(struct xe_sysctrl *sc, u32 bit_mask,
 	int ret;
 
 	ret = xe_mmio_wait32_not(sc->mmio, SYSCTRL_MB_CTRL, bit_mask, bit_mask,
-				 timeout_ms * 1000, NULL, false);
+				   timeout_ms * 1000, NULL);
 
 	return ret == 0;
 }
@@ -51,7 +51,7 @@ static bool sysctrl_wait_bit_set(struct xe_sysctrl *sc, u32 bit_mask,
 	int ret;
 
 	ret = xe_mmio_wait32(sc->mmio, SYSCTRL_MB_CTRL, bit_mask, bit_mask,
-			     timeout_ms * 1000, NULL, false);
+			     timeout_ms * 1000, NULL);
 
 	return ret == 0;
 }
diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c
index e29878b255ba..8fa8a02f73bc 100644
--- a/drivers/gpu/drm/xe/xe_uc_fw.c
+++ b/drivers/gpu/drm/xe/xe_uc_fw.c
@@ -899,8 +899,7 @@ static int uc_fw_xfer(struct xe_uc_fw *uc_fw, u32 offset, u32 dma_flags)
 			REG_MASKED_FIELD_ENABLE(dma_flags | START_DMA));
 
 	/* Wait for DMA to finish */
-	ret = xe_mmio_wait32(mmio, DMA_CTRL, START_DMA, 0, 100000, &dma_ctrl,
-			     false);
+	ret = xe_mmio_wait32(mmio, DMA_CTRL, START_DMA, 0, 100000, &dma_ctrl);
 	if (ret)
 		drm_err(&xe->drm, "DMA for %s fw failed, DMA_CTRL=%u\n",
 			xe_uc_fw_type_repr(uc_fw->type), dma_ctrl);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread
* [PATCH] drm/xe/mmio: Fix xe_mmio_wait32() to honor delay/sleep maximums
@ 2026-09-08 20:33 Alan Previn
  0 siblings, 0 replies; 28+ messages in thread
From: Alan Previn @ 2026-09-08 20:33 UTC (permalink / raw)
  To: intel-xe; +Cc: Alan Previn, dri-devel, Matt Roper

Check for overflow in udelay/usleep_range use in __xe_mmio_wait32
and pick the correct helper according to the wait time and atomic.
Implement a similar helper to replace DIV_ROUND_UP for 32-bit CPUs.
Avoid growing delays becoming intollerably large by capping the
in-loop wait time.

v3: - Use div64_s64 kernel API for 32-bit vs 64-bit division.
v2: - Fixed checkpatch failure.
    - Added helper for 64-bit DIV_ROUND_UP on 32-bit CPU (Shasiko
      review). Fixed bug max range in usleep_range(Shasiko review)

Fixes: 5c09bd6ccd41 ("drm/xe/mmio: Move xe_mmio_wait32() to xe_mmio.c")
Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
Assisted-by: Github-Copilot:Claude-Sonnet-5-0
---
 drivers/gpu/drm/xe/xe_mmio.c | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c
index 7fa18dfcb5a2..507095f33cec 100644
--- a/drivers/gpu/drm/xe/xe_mmio.c
+++ b/drivers/gpu/drm/xe/xe_mmio.c
@@ -7,6 +7,7 @@
 
 #include <linux/delay.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/math64.h>
 #include <linux/minmax.h>
 #include <linux/pci.h>
 
@@ -349,11 +350,23 @@ static int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u
 		if (ktime_after(ktime_add_us(cur, wait), end))
 			wait = ktime_us_delta(end, cur);
 
-		if (atomic)
-			udelay(wait);
-		else
-			usleep_range(wait, wait << 1);
-		wait <<= 1;
+#define __XE_MMIO_WAIT_MAX_INLOOP_100MS (100 * USEC_PER_MSEC)
+		if (atomic) {
+			if (wait <= MAX_UDELAY_MS * USEC_PER_MSEC)
+				udelay(wait);
+			else
+				mdelay(div64_s64(wait, USEC_PER_MSEC));
+		} else {
+			usleep_range(wait, wait + (wait >> 2)); /* range till wait + 25% */
+		}
+		/*
+		 * As we keep doubling the wait time for every check that fails, cap the
+		 * in-loop delay-or-sleep to less than 2x 100 milliseconds to prevent from
+		 * expanding 'wait' into exponentially longer wait times per loop that
+		 * end up delaying the next completion check way later than tolerable.
+		 */
+		wait = wait < __XE_MMIO_WAIT_MAX_INLOOP_100MS >> 1 ?
+		       wait << 1 : __XE_MMIO_WAIT_MAX_INLOOP_100MS;
 	}
 
 	if (ret != 0) {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread
* [PATCH] drm/xe/mmio: Fix xe_mmio_wait32() to honor delay/sleep maximums
@ 2026-09-08 18:56 Alan Previn
  2026-09-08 19:03 ` sashiko-bot
  2026-09-09  8:00 ` Jani Nikula
  0 siblings, 2 replies; 28+ messages in thread
From: Alan Previn @ 2026-09-08 18:56 UTC (permalink / raw)
  To: intel-xe; +Cc: Alan Previn, dri-devel, Matt Roper

Check for overflow in udelay/usleep_range use in __xe_mmio_wait32
and pick the correct helper according to the wait time and atomic.
Implement a similar helper to replace DIV_ROUND_UP for 32-bit CPUs.
Avoid growing delays becoming intollerably large by capping the
in-loop wait time.

v2: - Fixed checkpatch failure.
    - Added helper for 64-bit DIV_ROUND_UP on 32-bit CPU (Shasiko
      review). Fixed bug max range in usleep_range(Shasiko review)

Fixes: 5c09bd6ccd41 ("drm/xe/mmio: Move xe_mmio_wait32() to xe_mmio.c")
Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
Assisted-by: Github-Copilot:Claude-Sonnet-5-0
---
 drivers/gpu/drm/xe/xe_mmio.c | 50 ++++++++++++++++++++++++++++++++----
 1 file changed, 45 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c
index 7fa18dfcb5a2..1ae382f009de 100644
--- a/drivers/gpu/drm/xe/xe_mmio.c
+++ b/drivers/gpu/drm/xe/xe_mmio.c
@@ -7,6 +7,8 @@
 
 #include <linux/delay.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/math.h>
+#include <linux/math64.h>
 #include <linux/minmax.h>
 #include <linux/pci.h>
 
@@ -320,6 +322,30 @@ u64 xe_mmio_read64_2x32(struct xe_mmio *mmio, struct xe_reg reg)
 	return (u64)udw << 32 | ldw;
 }
 
+/**
+ * __div_round_up64() - alternative to DIV_ROUND_UP for use by __xe_mmio_wait32
+ * @dividend: 64 bit positive number to divide
+ * @divisor: 64 bit positive divisor
+ *
+ * DIV_ROUND_UP() relies on plain '/' and '%' operators, which for 64-bit
+ * operands on a 32-bit CPU get turned into calls to libgcc's __divdi3()/
+ * __moddi3(), routines the kernel does not link against. Provide a
+ * do_div()-based equivalent that works for signed 64-bit inputs on any
+ * architecture.
+ *
+ * Returns: rounded up division result
+ */
+static inline s64 __div_round_up64(s64 dividend, s64 divisor)
+{
+	u64 abs_dividend = abs(dividend);
+	u64 abs_divisor = abs(divisor);
+	u64 result = abs_dividend + abs_divisor - 1;
+
+	do_div(result, abs_divisor);
+	/* dont check for negative values as local caller only uses positive numbers */
+	return (s64)result;
+}
+
 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)
 {
@@ -349,11 +375,25 @@ static int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u
 		if (ktime_after(ktime_add_us(cur, wait), end))
 			wait = ktime_us_delta(end, cur);
 
-		if (atomic)
-			udelay(wait);
-		else
-			usleep_range(wait, wait << 1);
-		wait <<= 1;
+#define __XE_MMIO_WAIT_MAX_INLOOP_100MS (100 * USEC_PER_MSEC)
+		if (atomic) {
+			if (wait <= MAX_UDELAY_MS * USEC_PER_MSEC)
+				udelay(wait);
+			else if (BITS_PER_LONG == 32)
+				mdelay(DIV_ROUND_UP(wait, USEC_PER_MSEC));
+			else
+				mdelay(__div_round_up64(wait, USEC_PER_MSEC));
+		} else {
+			usleep_range(wait, wait + (wait >> 2)); /* range till wait + 25% */
+		}
+		/*
+		 * As we keep doubling the wait time for every check that fails, cap the
+		 * in-loop delay-or-sleep to less than 2x 100 milliseconds to prevent from
+		 * expanding 'wait' into exponentially longer wait times per loop that
+		 * end up delaying the next completion check way later than tolerable.
+		 */
+		wait = wait < __XE_MMIO_WAIT_MAX_INLOOP_100MS >> 1 ?
+		       wait << 1 : __XE_MMIO_WAIT_MAX_INLOOP_100MS;
 	}
 
 	if (ret != 0) {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread
* [PATCH] drm/xe/mmio: Fix xe_mmio_wait32() to honor delay/sleep maximums
@ 2026-09-07 23:55 Alan Previn
  2026-09-08  0:02 ` sashiko-bot
  0 siblings, 1 reply; 28+ messages in thread
From: Alan Previn @ 2026-09-07 23:55 UTC (permalink / raw)
  To: intel-xe; +Cc: Alan Previn, dri-devel, Matt Roper

Check for overflow in udelay/usleep_range use in __xe_mmio_wait32
and pick the correct helper accordingly. Fix sign-overflow and avoid
growing delays becoming intollerably large by capping the in-loop
wait time. Simplify sleep_min assignment by removing redundant cast.

Fixes: 5c09bd6ccd41 ("drm/xe/mmio: Move xe_mmio_wait32() to xe_mmio.c")
Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
Assisted-by: Github-Copilot:Claude-Sonnet-4-6
---
 drivers/gpu/drm/xe/xe_mmio.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c
index 7fa18dfcb5a2..cf2e05aaa4b2 100644
--- a/drivers/gpu/drm/xe/xe_mmio.c
+++ b/drivers/gpu/drm/xe/xe_mmio.c
@@ -349,11 +349,23 @@ static int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u
 		if (ktime_after(ktime_add_us(cur, wait), end))
 			wait = ktime_us_delta(end, cur);
 
-		if (atomic)
-			udelay(wait);
-		else
-			usleep_range(wait, wait << 1);
-		wait <<= 1;
+#define __XE_MMIO_WAIT_MAX_INLOOP_TIME (100 * USEC_PER_MSEC)
+		if (atomic) {
+			if (wait <= MAX_UDELAY_MS * USEC_PER_MSEC)
+				udelay(wait);
+			else
+				mdelay(DIV_ROUND_UP(wait, USEC_PER_MSEC));
+		} else {
+			usleep_range(wait, __XE_MMIO_WAIT_MAX_INLOOP_TIME);
+		}
+		/*
+		 * As we keep doubling the wait time for every check that fails, cap the
+		 * in-loop delay-or-sleep to less than 2x 100 miliseconds to prevent from
+		 * expanding 'wait' into exponentially longer wait times per loop that
+		 * end up delaying the next completion check way later than tolerable.
+		 */
+		wait = wait < __XE_MMIO_WAIT_MAX_INLOOP_TIME >> 1 ?
+		       wait << 1 : __XE_MMIO_WAIT_MAX_INLOOP_TIME;
 	}
 
 	if (ret != 0) {

base-commit: 71bc3b7cc55631a9b3807da98e2b2880838b9623
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2026-09-30  3:51 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-29 15:25 [PATCH] drm/xe/mmio: Fix xe_mmio_wait32() to honor delay/sleep maximums Alan Previn
2026-09-29 16:18 ` sashiko-bot
2026-09-29 19:07   ` Teres Alexis, Alan Previn
2026-09-29 16:19 ` ✓ CI.KUnit: success for drm/xe/mmio: Fix xe_mmio_wait32() to honor delay/sleep maximums (rev6) Patchwork
2026-09-29 17:35 ` ✓ Xe.CI.BAT: " Patchwork
2026-09-29 21:03 ` ✗ Xe.CI.FULL: failure " Patchwork
  -- strict thread matches above, loose matches on Subject: below --
2026-09-29 19:20 [PATCH] drm/xe/mmio: Fix xe_mmio_wait32() to honor delay/sleep maximums Alan Previn
2026-09-30  3:51 ` Rodrigo Vivi
2026-09-29  5:44 Alan Previn
2026-09-29  5:49 ` sashiko-bot
2026-09-29 17:51 ` Rodrigo Vivi
2026-09-14 21:57 Alan Previn
2026-09-14 22:16 ` sashiko-bot
2026-09-15  7:34 ` Jani Nikula
2026-09-15 16:00   ` Teres Alexis, Alan Previn
2026-09-15 16:43     ` Jani Nikula
2026-09-15 22:51     ` Rodrigo Vivi
2026-09-16 19:10       ` Teres Alexis, Alan Previn
2026-09-17  0:54         ` Rodrigo Vivi
2026-09-17  2:07           ` Teres Alexis, Alan Previn
2026-09-17 18:49             ` Teres Alexis, Alan Previn
2026-09-08 20:33 Alan Previn
2026-09-08 18:56 Alan Previn
2026-09-08 19:03 ` sashiko-bot
2026-09-09  8:00 ` Jani Nikula
2026-09-11  0:05   ` Teres Alexis, Alan Previn
2026-09-07 23:55 Alan Previn
2026-09-08  0:02 ` sashiko-bot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.