From: fei.yang@intel.com
To: intel-xe@lists.freedesktop.org
Cc: Fei Yang <fei.yang@intel.com>,
Matthew Brost <matthew.brost@intel.com>,
Stuart Summers <stuart.summers@intel.com>,
Roper Matthew D <matthew.d.roper@intel.com>
Subject: [PATCH 1/1 v4] drm/xe: Wait for HW clearance before issuing the next TLB inval.
Date: Wed, 24 Jun 2026 15:51:04 -0700 [thread overview]
Message-ID: <20260624225105.2355641-2-fei.yang@intel.com> (raw)
In-Reply-To: <20260624225105.2355641-1-fei.yang@intel.com>
From: Fei Yang <fei.yang@intel.com>
Hardware requires the software to poll the valid bit and make sure
it's cleared before issuing a new TLB invalidation request.
We also need to avoid racing against GuC on TLB invalidations. In
order to achieve that, check for pending TLB invalidation in tlb_inval
list.
Signed-off-by: Fei Yang <fei.yang@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Stuart Summers <stuart.summers@intel.com>
Cc: Roper Matthew D <matthew.d.roper@intel.com>
---
drivers/gpu/drm/xe/xe_guc_tlb_inval.c | 70 +++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
index cf6d106e6036..815fbd059112 100644
--- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
+++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
@@ -8,6 +8,7 @@
#include "xe_device.h"
#include "xe_exec_queue.h"
#include "xe_exec_queue_types.h"
+#include "xe_gt_printk.h"
#include "xe_gt_stats.h"
#include "xe_gt_types.h"
#include "xe_guc.h"
@@ -60,6 +61,12 @@ static int send_tlb_inval_all(struct xe_tlb_inval *tlb_inval, u32 seqno)
static int send_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval, u32 seqno)
{
+ /*
+ * Timeout for MMIO-based TLB invalidation polling. Make it 250ms
+ * based on hw_tlb_timeout = HZ/4 defined in tlb_inval_timeout_delay().
+ */
+ const long hw_tlb_timeout = HZ / 4;
+
struct xe_guc *guc = tlb_inval->private;
struct xe_gt *gt = guc_to_gt(guc);
struct xe_device *xe = guc_to_xe(guc);
@@ -79,19 +86,82 @@ static int send_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval, u32 seqno)
return send_tlb_inval(guc, action, ARRAY_SIZE(action));
} else if (xe_device_uc_enabled(xe) && !xe_device_wedged(xe)) {
struct xe_mmio *mmio = >->mmio;
+ int err;
if (IS_SRIOV_VF(xe))
return -ECANCELED;
+ /*
+ * seqno_lock serializes MMIO-based TLB invalidations to prevent
+ * races between concurrent requests issued through GuC CT and
+ * direct MMIO writes.
+ */
+ lockdep_assert_held(&tlb_inval->seqno_lock);
+
+ /*
+ * If there are pending GuC TLB invalidation requests MMIO-based
+ * requests should be avoided.
+ */
+ if (!xe_tlb_inval_idle(tlb_inval)) {
+ xe_gt_dbg(gt, "MMIO TLB INV skipped due to pending GuC INv\n");
+ return -ECANCELED;
+ }
+
CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
if (xe->info.platform == XE_PVC || GRAPHICS_VER(xe) >= 20) {
+ /*
+ * HW requires the valid bit to be clear before writing a
+ * new request.
+ */
+ err = xe_mmio_wait32(mmio, PVC_GUC_TLB_INV_DESC0,
+ PVC_GUC_TLB_INV_DESC0_VALID, 0,
+ hw_tlb_timeout, NULL, false);
+ if (err) {
+ xe_gt_err(gt, "MMIO TLB INV pre-write poll timeout\n");
+ return -ECANCELED;
+ }
+
xe_mmio_write32(mmio, PVC_GUC_TLB_INV_DESC1,
PVC_GUC_TLB_INV_DESC1_INVALIDATE);
xe_mmio_write32(mmio, PVC_GUC_TLB_INV_DESC0,
PVC_GUC_TLB_INV_DESC0_VALID);
+
+ /*
+ * Poll for clearance of the valid bit after writing to
+ * ensure the request has been consumed and to avoid races
+ * between TLB invalidation through GuC and MMIO.
+ */
+ err = xe_mmio_wait32(mmio, PVC_GUC_TLB_INV_DESC0,
+ PVC_GUC_TLB_INV_DESC0_VALID, 0,
+ hw_tlb_timeout, NULL, false);
+ if (err)
+ xe_gt_err(gt, "MMIO TLB INV post-write poll timeout\n");
} else {
+ /*
+ * HW requires the valid bit to be clear before writing a
+ * new request.
+ */
+ err = xe_mmio_wait32(mmio, GUC_TLB_INV_CR,
+ GUC_TLB_INV_CR_INVALIDATE, 0,
+ hw_tlb_timeout, NULL, false);
+ if (err) {
+ xe_gt_err(gt, "MMIO TLB INV pre-write poll timeout\n");
+ return -ECANCELED;
+ }
+
xe_mmio_write32(mmio, GUC_TLB_INV_CR,
GUC_TLB_INV_CR_INVALIDATE);
+
+ /*
+ * Poll for clearance of the valid bit after writing to
+ * ensure the request has been consumed and to avoid races
+ * between TLB invalidation through GuC and MMIO.
+ */
+ err = xe_mmio_wait32(mmio, GUC_TLB_INV_CR,
+ GUC_TLB_INV_CR_INVALIDATE, 0,
+ hw_tlb_timeout, NULL, false);
+ if (err)
+ xe_gt_err(gt, "MMIO TLB INV post-write poll timeout\n");
}
}
--
2.43.0
next prev parent reply other threads:[~2026-06-24 22:47 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-24 22:51 [PATCH 0/1 v4] drm/xe: Wait for HW clearance before issuing the next TLB inval fei.yang
2026-06-24 22:51 ` fei.yang [this message]
2026-06-24 23:00 ` ✓ CI.KUnit: success for " Patchwork
2026-06-25 0:37 ` ✗ Xe.CI.BAT: 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=20260624225105.2355641-2-fei.yang@intel.com \
--to=fei.yang@intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=matthew.brost@intel.com \
--cc=matthew.d.roper@intel.com \
--cc=stuart.summers@intel.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox