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
next prev 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