All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Charles <daniel.charles@intel.com>
To: intel-xe@lists.freedesktop.org
Cc: Daniel Charles <daniel.charles@intel.com>
Subject: [PATCH v2 2/3] drm/xe/wedge: preserve pending TLB invalidations during inspection
Date: Fri,  6 Nov 2026 14:13:22 -0800	[thread overview]
Message-ID: <20261106221323.1207676-3-daniel.charles@intel.com> (raw)
In-Reply-To: <20261106221323.1207676-1-daniel.charles@intel.com>

Pause TLB invalidation timeout and completion processing when the mode-3
inspection worker stops a GT. Keep pending invalidation fences unsignaled
during inspection rather than resetting them as part of the GT stop.

CONTINUE resets the preserved invalidations as part of completing permanent
wedging; SKIP leaves them paused with the GTs stopped. Ordinary GT wedging
retains its existing TLB reset behavior.

Preservation does not freeze subsequent mapping management or change the
existing cancellation and GGTT MMIO fallback behavior for new requests.
Inspection is best-effort, not an atomic snapshot.

Document that preserved fences can block process exit, unbind or unload,
and that a power cycle may be necessary. Inspection has no automatic
timeout, and SKIP does not restore normal operation.

Assisted-by: LLM
Signed-off-by: Daniel Charles <daniel.charles@intel.com>
---
 drivers/gpu/drm/xe/xe_debugfs.c         |  7 ++++++
 drivers/gpu/drm/xe/xe_gt.c              |  2 +-
 drivers/gpu/drm/xe/xe_tlb_inval.c       | 33 +++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_tlb_inval.h       |  1 +
 drivers/gpu/drm/xe/xe_tlb_inval_types.h |  2 ++
 drivers/gpu/drm/xe/xe_wedge.c           |  5 ++++
 drivers/gpu/drm/xe/xe_wedge_types.h     |  7 +++++-
 7 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c
index 2b0b2135e0184..f5b761e89b3a2 100644
--- a/drivers/gpu/drm/xe/xe_debugfs.c
+++ b/drivers/gpu/drm/xe/xe_debugfs.c
@@ -749,6 +749,13 @@ void xe_debugfs_register(struct xe_device *xe)
 	 * hibernation: releasing inspection does not restore normal operation.
 	 * Skip is not recovery: GTs remain stopped. Inspection has no automatic
 	 * timeout. Continue completes permanent wedging, not normal execution.
+	 * TLB preservation does not freeze mapping changes or gate new
+	 * invalidations. New requests may be canceled and signaled while older
+	 * fences remain preserved. GGTT invalidations may still program MMIO
+	 * with CT disabled; signaling on cancellation does not imply hardware
+	 * completion. Inspection is best-effort, not an atomic snapshot.
+	 * Preserved TLB fences may block process exit, unbind or unload; a power
+	 * cycle may be necessary. Automatic recovery is not guaranteed.
 	 */
 	debugfs_create_file("wedged_pause_resume", 0200, root, xe,
 			    &wedged_pause_resume_fops);
diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
index a84fa80e9fa9b..8be2053e6cb01 100644
--- a/drivers/gpu/drm/xe/xe_gt.c
+++ b/drivers/gpu/drm/xe/xe_gt.c
@@ -1212,7 +1212,7 @@ void xe_gt_wedge_pause(struct xe_gt *gt)
 {
 	xe_gt_assert(gt, READ_ONCE(gt_to_xe(gt)->wedged.mode) ==
 		     XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET_WAIT_FOR_RELEASE);
+	xe_tlb_inval_debug_pause(&gt->tlb_inval);
 	xe_uc_reset_prepare(&gt->uc);
 	xe_uc_wedge_declare(&gt->uc);
-	xe_tlb_inval_reset(&gt->tlb_inval);
 }
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval.c b/drivers/gpu/drm/xe/xe_tlb_inval.c
index c9cc5842d65b6..293929f92eb0f 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval.c
+++ b/drivers/gpu/drm/xe/xe_tlb_inval.c
@@ -83,9 +83,17 @@ static void xe_tlb_inval_fence_timeout(struct work_struct *work)
 	long timeout_delay = tlb_inval->ops->timeout_delay(tlb_inval);
 	int timedout_seqno = 0, seqno_recv = 0;
 
+	spin_lock_irq(&tlb_inval->pending_lock);
+	if (tlb_inval->debug_paused)
+		goto out_unlock;
+	spin_unlock_irq(&tlb_inval->pending_lock);
+
 	tlb_inval->ops->flush(tlb_inval);
 
 	spin_lock_irq(&tlb_inval->pending_lock);
+	if (tlb_inval->debug_paused)
+		goto out_unlock;
+
 	list_for_each_entry_safe(fence, next,
 				 &tlb_inval->pending_fences, link) {
 		s64 since_inval_ms = ktime_ms_delta(ktime_get(),
@@ -124,6 +132,7 @@ static void xe_tlb_inval_fence_timeout(struct work_struct *work)
 		queue_delayed_work(tlb_inval->timeout_wq, &tlb_inval->fence_tdr,
 				   timeout_delay);
 	seqno_recv = tlb_inval->seqno_recv;
+out_unlock:
 	spin_unlock_irq(&tlb_inval->pending_lock);
 
 	/*
@@ -184,6 +193,7 @@ int xe_gt_tlb_inval_init_early(struct xe_gt *gt)
 	tlb_inval->seqno = 1;
 	INIT_LIST_HEAD(&tlb_inval->pending_fences);
 	spin_lock_init(&tlb_inval->pending_lock);
+	tlb_inval->debug_paused = false;
 	spin_lock_init(&tlb_inval->lock);
 	INIT_DELAYED_WORK(&tlb_inval->fence_tdr, xe_tlb_inval_fence_timeout);
 
@@ -209,6 +219,24 @@ int xe_gt_tlb_inval_init_early(struct xe_gt *gt)
 	return drmm_add_action_or_reset(&xe->drm, tlb_inval_fini, tlb_inval);
 }
 
+/**
+ * xe_tlb_inval_debug_pause() - Preserve pending invalidations for inspection
+ * @tlb_inval: TLB invalidation client
+ *
+ * A reset ends this pause even while inspection waits for a reply.
+ * Holding a runtime PM reference does not prevent system suspend.
+ */
+void xe_tlb_inval_debug_pause(struct xe_tlb_inval *tlb_inval)
+{
+	if (!tlb_inval->ops->initialized(tlb_inval))
+		return;
+
+	spin_lock_irq(&tlb_inval->pending_lock);
+	tlb_inval->debug_paused = true;
+	cancel_delayed_work(&tlb_inval->fence_tdr);
+	spin_unlock_irq(&tlb_inval->pending_lock);
+}
+
 /**
  * xe_tlb_inval_reset() - TLB invalidation reset
  * @tlb_inval: TLB invalidation client
@@ -235,6 +263,7 @@ void xe_tlb_inval_reset(struct xe_tlb_inval *tlb_inval)
 
 	mutex_lock(&tlb_inval->seqno_lock);
 	spin_lock_irq(&tlb_inval->pending_lock);
+	tlb_inval->debug_paused = false;
 	cancel_delayed_work(&tlb_inval->fence_tdr);
 	/*
 	 * We might have various kworkers waiting for TLB flushes to complete
@@ -464,6 +493,10 @@ void xe_tlb_inval_done_handler(struct xe_tlb_inval *tlb_inval, int seqno)
 	 * process_g2h_msg().
 	 */
 	spin_lock_irqsave(&tlb_inval->pending_lock, flags);
+	if (tlb_inval->debug_paused) {
+		spin_unlock_irqrestore(&tlb_inval->pending_lock, flags);
+		return;
+	}
 	if (seqno == TLB_INVALIDATION_SEQNO_INVALID) {
 		xe_tlb_inval_reset_timeout(tlb_inval);
 		spin_unlock_irqrestore(&tlb_inval->pending_lock, flags);
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval.h b/drivers/gpu/drm/xe/xe_tlb_inval.h
index 665072b4b81dc..65bb2f6e530b5 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval.h
+++ b/drivers/gpu/drm/xe/xe_tlb_inval.h
@@ -17,6 +17,7 @@ struct xe_vm;
 int xe_gt_tlb_inval_init_early(struct xe_gt *gt);
 
 void xe_tlb_inval_reset(struct xe_tlb_inval *tlb_inval);
+void xe_tlb_inval_debug_pause(struct xe_tlb_inval *tlb_inval);
 int xe_tlb_inval_all(struct xe_tlb_inval *tlb_inval,
 		     struct xe_tlb_inval_fence *fence);
 int xe_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval);
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_types.h b/drivers/gpu/drm/xe/xe_tlb_inval_types.h
index 80d2019fa20b4..7ccd66c2eea7a 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval_types.h
+++ b/drivers/gpu/drm/xe/xe_tlb_inval_types.h
@@ -112,6 +112,8 @@ struct xe_tlb_inval {
 	 * @pending_lock: protects @pending_fences and updating @seqno_recv.
 	 */
 	spinlock_t pending_lock;
+	/** @debug_paused: Preserve mode-3 pending state under pending_lock. */
+	bool debug_paused;
 	/**
 	 * @timedout_seqno: seqno of the most recent timed out TLB
 	 * invalidation, 0 if none. Used to measure how late the ack for a
diff --git a/drivers/gpu/drm/xe/xe_wedge.c b/drivers/gpu/drm/xe/xe_wedge.c
index 8bfe0e2775d29..09ca1708fe5a5 100644
--- a/drivers/gpu/drm/xe/xe_wedge.c
+++ b/drivers/gpu/drm/xe/xe_wedge.c
@@ -17,6 +17,7 @@
 #include "xe_pm.h"
 #include "xe_printk.h"
 #include "xe_sriov.h"
+#include "xe_tlb_inval.h"
 #include "xe_wedge.h"
 
 /**
@@ -115,6 +116,9 @@ static void wedge_declare_now(struct xe_device *xe, unsigned long method,
 	if (!gts_already_wedged) {
 		for_each_initialized_gt(gt, xe, id)
 			xe_gt_wedge_declare(gt);
+	} else {
+		for_each_initialized_gt(gt, xe, id)
+			xe_tlb_inval_reset(&gt->tlb_inval);
 	}
 
 	/*
@@ -208,6 +212,7 @@ static void wedge_pause_work(struct work_struct *work)
 
 	xe_err(xe, "GT submission stopped for mode-3 hardware debugging.\n"
 	       "New DRM ioctls are blocked while waiting for 'wedged_pause_resume'.\n"
+	       "Pending TLB invalidations are preserved until continue or another reset.\n"
 	       "Skip: 0x%08x; continue into permanent wedge: 0x%08x.\n"
 	       "Skip does not restart GTs or recover the fault.\n",
 	       XE_WEDGE_REPLY_SKIP, XE_WEDGE_REPLY_CONTINUE);
diff --git a/drivers/gpu/drm/xe/xe_wedge_types.h b/drivers/gpu/drm/xe/xe_wedge_types.h
index 4fe03efffbdab..34d6d1b471271 100644
--- a/drivers/gpu/drm/xe/xe_wedge_types.h
+++ b/drivers/gpu/drm/xe/xe_wedge_types.h
@@ -31,7 +31,12 @@ enum xe_wedged_mode {
 	XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET_WAIT_FOR_RELEASE = 3,
 };
 
-/* Skip releases inspection without recovering the fault or restarting GTs. */
+/*
+ * Skip releases inspection without recovering the fault or restarting GTs.
+ * Pending TLB invalidations remain paused; fence waiters may block indefinitely.
+ * Later resets are possible, but automatic recovery is not guaranteed.
+ * Continue resets deferred invalidations and completes permanent wedging.
+ */
 #define XE_WEDGE_REPLY_CONTINUE 0xdeadbbbb
 #define XE_WEDGE_REPLY_SKIP 0xdeadf001
 
-- 
2.43.0


  parent reply	other threads:[~2026-11-06 22:17 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-06 22:13 [PATCH v2 0/3] drm/xe: add wedged_mode=3 fault inspection Daniel Charles
2026-11-06 22:13 ` [PATCH v2 1/3] drm/xe/wedge: add fault inspection with debugfs release Daniel Charles
2026-11-06 22:59   ` sashiko-bot
2026-11-06 22:13 ` Daniel Charles [this message]
2026-11-06 22:13 ` [PATCH v2 3/3] drm/xe/wedge: request inspection for additional fault paths Daniel Charles
2026-11-06 22:40 ` ✗ CI.checkpatch: warning for drm/xe: add wedged_mode=3 fault inspection Patchwork
2026-11-06 22:42 ` ✓ CI.KUnit: success " Patchwork
2026-11-06 23:16 ` ✓ Xe.CI.BAT: " Patchwork
2026-11-08  3:36 ` ✗ Xe.CI.FULL: failure " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261106221323.1207676-3-daniel.charles@intel.com \
    --to=daniel.charles@intel.com \
    --cc=intel-xe@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.