Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Stuart Summers <stuart.summers@intel.com>
Cc: intel-xe@lists.freedesktop.org, rodrigo.vivi@intel.com,
	matthew.brost@intel.com, matthew.d.roper@intel.com,
	fei.yang@intel.com, Stuart Summers <stuart.summers@intel.com>
Subject: [PATCH 07/11] drm/xe: Run page table updates on the media GT when there is no primary
Date: Tue, 10 Nov 2026 23:14:49 +0000	[thread overview]
Message-ID: <20261110231442.218721-20-stuart.summers@intel.com> (raw)
In-Reply-To: <20261110231442.218721-13-stuart.summers@intel.com>

The tile's migration context, and the bind exec queues built on top of
it, are hard wired to the primary GT and its copy engine.  On a device
with no graphics IP that GT is NULL, and xe_migrate_init() is never
called at all, so probe dies in xe_cpu_bind_init() on an uninitialised
tile->migrate.

Page table updates are plain memory writes, so any GT can issue them.
Add xe_tile_pt_gt() and xe_tile_pt_class(), which name the primary GT and
its copy engine as before but fall back to the media GT and a video
decode engine, and use them for the migration context, the bind queues
and the place xe_gt_init() decides to set migration up.

Note this only makes page table updates work.  The blit based copy and
clear paths now target a video engine rather than NULL on such a device,
which stops them oopsing, but they are still not functional there.

Signed-off-by: Stuart Summers <stuart.summers@intel.com>
---
 drivers/gpu/drm/xe/xe_exec_queue.c |  5 +++--
 drivers/gpu/drm/xe/xe_gt.c         | 11 ++++++----
 drivers/gpu/drm/xe/xe_migrate.c    | 29 ++++++++++++++-------------
 drivers/gpu/drm/xe/xe_tile.h       | 32 ++++++++++++++++++++++++++++++
 4 files changed, 57 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index 7ade915c59a8..cb93c4ee7bb8 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -28,6 +28,7 @@
 #include "xe_macros.h"
 #include "xe_migrate.h"
 #include "xe_pm.h"
+#include "xe_tile.h"
 #include "xe_trace.h"
 #include "xe_vm.h"
 #include "xe_pxp.h"
@@ -588,7 +589,7 @@ struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe,
 						struct xe_vm *user_vm,
 						u32 flags, u64 extensions)
 {
-	struct xe_gt *gt = tile->primary_gt;
+	struct xe_gt *gt = xe_tile_pt_gt(tile);
 	struct xe_exec_queue *q;
 	struct xe_vm *migrate_vm;
 
@@ -606,7 +607,7 @@ struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe,
 					 flags, extensions);
 	} else {
 		q = xe_exec_queue_create_class(xe, gt, migrate_vm,
-					       XE_ENGINE_CLASS_COPY, flags,
+					       xe_tile_pt_class(tile), flags,
 					       extensions);
 	}
 	xe_vm_put(migrate_vm);
diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
index be79a0da2f2f..82299c1bc6c5 100644
--- a/drivers/gpu/drm/xe/xe_gt.c
+++ b/drivers/gpu/drm/xe/xe_gt.c
@@ -61,6 +61,7 @@
 #include "xe_sa.h"
 #include "xe_sched_job.h"
 #include "xe_sriov.h"
+#include "xe_tile.h"
 #include "xe_tlb_inval.h"
 #include "xe_tuning.h"
 #include "xe_uc.h"
@@ -657,10 +658,12 @@ static int gt_init_with_all_forcewake(struct xe_gt *gt)
 		}
 	}
 
-	if (xe_gt_is_main_type(gt)) {
-		struct xe_tile *tile = gt_to_tile(gt);
-
-		err = xe_migrate_init(tile->migrate);
+	/*
+	 * Normally the migration context runs on the primary GT, but a tile
+	 * with no graphics IP has only its media GT to run it on.
+	 */
+	if (gt == xe_tile_pt_gt(gt_to_tile(gt))) {
+		err = xe_migrate_init(gt_to_tile(gt)->migrate);
 		if (err)
 			return err;
 	}
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index 19c37eb31589..754592c5cf88 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -43,6 +43,7 @@
 #include "xe_sriov_vf_ccs.h"
 #include "xe_svm.h"
 #include "xe_sync.h"
+#include "xe_tile.h"
 #include "xe_trace_bo.h"
 #include "xe_validation.h"
 #include "xe_vm.h"
@@ -478,7 +479,7 @@ static void xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m,
 		if (xe->info.has_usm) {
 			xe_tile_assert(tile, xe_bo_size(batch) == SZ_1M);
 
-			batch = tile->primary_gt->usm.bb_pool->bo;
+			batch = xe_tile_pt_gt(tile)->usm.bb_pool->bo;
 			m->usm_batch_base_ofs = m->batch_base_ofs + SZ_1M;
 			xe_tile_assert(tile, xe_bo_size(batch) == SZ_512K);
 
@@ -499,7 +500,7 @@ static void xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m,
 		m->batch_base_ofs = xe_migrate_vram_ofs(xe, batch_addr, false);
 
 		if (xe->info.has_usm) {
-			batch = tile->primary_gt->usm.bb_pool->bo;
+			batch = xe_tile_pt_gt(tile)->usm.bb_pool->bo;
 			batch_addr = xe_bo_addr(batch, 0, XE_PAGE_SIZE);
 			m->usm_batch_base_ofs = xe_migrate_vram_ofs(xe, batch_addr, false);
 		}
@@ -787,7 +788,7 @@ static void xe_migrate_ulls_exit(struct work_struct *work)
 int xe_migrate_init(struct xe_migrate *m)
 {
 	struct xe_tile *tile = m->tile;
-	struct xe_gt *primary_gt = tile->primary_gt;
+	struct xe_gt *gt = xe_tile_pt_gt(tile);
 	struct xe_device *xe = tile_to_xe(tile);
 	struct xe_vm *vm;
 	int err;
@@ -803,8 +804,8 @@ int xe_migrate_init(struct xe_migrate *m)
 		goto err_out;
 
 	if (xe->info.has_usm) {
-		struct xe_hw_engine *hwe0 = primary_gt->usm.paging_hwe0;
-		u32 logical_mask = primary_gt->usm.paging_logical_mask;
+		struct xe_hw_engine *hwe0 = gt->usm.paging_hwe0;
+		u32 logical_mask = gt->usm.paging_logical_mask;
 
 		if (!hwe0 || !logical_mask) {
 			err = -EINVAL;
@@ -821,8 +822,8 @@ int xe_migrate_init(struct xe_migrate *m)
 					    EXEC_QUEUE_FLAG_MIGRATE |
 					    EXEC_QUEUE_FLAG_LOW_LATENCY, 0);
 	} else {
-		m->q = xe_exec_queue_create_class(xe, primary_gt, vm,
-						  XE_ENGINE_CLASS_COPY,
+		m->q = xe_exec_queue_create_class(xe, gt, vm,
+						  xe_tile_pt_class(tile),
 						  EXEC_QUEUE_FLAG_KERNEL |
 						  EXEC_QUEUE_FLAG_MIGRATE, 0);
 	}
@@ -1170,7 +1171,7 @@ static u32 xe_migrate_ccs_copy(struct xe_migrate *m,
 			       u64 dst_ofs, bool dst_is_indirect, u32 dst_size,
 			       u64 ccs_ofs, bool copy_ccs)
 {
-	struct xe_gt *gt = m->tile->primary_gt;
+	struct xe_gt *gt = xe_tile_pt_gt(m->tile);
 	u32 flush_flags = 0;
 
 	if (!copy_ccs && dst_is_indirect) {
@@ -1214,7 +1215,7 @@ static struct dma_fence *__xe_migrate_copy(struct xe_migrate *m,
 					   bool copy_only_ccs,
 					   bool is_vram_resolve)
 {
-	struct xe_gt *gt = m->tile->primary_gt;
+	struct xe_gt *gt = xe_tile_pt_gt(m->tile);
 	struct xe_device *xe = gt_to_xe(gt);
 	struct dma_fence *fence = NULL;
 	u64 size = xe_bo_size(src_bo);
@@ -1512,7 +1513,7 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q,
 	bool dst_is_pltt = read_write == XE_SRIOV_VF_CCS_WRITE_CTX;
 	struct ttm_resource *src = new_mem;
 	struct xe_migrate *m = tile->migrate;
-	struct xe_gt *gt = tile->primary_gt;
+	struct xe_gt *gt = xe_tile_pt_gt(tile);
 	u32 batch_size, batch_size_allocated;
 	struct xe_device *xe = gt_to_xe(gt);
 	struct xe_res_cursor src_it, ccs_it;
@@ -1714,7 +1715,7 @@ struct dma_fence *xe_migrate_vram_copy_chunk(struct xe_bo *vram_bo, u64 vram_off
 {
 	struct xe_device *xe = xe_bo_device(vram_bo);
 	struct xe_tile *tile = vram_bo->tile;
-	struct xe_gt *gt = tile->primary_gt;
+	struct xe_gt *gt = xe_tile_pt_gt(tile);
 	struct xe_migrate *m = tile->migrate;
 	struct dma_fence *fence = NULL;
 	struct ttm_resource *vram = vram_bo->ttm.resource;
@@ -1930,7 +1931,7 @@ struct dma_fence *xe_migrate_clear(struct xe_migrate *m,
 	bool clear_vram = mem_type_is_vram(dst->mem_type);
 	bool clear_bo_data = XE_MIGRATE_CLEAR_FLAG_BO_DATA & clear_flags;
 	bool clear_ccs = XE_MIGRATE_CLEAR_FLAG_CCS_DATA & clear_flags;
-	struct xe_gt *gt = m->tile->primary_gt;
+	struct xe_gt *gt = xe_tile_pt_gt(m->tile);
 	struct xe_device *xe = gt_to_xe(gt);
 	bool clear_only_system_ccs = false;
 	struct dma_fence *fence = NULL;
@@ -2295,7 +2296,7 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
 					 struct dma_fence *deps,
 					 const enum xe_migrate_copy_dir dir)
 {
-	struct xe_gt *gt = m->tile->primary_gt;
+	struct xe_gt *gt = xe_tile_pt_gt(m->tile);
 	struct xe_device *xe = gt_to_xe(gt);
 	bool use_usm_batch = xe->info.has_usm;
 	struct dma_fence *fence = NULL;
@@ -2723,7 +2724,7 @@ int xe_migrate_debug_ccs_overlap(struct xe_migrate *m,
 				 bool write_to_ccs)
 {
 	struct xe_device *xe = tile_to_xe(m->tile);
-	struct xe_gt *gt = m->tile->primary_gt;
+	struct xe_gt *gt = xe_tile_pt_gt(m->tile);
 	struct dma_fence *fence;
 	struct xe_bb *bb;
 	struct xe_sched_job *job;
diff --git a/drivers/gpu/drm/xe/xe_tile.h b/drivers/gpu/drm/xe/xe_tile.h
index a2a2c0e936b8..f35b675f7a20 100644
--- a/drivers/gpu/drm/xe/xe_tile.h
+++ b/drivers/gpu/drm/xe/xe_tile.h
@@ -6,6 +6,7 @@
 #ifndef _XE_TILE_H_
 #define _XE_TILE_H_
 
+#include "xe_hw_engine_types.h"
 #include "xe_tile_types.h"
 
 struct xe_device;
@@ -24,6 +25,37 @@ static inline bool xe_tile_is_root(struct xe_tile *tile)
 	return tile->id == 0;
 }
 
+/**
+ * xe_tile_pt_gt() - GT used to run a tile's page table update jobs
+ * @tile: Pointer to the struct xe_tile.
+ *
+ * Page table updates, and the migration context they are submitted through,
+ * normally run on the primary GT.  A device whose graphics IP is absent has
+ * no primary GT, but its media GT can write page tables just as well.
+ *
+ * Return: The tile's primary GT, or its media GT if it has no primary GT.
+ */
+static inline struct xe_gt *xe_tile_pt_gt(struct xe_tile *tile)
+{
+	return tile->primary_gt ?: tile->media_gt;
+}
+
+/**
+ * xe_tile_pt_class() - Engine class to run a tile's page table update jobs on
+ * @tile: Pointer to the struct xe_tile.
+ *
+ * The engine class to pair with xe_tile_pt_gt(). The copy engine is the usual
+ * choice, but it lives on the primary GT; when there is none, fall back to a
+ * video decode engine on the media GT.
+ *
+ * Return: The engine class to create the tile's page table exec queue with.
+ */
+static inline enum xe_engine_class xe_tile_pt_class(struct xe_tile *tile)
+{
+	return tile->primary_gt ? XE_ENGINE_CLASS_COPY :
+				  XE_ENGINE_CLASS_VIDEO_DECODE;
+}
+
 /**
  * xe_tile_to_vr() - Return the struct xe_vram_region pointer from a
  * struct xe_tile pointer
-- 
2.43.0


  parent reply	other threads:[~2026-11-10 23:15 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-10 23:14 [PATCH 00/11] Allow boot with only media GT Stuart Summers
2026-11-10 23:14 ` [PATCH 01/11] drm/xe: Detect each GMD_ID IP in a loop Stuart Summers
2026-11-10 23:14 ` [PATCH 02/11] drm/xe: Tolerate a missing graphics IP in xe_info_init() Stuart Summers
2026-11-10 23:14 ` [PATCH 03/11] drm/xe: Verify IP presence against GU_CNTL Stuart Summers
2026-11-10 23:14 ` [PATCH 04/11] drm/xe: Guard per-tile primary GT accesses Stuart Summers
2026-11-10 23:14 ` [PATCH 05/11] drm/xe: Stop assuming the root tile has a primary GT Stuart Summers
2026-11-11  2:59   ` sashiko-bot
2026-11-10 23:14 ` [PATCH 06/11] drm/xe: Do not claim flat CCS without a graphics IP Stuart Summers
2026-11-11  3:21   ` sashiko-bot
2026-11-10 23:14 ` Stuart Summers [this message]
2026-11-11  3:53   ` [PATCH 07/11] drm/xe: Run page table updates on the media GT when there is no primary sashiko-bot
2026-11-10 23:14 ` [PATCH 08/11] drm/xe: Document that gt_types_allowed=media now probes Stuart Summers
2026-11-10 23:14 ` [PATCH 09/11] drm/xe: Fall back to CPU copies when the tile cannot blit Stuart Summers
2026-11-11  4:25   ` sashiko-bot
2026-11-10 23:14 ` [PATCH 10/11] drm/xe: Require a fully visible VRAM BAR without a primary GT Stuart Summers
2026-11-11  4:38   ` sashiko-bot
2026-11-10 23:14 ` [PATCH 11/11] drm/xe: Allow probe " Stuart Summers
2026-11-11  4:57   ` sashiko-bot
2026-11-10 23:39 ` ✓ CI.KUnit: success for Allow boot with only media GT Patchwork
2026-11-11  0:14 ` ✓ Xe.CI.BAT: " Patchwork
2026-11-11  4:17 ` ✓ Xe.CI.FULL: " Patchwork
2026-11-12 12:21 ` [PATCH 00/11] " Piotr Piórkowski

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=20261110231442.218721-20-stuart.summers@intel.com \
    --to=stuart.summers@intel.com \
    --cc=fei.yang@intel.com \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=matthew.brost@intel.com \
    --cc=matthew.d.roper@intel.com \
    --cc=rodrigo.vivi@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