From 5d9e708d2a69ab1f64a17aec810cd7c70c5b9fab Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Tue, 24 Mar 2026 08:37:20 -0700 Subject: [PATCH 001/120] drm/xe/pxp: Clean up termination status on failure If the PXP HW termination fails during PXP start, the normal completion code won't be called, so the termination will remain uncomplete. To avoid unnecessary waits, mark the termination as completed from the error path. Note that we already do this if the termination fails when handling a termination irq from the HW. Fixes: f8caa80154c4 ("drm/xe/pxp: Add PXP queue tracking and session start") Signed-off-by: Daniele Ceraolo Spurio Cc: Alan Previn Teres Alexis Cc: Julia Filipchuk Reviewed-by: Julia Filipchuk Link: https://patch.msgid.link/20260324153718.3155504-7-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_pxp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index e2978e48f660..b60ea85c3e11 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -583,6 +583,7 @@ static int pxp_start(struct xe_pxp *pxp, u8 type) drm_err(&pxp->xe->drm, "PXP termination failed before start\n"); mutex_lock(&pxp->mutex); pxp->status = XE_PXP_ERROR; + complete_all(&pxp->termination); goto out_unlock; } From f1b5a77fc9b6a90cd9a5e3db9d4c73ae1edfcfac Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Tue, 24 Mar 2026 08:37:21 -0700 Subject: [PATCH 002/120] drm/xe/pxp: Remove incorrect handling of impossible state during suspend The default case of the PXP suspend switch is incorrectly exiting without releasing the lock. However, this case is impossible to hit because we're switching on an enum and all the valid enum values have their own cases. Therefore, we can just get rid of the default case and rely on the compiler to warn us if a new enum value is added and we forget to add it to the switch. Fixes: 51462211f4a9 ("drm/xe/pxp: add PXP PM support") Signed-off-by: Daniele Ceraolo Spurio Cc: Alan Previn Teres Alexis Cc: Julia Filipchuk Reviewed-by: Julia Filipchuk Link: https://patch.msgid.link/20260324153718.3155504-8-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_pxp.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index b60ea85c3e11..a054b57f5ae5 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -871,11 +871,6 @@ int xe_pxp_pm_suspend(struct xe_pxp *pxp) pxp->key_instance++; needs_queue_inval = true; break; - default: - drm_err(&pxp->xe->drm, "unexpected state during PXP suspend: %u", - pxp->status); - ret = -EIO; - goto out; } /* @@ -900,7 +895,6 @@ int xe_pxp_pm_suspend(struct xe_pxp *pxp) pxp->last_suspend_key_instance = pxp->key_instance; -out: return ret; } From 0850ec7bb2459602351639dccf7a68a03c9d1ee0 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Tue, 24 Mar 2026 08:37:22 -0700 Subject: [PATCH 003/120] drm/xe/pxp: Clear restart flag in pxp_start after jumping back If we don't clear the flag we'll keep jumping back at the beginning of the function once we reach the end. Fixes: ccd3c6820a90 ("drm/xe/pxp: Decouple queue addition from PXP start") Signed-off-by: Daniele Ceraolo Spurio Cc: Julia Filipchuk Reviewed-by: Julia Filipchuk Link: https://patch.msgid.link/20260324153718.3155504-9-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_pxp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index a054b57f5ae5..aad3dfa3156e 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -512,7 +512,7 @@ static int __exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q) static int pxp_start(struct xe_pxp *pxp, u8 type) { int ret = 0; - bool restart = false; + bool restart; if (!xe_pxp_is_enabled(pxp)) return -ENODEV; @@ -541,6 +541,8 @@ static int pxp_start(struct xe_pxp *pxp, u8 type) msecs_to_jiffies(PXP_ACTIVATION_TIMEOUT_MS))) return -ETIMEDOUT; + restart = false; + mutex_lock(&pxp->mutex); /* If PXP is not already active, turn it on */ From 6eb04caaa972934c9b6cea0e0c29e466bf9a346f Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Tue, 24 Mar 2026 08:37:23 -0700 Subject: [PATCH 004/120] drm/xe/pxp: Don't allow PXP on older PTL GSC FWs On PTL, older GSC FWs have a bug that can cause them to crash during PXP invalidation events, which leads to a complete loss of power management on the media GT. Therefore, we can't use PXP on FWs that have this bug, which was fixed in PTL GSC build 1396. Fixes: b1dcec9bd8a1 ("drm/xe/ptl: Enable PXP for PTL") Signed-off-by: Daniele Ceraolo Spurio Cc: Julia Filipchuk Reviewed-by: Julia Filipchuk Acked-by: Rodrigo Vivi Link: https://patch.msgid.link/20260324153718.3155504-10-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_pxp.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index aad3dfa3156e..7244090b0782 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -380,6 +380,18 @@ int xe_pxp_init(struct xe_device *xe) return 0; } + /* + * On PTL, older GSC FWs have a bug that can cause them to crash during + * PXP invalidation events, which leads to a complete loss of power + * management on the media GT. Therefore, we can't use PXP on FWs that + * have this bug, which was fixed in PTL GSC build 1396. + */ + if (xe->info.platform == XE_PANTHERLAKE && + gt->uc.gsc.fw.versions.found[XE_UC_FW_VER_RELEASE].build < 1396) { + drm_info(&xe->drm, "PXP requires PTL GSC build 1396 or newer\n"); + return 0; + } + pxp = drmm_kzalloc(&xe->drm, sizeof(struct xe_pxp), GFP_KERNEL); if (!pxp) { err = -ENOMEM; From 2247feb9badca5a4774df9a437bfc44fba4f22de Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Thu, 26 Feb 2026 17:52:25 -0800 Subject: [PATCH 005/120] drm/xe: Disable garbage collector work item on SVM close MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When an SVM is closed, the garbage collector work item must be stopped synchronously and any future queuing must be prevented. Replace flush_work() with disable_work_sync() to ensure both conditions are met. Fixes: 63f6e480d115 ("drm/xe: Add SVM garbage collector") Cc: stable@vger.kernel.org Signed-off-by: Matthew Brost Reviewed-by: Thomas Hellström Link: https://patch.msgid.link/20260227015225.3081787-1-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_svm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 5b627eed1eab..5933b2b6392b 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -931,7 +931,7 @@ int xe_svm_init(struct xe_vm *vm) void xe_svm_close(struct xe_vm *vm) { xe_assert(vm->xe, xe_vm_is_closed(vm)); - flush_work(&vm->svm.garbage_collector.work); + disable_work_sync(&vm->svm.garbage_collector.work); xe_svm_put_pagemaps(vm); drm_pagemap_release_owner(&vm->svm.peer); } From b08ceb443866808b881b12d4183008d214d816c1 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Thu, 26 Mar 2026 14:01:15 -0700 Subject: [PATCH 006/120] drm/xe: Avoid memory allocations in xe_device_declare_wedged() xe_device_declare_wedged() runs in the DMA-fence signaling path, where GFP_KERNEL memory allocations are not allowed. However, registering xe_device_wedged_fini via drmm_add_action_or_reset() triggers a GFP_KERNEL allocation. Fix this by deferring the registration of xe_device_wedged_fini until late in the driver load sequence. Additionally, drop the wedged PM reference only if the device is actually wedged in xe_device_wedged_fini. Fixes: 452bca0edbd0 ("drm/xe: Don't suspend device upon wedge") Signed-off-by: Matthew Brost Reviewed-by: Rodrigo Vivi Link: https://patch.msgid.link/20260326210116.202585-2-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_device.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 44d04ac0951a..91327f43a04d 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -833,6 +833,14 @@ static void detect_preproduction_hw(struct xe_device *xe) } } +static void xe_device_wedged_fini(struct drm_device *drm, void *arg) +{ + struct xe_device *xe = arg; + + if (atomic_read(&xe->wedged.flag)) + xe_pm_runtime_put(xe); +} + int xe_device_probe(struct xe_device *xe) { struct xe_tile *tile; @@ -1009,6 +1017,10 @@ int xe_device_probe(struct xe_device *xe) detect_preproduction_hw(xe); + err = drmm_add_action_or_reset(&xe->drm, xe_device_wedged_fini, xe); + if (err) + goto err_unregister_display; + return devm_add_action_or_reset(xe->drm.dev, xe_device_sanitize, xe); err_unregister_display: @@ -1240,13 +1252,6 @@ u64 xe_device_uncanonicalize_addr(struct xe_device *xe, u64 address) return address & GENMASK_ULL(xe->info.va_bits - 1, 0); } -static void xe_device_wedged_fini(struct drm_device *drm, void *arg) -{ - struct xe_device *xe = arg; - - xe_pm_runtime_put(xe); -} - /** * DOC: Xe Device Wedging * @@ -1324,15 +1329,9 @@ void xe_device_declare_wedged(struct xe_device *xe) return; } - xe_pm_runtime_get_noresume(xe); - - if (drmm_add_action_or_reset(&xe->drm, xe_device_wedged_fini, xe)) { - drm_err(&xe->drm, "Failed to register xe_device_wedged_fini clean-up. Although device is wedged.\n"); - return; - } - if (!atomic_xchg(&xe->wedged.flag, 1)) { xe->needs_flr_on_fini = true; + xe_pm_runtime_get_noresume(xe); drm_err(&xe->drm, "CRITICAL: Xe has declared device %s as wedged.\n" "IOCTLs and executions are blocked.\n" From 4a706bd93c4fb156a13477e26ffdf2e633edeb10 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Thu, 26 Mar 2026 14:01:16 -0700 Subject: [PATCH 007/120] drm/xe: Drop registration of guc_submit_wedged_fini from xe_guc_submit_wedge() xe_guc_submit_wedge() runs in the DMA-fence signaling path, where GFP_KERNEL memory allocations are not permitted. However, registering guc_submit_wedged_fini via drmm_add_action_or_reset() triggers such an allocation. Avoid this by moving the logic from guc_submit_wedged_fini() into guc_submit_fini(), where wedged exec queue references are dropped during normal teardown. Fixes: 8ed9aaae39f3 ("drm/xe: Force wedged state and block GT reset upon any GPU hang") Signed-off-by: Matthew Brost Reviewed-by: Rodrigo Vivi Link: https://patch.msgid.link/20260326210116.202585-3-matthew.brost@intel.com --- drivers/gpu/drm/xe/xe_guc_submit.c | 33 ++++++++---------------------- 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index a145234f662b..10556156eaad 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -259,24 +259,12 @@ static void guc_submit_sw_fini(struct drm_device *drm, void *arg) } static void guc_submit_fini(void *arg) -{ - struct xe_guc *guc = arg; - - /* Forcefully kill any remaining exec queues */ - xe_guc_ct_stop(&guc->ct); - guc_submit_reset_prepare(guc); - xe_guc_softreset(guc); - xe_guc_submit_stop(guc); - xe_uc_fw_sanitize(&guc->fw); - xe_guc_submit_pause_abort(guc); -} - -static void guc_submit_wedged_fini(void *arg) { struct xe_guc *guc = arg; struct xe_exec_queue *q; unsigned long index; + /* Drop any wedged queue refs */ mutex_lock(&guc->submission_state.lock); xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) { if (exec_queue_wedged(q)) { @@ -286,6 +274,14 @@ static void guc_submit_wedged_fini(void *arg) } } mutex_unlock(&guc->submission_state.lock); + + /* Forcefully kill any remaining exec queues */ + xe_guc_ct_stop(&guc->ct); + guc_submit_reset_prepare(guc); + xe_guc_softreset(guc); + xe_guc_submit_stop(guc); + xe_uc_fw_sanitize(&guc->fw); + xe_guc_submit_pause_abort(guc); } static const struct xe_exec_queue_ops guc_exec_queue_ops; @@ -1320,10 +1316,8 @@ static void disable_scheduling_deregister(struct xe_guc *guc, void xe_guc_submit_wedge(struct xe_guc *guc) { struct xe_device *xe = guc_to_xe(guc); - struct xe_gt *gt = guc_to_gt(guc); struct xe_exec_queue *q; unsigned long index; - int err; xe_gt_assert(guc_to_gt(guc), guc_to_xe(guc)->wedged.mode); @@ -1335,15 +1329,6 @@ void xe_guc_submit_wedge(struct xe_guc *guc) return; if (xe->wedged.mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET) { - err = devm_add_action_or_reset(guc_to_xe(guc)->drm.dev, - guc_submit_wedged_fini, guc); - if (err) { - xe_gt_err(gt, "Failed to register clean-up on wedged.mode=%s; " - "Although device is wedged.\n", - xe_wedged_mode_to_string(XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET)); - return; - } - mutex_lock(&guc->submission_state.lock); xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) if (xe_exec_queue_get_unless_zero(q)) From df03d7c2bbc91d1e83f8b42881ad791353df7d94 Mon Sep 17 00:00:00 2001 From: Francois Dugast Date: Fri, 27 Mar 2026 21:27:49 +0100 Subject: [PATCH 008/120] drm/xe: Document GT statistics In the context of porting applications to SVM, the Xe GT statistics are used by application developers to validate expected behavior such as proper alignment, page fault count and migrations. As those statistics are made for kernel developers, they assume good understanding of driver internals, which is not always the case on the application side. Therefore, this commit documents the usage of GT statistics and clarifies the meaning of identifiers which correspond to the values exposed via debugfs. Documentation is close to identifiers declaration to make it easier to maintain when adding new entries in the future. v2: Fix page reclaim list (PRL) entries (Matthew Brost) Assisted-by: GitHub Copilot:claude-sonnet-4.6 Cc: Matthew Brost Reviewed-by: Matthew Brost Link: https://lore.kernel.org/r/20260327202749.222794-1-francois.dugast@intel.com Signed-off-by: Francois Dugast --- Documentation/gpu/xe/index.rst | 1 + Documentation/gpu/xe/xe_gt_stats.rst | 11 +++ drivers/gpu/drm/xe/xe_gt_stats.c | 41 +++++++++ drivers/gpu/drm/xe/xe_gt_stats_types.h | 118 +++++++++++++++++++++++++ 4 files changed, 171 insertions(+) create mode 100644 Documentation/gpu/xe/xe_gt_stats.rst diff --git a/Documentation/gpu/xe/index.rst b/Documentation/gpu/xe/index.rst index bc432c95d1a3..874ffcb6da3a 100644 --- a/Documentation/gpu/xe/index.rst +++ b/Documentation/gpu/xe/index.rst @@ -29,3 +29,4 @@ DG2, etc is provided to prototype the driver. xe_device xe-drm-usage-stats.rst xe_configfs + xe_gt_stats diff --git a/Documentation/gpu/xe/xe_gt_stats.rst b/Documentation/gpu/xe/xe_gt_stats.rst new file mode 100644 index 000000000000..5ff806abaddb --- /dev/null +++ b/Documentation/gpu/xe/xe_gt_stats.rst @@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +================ +Xe GT Statistics +================ + +.. kernel-doc:: drivers/gpu/drm/xe/xe_gt_stats.c + :doc: Xe GT Statistics + +.. kernel-doc:: drivers/gpu/drm/xe/xe_gt_stats_types.h + :internal: diff --git a/drivers/gpu/drm/xe/xe_gt_stats.c b/drivers/gpu/drm/xe/xe_gt_stats.c index 59b3b23a54c8..789397514f3e 100644 --- a/drivers/gpu/drm/xe/xe_gt_stats.c +++ b/drivers/gpu/drm/xe/xe_gt_stats.c @@ -9,6 +9,47 @@ #include "xe_device.h" #include "xe_gt_stats.h" +/** + * DOC: Xe GT Statistics + * + * Overview + * ======== + * + * The Xe driver exposes per-GT statistics through the debugfs filesystem at:: + * + * /sys/kernel/debug/dri//gt/stats + * + * This interface requires the kernel to be built with ``CONFIG_DEBUG_FS=y``. + * + * Reading statistics + * ================== + * + * Reading the file prints all available statistics, one per line, in + * ``name: value`` format:: + * + * $ cat /sys/kernel/debug/dri/0/gt0/stats + * svm_pagefault_count: 0 + * tlb_inval_count: 1234 + * ... + * + * All values are 64-bit unsigned integers aggregated across all CPUs. + * Counters accumulate since the driver was loaded or since the last explicit + * reset. Timing counters use microseconds as their unit; data volume counters + * use KiB. + * + * Resetting statistics + * ==================== + * + * Writing a boolean true value to the file resets all counters to zero:: + * + * echo 1 > /sys/kernel/debug/dri/0/gt0/stats + * + * Any value accepted by ``kstrtobool()`` (e.g. ``1``, ``y``, ``yes``, + * ``on``) triggers the reset. Resetting while the GPU is active may yield + * unpredictable intermediate values; it is recommended to reset only when + * the GPU is idle. + */ + static void xe_gt_stats_fini(struct drm_device *drm, void *arg) { struct xe_gt *gt = arg; diff --git a/drivers/gpu/drm/xe/xe_gt_stats_types.h b/drivers/gpu/drm/xe/xe_gt_stats_types.h index 081c787ddcb6..425491bed6c4 100644 --- a/drivers/gpu/drm/xe/xe_gt_stats_types.h +++ b/drivers/gpu/drm/xe/xe_gt_stats_types.h @@ -8,6 +8,124 @@ #include +/** + * enum xe_gt_stats_id - GT statistics identifiers + * @XE_GT_STATS_ID_SVM_PAGEFAULT_COUNT: Total SVM page faults handled. + * @XE_GT_STATS_ID_TLB_INVAL: Total GPU Translation Lookaside Buffer (TLB) + * invalidations issued. + * @XE_GT_STATS_ID_SVM_TLB_INVAL_COUNT: TLB invalidations issued during SVM + * page-fault handling. + * @XE_GT_STATS_ID_SVM_TLB_INVAL_US: Cumulative time (µs) waiting for TLB + * invalidations during SVM page-fault handling. + * + * @XE_GT_STATS_ID_VMA_PAGEFAULT_COUNT: Buffer-object (non-SVM) page faults + * handled. + * @XE_GT_STATS_ID_VMA_PAGEFAULT_KB: Size (KiB) of VMAs involved in + * buffer-object page fault handling. + * @XE_GT_STATS_ID_INVALID_PREFETCH_PAGEFAULT_COUNT: GPU prefetch faults for + * addresses with no valid backing. + * + * @XE_GT_STATS_ID_SVM_4K_PAGEFAULT_COUNT: SVM page faults resolved by + * mapping 4K pages. + * @XE_GT_STATS_ID_SVM_64K_PAGEFAULT_COUNT: SVM page faults resolved by + * mapping 64K pages. + * @XE_GT_STATS_ID_SVM_2M_PAGEFAULT_COUNT: SVM page faults resolved by + * mapping 2M pages. + * @XE_GT_STATS_ID_SVM_4K_VALID_PAGEFAULT_COUNT: Valid SVM page faults + * at 4K page size, where the GPU mapping was already valid — resolved without + * creating new mappings. + * @XE_GT_STATS_ID_SVM_64K_VALID_PAGEFAULT_COUNT: Valid SVM page faults at 64K + * page size. + * @XE_GT_STATS_ID_SVM_2M_VALID_PAGEFAULT_COUNT: Valid SVM page faults at 2M + * page size. + * @XE_GT_STATS_ID_SVM_4K_PAGEFAULT_US: Cumulative time (µs) handling 4K SVM + * page faults. + * @XE_GT_STATS_ID_SVM_64K_PAGEFAULT_US: Cumulative time (µs) handling 64K + * SVM page faults. + * @XE_GT_STATS_ID_SVM_2M_PAGEFAULT_US: Cumulative time (µs) handling 2M SVM + * page faults. + * + * @XE_GT_STATS_ID_SVM_4K_MIGRATE_COUNT: 4K pages moved from CPU to device + * memory. + * @XE_GT_STATS_ID_SVM_64K_MIGRATE_COUNT: 64K pages moved from CPU to device + * memory. + * @XE_GT_STATS_ID_SVM_2M_MIGRATE_COUNT: 2M pages moved from CPU to device + * memory. + * @XE_GT_STATS_ID_SVM_4K_MIGRATE_US: Cumulative time (µs) moving 4K pages + * from CPU to device memory. + * @XE_GT_STATS_ID_SVM_64K_MIGRATE_US: Cumulative time (µs) moving 64K pages + * from CPU to device memory. + * @XE_GT_STATS_ID_SVM_2M_MIGRATE_US: Cumulative time (µs) moving 2M pages + * from CPU to device memory. + * + * @XE_GT_STATS_ID_SVM_DEVICE_COPY_US: Cumulative time (µs) for memory copies to + * device, across all page sizes. + * @XE_GT_STATS_ID_SVM_4K_DEVICE_COPY_US: Cumulative time (µs) for memory copies + * of 4K pages to device. + * @XE_GT_STATS_ID_SVM_64K_DEVICE_COPY_US: Cumulative time (µs) for memory + * copies of 64K pages to device. + * @XE_GT_STATS_ID_SVM_2M_DEVICE_COPY_US: Cumulative time (µs) for memory copies + * of 2M pages to device. + * @XE_GT_STATS_ID_SVM_CPU_COPY_US: Cumulative time (µs) for memory copies to + * CPU, across all page sizes. + * @XE_GT_STATS_ID_SVM_4K_CPU_COPY_US: Cumulative time (µs) for memory copies of + * 4K pages to CPU. + * @XE_GT_STATS_ID_SVM_64K_CPU_COPY_US: Cumulative time (µs) for memory copies + * of 64K pages to CPU. + * @XE_GT_STATS_ID_SVM_2M_CPU_COPY_US: Cumulative time (µs) for memory copies of + * 2M pages to CPU. + * @XE_GT_STATS_ID_SVM_DEVICE_COPY_KB: Data (KiB) copied to device across all + * page sizes. + * @XE_GT_STATS_ID_SVM_4K_DEVICE_COPY_KB: Data (KiB) copied to device for 4K + * pages. + * @XE_GT_STATS_ID_SVM_64K_DEVICE_COPY_KB: Data (KiB) copied to device for + * 64K pages. + * @XE_GT_STATS_ID_SVM_2M_DEVICE_COPY_KB: Data (KiB) copied to device for 2M + * pages. + * @XE_GT_STATS_ID_SVM_CPU_COPY_KB: Data (KiB) copied to CPU across all page + * sizes. + * @XE_GT_STATS_ID_SVM_4K_CPU_COPY_KB: Data (KiB) copied to CPU for 4K pages. + * @XE_GT_STATS_ID_SVM_64K_CPU_COPY_KB: Data (KiB) copied to CPU for 64K pages. + * @XE_GT_STATS_ID_SVM_2M_CPU_COPY_KB: Data (KiB) copied to CPU for 2M pages. + * + * @XE_GT_STATS_ID_SVM_4K_GET_PAGES_US: Cumulative time (µs) getting CPU + * memory pages for GPU access at 4K page size. + * @XE_GT_STATS_ID_SVM_64K_GET_PAGES_US: Cumulative time (µs) getting CPU + * memory pages for GPU access at 64K page size. + * @XE_GT_STATS_ID_SVM_2M_GET_PAGES_US: Cumulative time (µs) getting CPU + * memory pages for GPU access at 2M page size. + * @XE_GT_STATS_ID_SVM_4K_BIND_US: Cumulative time (µs) binding 4K pages + * into the GPU page table. + * @XE_GT_STATS_ID_SVM_64K_BIND_US: Cumulative time (µs) binding 64K pages + * into the GPU page table. + * @XE_GT_STATS_ID_SVM_2M_BIND_US: Cumulative time (µs) binding 2M pages + * into the GPU page table. + * + * @XE_GT_STATS_ID_HW_ENGINE_GROUP_SUSPEND_LR_QUEUE_COUNT: Times the + * scheduler preempted a long-running (LR) GPU exec queue. + * @XE_GT_STATS_ID_HW_ENGINE_GROUP_SKIP_LR_QUEUE_COUNT: Times the scheduler + * skipped suspend because the system was idle. + * @XE_GT_STATS_ID_HW_ENGINE_GROUP_WAIT_DMA_QUEUE_COUNT: Times the driver + * stalled waiting for prior GPU work to complete before scheduling more. + * @XE_GT_STATS_ID_HW_ENGINE_GROUP_SUSPEND_LR_QUEUE_US: Cumulative time + * (µs) spent preempting long-running (LR) GPU exec queues. + * @XE_GT_STATS_ID_HW_ENGINE_GROUP_WAIT_DMA_QUEUE_US: Cumulative time (µs) + * stalled waiting for prior GPU work to complete. + * + * @XE_GT_STATS_ID_PRL_4K_ENTRY_COUNT: 4K-page entries from the page reclaim + * list that were processed. + * @XE_GT_STATS_ID_PRL_64K_ENTRY_COUNT: 64K-page entries from the page reclaim + * list that were processed. + * @XE_GT_STATS_ID_PRL_2M_ENTRY_COUNT: 2M-page entries from the page reclaim + * list that were processed. + * @XE_GT_STATS_ID_PRL_ISSUED_COUNT: Times a page reclamation was issued. + * @XE_GT_STATS_ID_PRL_ABORTED_COUNT: Times the page reclaim process was + * aborted. + * + * @__XE_GT_STATS_NUM_IDS: Number of valid IDs; not a real counter. + * + * See Documentation/gpu/xe/xe_gt_stats.rst. + */ enum xe_gt_stats_id { XE_GT_STATS_ID_SVM_PAGEFAULT_COUNT, XE_GT_STATS_ID_TLB_INVAL, From bb2447ef6aee314f303b1a8e0ede6b98c8f6a529 Mon Sep 17 00:00:00 2001 From: Anoop Vijay Date: Fri, 27 Mar 2026 06:18:38 -0700 Subject: [PATCH 009/120] drm/xe/xe_sysctrl: Add System Controller types and device integration Add foundational type definitions for System Controller (sysctrl) support and integrate them into the xe_device structure. Introduce a capability flag in device descriptor and runtime information to record sysctrl presence on supported platforms. System Controller is a separate firmware-managed entity responsible for selected platform-level control and coordination tasks on Intel Xe3p discrete GPU platforms. The driver communicates with it via a mailbox interface for delegated operations. This commit introduces core data structures required for sysctrl support, including MMIO region definitions, a command mutex, and state tracking required for mailbox communication. No functional changes. This patch provides preparatory infrastructure for System Controller support. Signed-off-by: Anoop Vijay Reviewed-by: Umesh Nerlige Ramappa Signed-off-by: Umesh Nerlige Ramappa Link: https://patch.msgid.link/20260327131837.2192929-10-anoop.c.vijay@intel.com --- drivers/gpu/drm/xe/xe_device_types.h | 6 +++++ drivers/gpu/drm/xe/xe_pci_types.h | 1 + drivers/gpu/drm/xe/xe_sysctrl_types.h | 32 +++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 drivers/gpu/drm/xe/xe_sysctrl_types.h diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 615218d775b1..150c76b2acaf 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -27,6 +27,7 @@ #include "xe_sriov_vf_ccs_types.h" #include "xe_step_types.h" #include "xe_survivability_mode_types.h" +#include "xe_sysctrl_types.h" #include "xe_tile_types.h" #include "xe_validation.h" @@ -196,6 +197,8 @@ struct xe_device { u8 has_soc_remapper_telem:1; /** @info.has_sriov: Supports SR-IOV */ u8 has_sriov:1; + /** @info.has_sysctrl: Supports System Controller */ + u8 has_sysctrl:1; /** @info.has_usm: Device has unified shared memory support */ u8 has_usm:1; /** @info.has_64bit_timestamp: Device supports 64-bit timestamps */ @@ -508,6 +511,9 @@ struct xe_device { /** @i2c: I2C host controller */ struct xe_i2c *i2c; + /** @sc: System Controller */ + struct xe_sysctrl sc; + /** @atomic_svm_timeslice_ms: Atomic SVM fault timeslice MS */ u32 atomic_svm_timeslice_ms; diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h index 8eee4fb1c57c..08386c5eca27 100644 --- a/drivers/gpu/drm/xe/xe_pci_types.h +++ b/drivers/gpu/drm/xe/xe_pci_types.h @@ -57,6 +57,7 @@ struct xe_device_desc { u8 has_soc_remapper_sysctrl:1; u8 has_soc_remapper_telem:1; u8 has_sriov:1; + u8 has_sysctrl:1; u8 needs_scratch:1; u8 skip_guc_pc:1; u8 skip_mtcfg:1; diff --git a/drivers/gpu/drm/xe/xe_sysctrl_types.h b/drivers/gpu/drm/xe/xe_sysctrl_types.h new file mode 100644 index 000000000000..8217f6befe70 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_sysctrl_types.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_SYSCTRL_TYPES_H_ +#define _XE_SYSCTRL_TYPES_H_ + +#include +#include + +struct xe_mmio; + +/** + * struct xe_sysctrl - System Controller driver context + * + * This structure maintains the runtime state for System Controller + * communication. All fields are initialized during xe_sysctrl_init() + * and protected appropriately for concurrent access. + */ +struct xe_sysctrl { + /** @mmio: MMIO region for system control registers */ + struct xe_mmio *mmio; + + /** @cmd_lock: Mutex protecting mailbox command operations */ + struct mutex cmd_lock; + + /** @phase_bit: Message boundary phase toggle bit (0 or 1) */ + bool phase_bit; +}; + +#endif From 281a79f78dfedf10f6c7de4334434c38eb5459dd Mon Sep 17 00:00:00 2001 From: Anoop Vijay Date: Fri, 27 Mar 2026 06:18:39 -0700 Subject: [PATCH 010/120] drm/xe/xe_sysctrl: Add System Controller mailbox register definitions Add register definitions for System Controller mailbox interface, including control, data, and protocol-related fields, along with base address and BAR configuration required by the driver. No functional changes. This patch introduces register definitions only. Signed-off-by: Anoop Vijay Reviewed-by: Umesh Nerlige Ramappa Signed-off-by: Umesh Nerlige Ramappa Link: https://patch.msgid.link/20260327131837.2192929-11-anoop.c.vijay@intel.com --- drivers/gpu/drm/xe/regs/xe_sysctrl_regs.h | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 drivers/gpu/drm/xe/regs/xe_sysctrl_regs.h diff --git a/drivers/gpu/drm/xe/regs/xe_sysctrl_regs.h b/drivers/gpu/drm/xe/regs/xe_sysctrl_regs.h new file mode 100644 index 000000000000..59f3f3ec59a6 --- /dev/null +++ b/drivers/gpu/drm/xe/regs/xe_sysctrl_regs.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_SYSCTRL_REGS_H_ +#define _XE_SYSCTRL_REGS_H_ + +#include "xe_regs.h" + +#define SYSCTRL_BASE_OFFSET 0xdb000 +#define SYSCTRL_BASE (SOC_BASE + SYSCTRL_BASE_OFFSET) +#define SYSCTRL_MAILBOX_INDEX 0x03 +#define SYSCTRL_BAR_LENGTH 0x1000 + +#define SYSCTRL_MB_CTRL XE_REG(0x10) +#define SYSCTRL_MB_CTRL_RUN_BUSY REG_BIT(31) +#define SYSCTRL_MB_CTRL_IRQ REG_BIT(30) +#define SYSCTRL_MB_CTRL_RUN_BUSY_OUT REG_BIT(29) +#define SYSCTRL_MB_CTRL_PARAM3_MASK REG_GENMASK(28, 24) +#define SYSCTRL_MB_CTRL_PARAM2_MASK REG_GENMASK(23, 16) +#define SYSCTRL_MB_CTRL_PARAM1_MASK REG_GENMASK(15, 8) +#define SYSCTRL_MB_CTRL_COMMAND_MASK REG_GENMASK(7, 0) +#define SYSCTRL_MB_CTRL_CMD REG_FIELD_PREP(SYSCTRL_MB_CTRL_COMMAND_MASK, 5) + +#define SYSCTRL_MB_DATA0 XE_REG(0x14) +#define SYSCTRL_MB_DATA1 XE_REG(0x18) +#define SYSCTRL_MB_DATA2 XE_REG(0x1c) +#define SYSCTRL_MB_DATA3 XE_REG(0x20) + +#define SYSCTRL_FRAME_PHASE REG_BIT(24) +#define SYSCTRL_FRAME_CURRENT_MASK REG_GENMASK(21, 16) +#define SYSCTRL_FRAME_TOTAL_MASK REG_GENMASK(13, 8) +#define SYSCTRL_FRAME_COMMAND_MASK REG_GENMASK(7, 0) + +#endif From 37ace5254a2b1520753762527365ecad7fad797a Mon Sep 17 00:00:00 2001 From: Anoop Vijay Date: Fri, 27 Mar 2026 06:18:40 -0700 Subject: [PATCH 011/120] drm/xe/xe_sysctrl: Add ABI and mailbox interface headers Add ABI definitions, mailbox API, and command data structures required for System Controller communication. No functional changes. This patch introduces definitions for mailbox communication. Signed-off-by: Anoop Vijay Reviewed-by: Umesh Nerlige Ramappa Signed-off-by: Umesh Nerlige Ramappa Link: https://patch.msgid.link/20260327131837.2192929-12-anoop.c.vijay@intel.com --- drivers/gpu/drm/xe/abi/xe_sysctrl_abi.h | 65 +++++++++++++++++++ drivers/gpu/drm/xe/xe_sysctrl_mailbox.h | 31 +++++++++ drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h | 40 ++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 drivers/gpu/drm/xe/abi/xe_sysctrl_abi.h create mode 100644 drivers/gpu/drm/xe/xe_sysctrl_mailbox.h create mode 100644 drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h diff --git a/drivers/gpu/drm/xe/abi/xe_sysctrl_abi.h b/drivers/gpu/drm/xe/abi/xe_sysctrl_abi.h new file mode 100644 index 000000000000..4cbde267ac44 --- /dev/null +++ b/drivers/gpu/drm/xe/abi/xe_sysctrl_abi.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_SYSCTRL_ABI_H_ +#define _XE_SYSCTRL_ABI_H_ + +#include + +/** + * DOC: System Controller ABI + * + * This header defines the Application Binary Interface (ABI) used by + * drm/xe to communicate with System Controller firmware on Intel Xe3p + * discrete GPU platforms. + * + * System Controller (sysctrl) is a firmware-managed entity on Intel + * dGPUs responsible for certain low-level platform management + * functions. + * + * Communication protocol: + * + * Communication uses a mailbox interface with messages composed of: + * + * - Application message header (struct xe_sysctrl_app_msg_hdr) + * containing group_id, command, and version + * - Variable-length, command-specific payload + * + * Message header format: + * + * The 32-bit application message header is packed as: + * + * - Bits [7:0] : Group ID identifying command group + * - Bits [15:8] : Command identifier within group + * - Bits [23:16] : Command version for interface compatibility + * - Bits [31:24] : Reserved, must be zero + * + * This header defines firmware ABI message formats and constants shared + * between driver and System Controller firmware. + */ + +/** + * struct xe_sysctrl_app_msg_hdr - Application layer message header + * @data: 32-bit header data + * + * Header structure for application-level messages. + */ +struct xe_sysctrl_app_msg_hdr { + u32 data; +} __packed; + +#define SYSCTRL_HDR_GROUP_ID_MASK GENMASK(7, 0) +#define SYSCTRL_HDR_COMMAND_MASK GENMASK(14, 8) +#define SYSCTRL_HDR_COMMAND_MAX 0x7f +#define SYSCTRL_HDR_IS_RESPONSE BIT(15) +#define SYSCTRL_HDR_RESERVED_MASK GENMASK(23, 16) +#define SYSCTRL_HDR_RESULT_MASK GENMASK(31, 24) + +#define APP_HDR_GROUP_ID_MASK GENMASK(7, 0) +#define APP_HDR_COMMAND_MASK GENMASK(15, 8) +#define APP_HDR_VERSION_MASK GENMASK(23, 16) +#define APP_HDR_RESERVED_MASK GENMASK(31, 24) + +#endif diff --git a/drivers/gpu/drm/xe/xe_sysctrl_mailbox.h b/drivers/gpu/drm/xe/xe_sysctrl_mailbox.h new file mode 100644 index 000000000000..91460be9e22c --- /dev/null +++ b/drivers/gpu/drm/xe/xe_sysctrl_mailbox.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_SYSCTRL_MAILBOX_H_ +#define _XE_SYSCTRL_MAILBOX_H_ + +#include +#include + +#include "abi/xe_sysctrl_abi.h" + +struct xe_sysctrl; +struct xe_sysctrl_mailbox_command; + +#define XE_SYSCTRL_APP_HDR_GROUP_ID(hdr) \ + FIELD_GET(APP_HDR_GROUP_ID_MASK, le32_to_cpu((hdr)->data)) + +#define XE_SYSCTRL_APP_HDR_COMMAND(hdr) \ + FIELD_GET(APP_HDR_COMMAND_MASK, le32_to_cpu((hdr)->data)) + +#define XE_SYSCTRL_APP_HDR_VERSION(hdr) \ + FIELD_GET(APP_HDR_VERSION_MASK, le32_to_cpu((hdr)->data)) + +void xe_sysctrl_mailbox_init(struct xe_sysctrl *sc); +int xe_sysctrl_send_command(struct xe_sysctrl *sc, + struct xe_sysctrl_mailbox_command *cmd, + size_t *rdata_len); + +#endif diff --git a/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h b/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h new file mode 100644 index 000000000000..89456aec6097 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_SYSCTRL_MAILBOX_TYPES_H_ +#define _XE_SYSCTRL_MAILBOX_TYPES_H_ + +#include + +#include "abi/xe_sysctrl_abi.h" + +/** + * struct xe_sysctrl_mailbox_command - System Controller mailbox command + */ +struct xe_sysctrl_mailbox_command { + /** @header: Application message header containing command information */ + struct xe_sysctrl_app_msg_hdr header; + + /** @data_in: Pointer to input payload data (can be NULL if no input data) */ + void *data_in; + + /** @data_in_len: Size of input payload in bytes (0 if no input data) */ + size_t data_in_len; + + /** @data_out: Pointer to output buffer for response data (can be NULL if no response) */ + void *data_out; + + /** @data_out_len: Size of output buffer in bytes (0 if no response expected) */ + size_t data_out_len; +}; + +#define XE_SYSCTRL_MB_FRAME_SIZE 16 +#define XE_SYSCTRL_MB_MAX_FRAMES 64 +#define XE_SYSCTRL_MB_MAX_MESSAGE_SIZE \ + (XE_SYSCTRL_MB_FRAME_SIZE * XE_SYSCTRL_MB_MAX_FRAMES) + +#define XE_SYSCTRL_MB_DEFAULT_TIMEOUT_MS 500 + +#endif From 5ea3f0dc8f9d33adf72532b366d0b7b91dae4d7f Mon Sep 17 00:00:00 2001 From: Anoop Vijay Date: Fri, 27 Mar 2026 06:18:41 -0700 Subject: [PATCH 012/120] drm/xe/xe_sysctrl: Add System Controller initialization support Add initialization and cleanup infrastructure for System Controller subsystem and integrate it into xe device probe path. During initialization, platform support is checked via has_sysctrl capability flag and the mailbox region is configured through SoC remapper interface. Signed-off-by: Anoop Vijay Reviewed-by: Umesh Nerlige Ramappa Signed-off-by: Umesh Nerlige Ramappa Link: https://patch.msgid.link/20260327131837.2192929-13-anoop.c.vijay@intel.com --- drivers/gpu/drm/xe/Makefile | 1 + drivers/gpu/drm/xe/xe_device.c | 5 +++ drivers/gpu/drm/xe/xe_sysctrl.c | 77 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_sysctrl.h | 21 +++++++++ 4 files changed, 104 insertions(+) create mode 100644 drivers/gpu/drm/xe/xe_sysctrl.c create mode 100644 drivers/gpu/drm/xe/xe_sysctrl.h diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index dab979287a96..800ab80f4b53 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -123,6 +123,7 @@ xe-y += xe_bb.o \ xe_step.o \ xe_survivability_mode.o \ xe_sync.o \ + xe_sysctrl.o \ xe_tile.o \ xe_tile_sysfs.o \ xe_tlb_inval.o \ diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 91327f43a04d..4d4d7a35e089 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -65,6 +65,7 @@ #include "xe_survivability_mode.h" #include "xe_sriov.h" #include "xe_svm.h" +#include "xe_sysctrl.h" #include "xe_tile.h" #include "xe_ttm_stolen_mgr.h" #include "xe_ttm_sys_mgr.h" @@ -992,6 +993,10 @@ int xe_device_probe(struct xe_device *xe) if (err) goto err_unregister_display; + err = xe_sysctrl_init(xe); + if (err) + goto err_unregister_display; + err = xe_device_sysfs_init(xe); if (err) goto err_unregister_display; diff --git a/drivers/gpu/drm/xe/xe_sysctrl.c b/drivers/gpu/drm/xe/xe_sysctrl.c new file mode 100644 index 000000000000..f1b3af1748ad --- /dev/null +++ b/drivers/gpu/drm/xe/xe_sysctrl.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2026 Intel Corporation + */ + +#include +#include + +#include + +#include "regs/xe_sysctrl_regs.h" +#include "xe_device.h" +#include "xe_mmio.h" +#include "xe_soc_remapper.h" +#include "xe_sysctrl.h" +#include "xe_sysctrl_mailbox.h" +#include "xe_sysctrl_types.h" + +/** + * DOC: System Controller (sysctrl) + * + * System Controller (sysctrl) is a firmware-managed entity on Intel dGPUs + * responsible for selected low-level platform management functions. + * Communication between driver and System Controller is performed + * via a mailbox interface, enabling command and response exchange. + * + * This module provides initialization and support code for interacting + * with System Controller through the mailbox interface. + */ +static void sysctrl_fini(void *arg) +{ + struct xe_device *xe = arg; + + xe->soc_remapper.set_sysctrl_region(xe, 0); +} + +/** + * xe_sysctrl_init() - Initialize System Controller subsystem + * @xe: xe device instance + * + * Entry point for System Controller initialization, called from xe_device_probe. + * This function checks platform support and initializes the system controller. + * + * Return: 0 on success, error code on failure + */ +int xe_sysctrl_init(struct xe_device *xe) +{ + struct xe_tile *tile = xe_device_get_root_tile(xe); + struct xe_sysctrl *sc = &xe->sc; + int ret; + + if (!xe->info.has_soc_remapper_sysctrl) + return 0; + + if (!xe->info.has_sysctrl) + return 0; + + xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX); + + ret = devm_add_action_or_reset(xe->drm.dev, sysctrl_fini, xe); + if (ret) + return ret; + + sc->mmio = devm_kzalloc(xe->drm.dev, sizeof(*sc->mmio), GFP_KERNEL); + if (!sc->mmio) + return -ENOMEM; + + xe_mmio_init(sc->mmio, tile, tile->mmio.regs, tile->mmio.regs_size); + sc->mmio->adj_offset = SYSCTRL_BASE; + sc->mmio->adj_limit = U32_MAX; + + ret = devm_mutex_init(xe->drm.dev, &sc->cmd_lock); + if (ret) + return ret; + + return 0; +} diff --git a/drivers/gpu/drm/xe/xe_sysctrl.h b/drivers/gpu/drm/xe/xe_sysctrl.h new file mode 100644 index 000000000000..d5d8735038ae --- /dev/null +++ b/drivers/gpu/drm/xe/xe_sysctrl.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_SYSCTRL_H_ +#define _XE_SYSCTRL_H_ + +#include + +#include "xe_device_types.h" +#include "xe_sysctrl_types.h" + +static inline struct xe_device *sc_to_xe(struct xe_sysctrl *sc) +{ + return container_of(sc, struct xe_device, sc); +} + +int xe_sysctrl_init(struct xe_device *xe); + +#endif From 1f95f618182b5c99d46378141e0fb84f09bf914b Mon Sep 17 00:00:00 2001 From: Anoop Vijay Date: Fri, 27 Mar 2026 06:18:42 -0700 Subject: [PATCH 013/120] drm/xe/xe_sysctrl: Add System Controller mailbox communication support Add mailbox communication layer required for interacting with System Controller firmware, enabling command submission and response handling. This patch implements command/response handling logic, including error and timeout handling. Signed-off-by: Anoop Vijay Reviewed-by: Umesh Nerlige Ramappa Signed-off-by: Umesh Nerlige Ramappa Link: https://patch.msgid.link/20260327131837.2192929-14-anoop.c.vijay@intel.com --- drivers/gpu/drm/xe/Makefile | 1 + drivers/gpu/drm/xe/xe_sysctrl.c | 2 + drivers/gpu/drm/xe/xe_sysctrl_mailbox.c | 371 ++++++++++++++++++++++++ 3 files changed, 374 insertions(+) create mode 100644 drivers/gpu/drm/xe/xe_sysctrl_mailbox.c diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 800ab80f4b53..f9abaf687d46 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -124,6 +124,7 @@ xe-y += xe_bb.o \ xe_survivability_mode.o \ xe_sync.o \ xe_sysctrl.o \ + xe_sysctrl_mailbox.o \ xe_tile.o \ xe_tile_sysfs.o \ xe_tlb_inval.o \ diff --git a/drivers/gpu/drm/xe/xe_sysctrl.c b/drivers/gpu/drm/xe/xe_sysctrl.c index f1b3af1748ad..850f9dd7e9f0 100644 --- a/drivers/gpu/drm/xe/xe_sysctrl.c +++ b/drivers/gpu/drm/xe/xe_sysctrl.c @@ -73,5 +73,7 @@ int xe_sysctrl_init(struct xe_device *xe) if (ret) return ret; + xe_sysctrl_mailbox_init(sc); + return 0; } diff --git a/drivers/gpu/drm/xe/xe_sysctrl_mailbox.c b/drivers/gpu/drm/xe/xe_sysctrl_mailbox.c new file mode 100644 index 000000000000..3caa9f15875f --- /dev/null +++ b/drivers/gpu/drm/xe/xe_sysctrl_mailbox.c @@ -0,0 +1,371 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2026 Intel Corporation + */ + +#include +#include +#include +#include +#include + +#include "regs/xe_sysctrl_regs.h" +#include "xe_device.h" +#include "xe_mmio.h" +#include "xe_pm.h" +#include "xe_printk.h" +#include "xe_sysctrl.h" +#include "xe_sysctrl_mailbox.h" +#include "xe_sysctrl_mailbox_types.h" + +struct xe_sysctrl_mailbox_msg_hdr { + __le32 data; +} __packed; + +#define XE_SYSCTRL_HDR_GROUP_ID(hdr) \ + FIELD_GET(SYSCTRL_HDR_GROUP_ID_MASK, le32_to_cpu((hdr)->data)) + +#define XE_SYSCTRL_HDR_COMMAND(hdr) \ + FIELD_GET(SYSCTRL_HDR_COMMAND_MASK, le32_to_cpu((hdr)->data)) + +#define XE_SYSCTRL_HDR_IS_RESPONSE(hdr) \ + FIELD_GET(SYSCTRL_HDR_IS_RESPONSE, le32_to_cpu((hdr)->data)) + +#define XE_SYSCTRL_HDR_RESULT(hdr) \ + FIELD_GET(SYSCTRL_HDR_RESULT_MASK, le32_to_cpu((hdr)->data)) + +static bool sysctrl_wait_bit_clear(struct xe_sysctrl *sc, u32 bit_mask, + unsigned int timeout_ms) +{ + int ret; + + ret = xe_mmio_wait32_not(sc->mmio, SYSCTRL_MB_CTRL, bit_mask, bit_mask, + timeout_ms * 1000, NULL, false); + + return ret == 0; +} + +static bool sysctrl_wait_bit_set(struct xe_sysctrl *sc, u32 bit_mask, + unsigned int timeout_ms) +{ + int ret; + + ret = xe_mmio_wait32(sc->mmio, SYSCTRL_MB_CTRL, bit_mask, bit_mask, + timeout_ms * 1000, NULL, false); + + return ret == 0; +} + +static int sysctrl_write_frame(struct xe_sysctrl *sc, const void *frame, + size_t len) +{ + static const struct xe_reg regs[] = { + SYSCTRL_MB_DATA0, SYSCTRL_MB_DATA1, SYSCTRL_MB_DATA2, SYSCTRL_MB_DATA3 + }; + struct xe_device *xe = sc_to_xe(sc); + u32 val[XE_SYSCTRL_MB_FRAME_SIZE / sizeof(u32)] = {0}; + u32 dw = DIV_ROUND_UP(len, sizeof(u32)); + u32 i; + + xe_assert(xe, len > 0 && len <= XE_SYSCTRL_MB_FRAME_SIZE); + + memcpy(val, frame, len); + + for (i = 0; i < dw; i++) + xe_mmio_write32(sc->mmio, regs[i], val[i]); + + return 0; +} + +static int sysctrl_read_frame(struct xe_sysctrl *sc, void *frame, + size_t len) +{ + static const struct xe_reg regs[] = { + SYSCTRL_MB_DATA0, SYSCTRL_MB_DATA1, SYSCTRL_MB_DATA2, SYSCTRL_MB_DATA3 + }; + struct xe_device *xe = sc_to_xe(sc); + u32 val[XE_SYSCTRL_MB_FRAME_SIZE / sizeof(u32)] = {0}; + u32 dw = DIV_ROUND_UP(len, sizeof(u32)); + u32 i; + + xe_assert(xe, len > 0 && len <= XE_SYSCTRL_MB_FRAME_SIZE); + + for (i = 0; i < dw; i++) + val[i] = xe_mmio_read32(sc->mmio, regs[i]); + + memcpy(frame, val, len); + + return 0; +} + +static void sysctrl_clear_response(struct xe_sysctrl *sc) +{ + xe_mmio_rmw32(sc->mmio, SYSCTRL_MB_CTRL, SYSCTRL_MB_CTRL_RUN_BUSY_OUT, 0); +} + +static int sysctrl_prepare_command(struct xe_device *xe, + u8 group_id, u8 command, + const void *data_in, size_t data_in_len, + u8 **mbox_cmd, size_t *cmd_size) +{ + struct xe_sysctrl_mailbox_msg_hdr *hdr; + size_t size; + u8 *buffer; + + xe_assert(xe, command <= SYSCTRL_HDR_COMMAND_MAX); + + if (data_in_len > XE_SYSCTRL_MB_MAX_MESSAGE_SIZE - sizeof(*hdr)) { + xe_err(xe, "sysctrl: Input data too large: %zu bytes\n", data_in_len); + return -EINVAL; + } + + size = sizeof(*hdr) + data_in_len; + + buffer = kmalloc(size, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + hdr = (struct xe_sysctrl_mailbox_msg_hdr *)buffer; + hdr->data = cpu_to_le32(FIELD_PREP(SYSCTRL_HDR_GROUP_ID_MASK, group_id) | + FIELD_PREP(SYSCTRL_HDR_COMMAND_MASK, command)); + + if (data_in && data_in_len) + memcpy(buffer + sizeof(*hdr), data_in, data_in_len); + + *mbox_cmd = buffer; + *cmd_size = size; + + return 0; +} + +static int sysctrl_send_frames(struct xe_sysctrl *sc, + const u8 *mbox_cmd, + size_t cmd_size, unsigned int timeout_ms) +{ + struct xe_device *xe = sc_to_xe(sc); + u32 ctrl_reg, total_frames, frame; + size_t bytes_sent, frame_size; + + total_frames = DIV_ROUND_UP(cmd_size, XE_SYSCTRL_MB_FRAME_SIZE); + + if (!sysctrl_wait_bit_clear(sc, SYSCTRL_MB_CTRL_RUN_BUSY, timeout_ms)) { + xe_err(xe, "sysctrl: Mailbox busy\n"); + return -EBUSY; + } + + sc->phase_bit ^= 1; + bytes_sent = 0; + + for (frame = 0; frame < total_frames; frame++) { + frame_size = min_t(size_t, cmd_size - bytes_sent, XE_SYSCTRL_MB_FRAME_SIZE); + + if (sysctrl_write_frame(sc, mbox_cmd + bytes_sent, frame_size)) { + xe_err(xe, "sysctrl: Failed to write frame %u\n", frame); + sc->phase_bit = 0; + return -EIO; + } + + ctrl_reg = SYSCTRL_MB_CTRL_RUN_BUSY | + REG_FIELD_PREP(SYSCTRL_FRAME_CURRENT_MASK, frame) | + REG_FIELD_PREP(SYSCTRL_FRAME_TOTAL_MASK, total_frames - 1) | + SYSCTRL_MB_CTRL_CMD | + (sc->phase_bit ? SYSCTRL_FRAME_PHASE : 0); + + xe_mmio_write32(sc->mmio, SYSCTRL_MB_CTRL, ctrl_reg); + + if (!sysctrl_wait_bit_clear(sc, SYSCTRL_MB_CTRL_RUN_BUSY, timeout_ms)) { + xe_err(xe, "sysctrl: Frame %u acknowledgment timeout\n", frame); + sc->phase_bit = 0; + return -ETIMEDOUT; + } + + bytes_sent += frame_size; + } + + return 0; +} + +static int sysctrl_process_frame(struct xe_sysctrl *sc, void *out, + size_t frame_size, unsigned int timeout_ms, + bool *done) +{ + u32 curr_frame, total_frames, ctrl_reg; + struct xe_device *xe = sc_to_xe(sc); + int ret; + + if (!sysctrl_wait_bit_set(sc, SYSCTRL_MB_CTRL_RUN_BUSY_OUT, timeout_ms)) { + xe_err(xe, "sysctrl: Response frame timeout\n"); + return -ETIMEDOUT; + } + + ctrl_reg = xe_mmio_read32(sc->mmio, SYSCTRL_MB_CTRL); + total_frames = FIELD_GET(SYSCTRL_FRAME_TOTAL_MASK, ctrl_reg); + curr_frame = FIELD_GET(SYSCTRL_FRAME_CURRENT_MASK, ctrl_reg); + + ret = sysctrl_read_frame(sc, out, frame_size); + if (ret) + return ret; + + sysctrl_clear_response(sc); + + if (curr_frame == total_frames) + *done = true; + + return 0; +} + +static int sysctrl_receive_frames(struct xe_sysctrl *sc, + const struct xe_sysctrl_mailbox_msg_hdr *req, + void *data_out, size_t data_out_len, + size_t *rdata_len, unsigned int timeout_ms) +{ + struct xe_sysctrl_mailbox_msg_hdr *hdr; + struct xe_device *xe = sc_to_xe(sc); + size_t remain = sizeof(*hdr) + data_out_len; + u8 *buffer __free(kfree) = kzalloc(remain, GFP_KERNEL); + size_t frame_size; + bool done = false; + int ret = 0; + u8 *out; + + if (!buffer) + return -ENOMEM; + + out = buffer; + while (!done && remain) { + frame_size = min_t(size_t, remain, XE_SYSCTRL_MB_FRAME_SIZE); + + ret = sysctrl_process_frame(sc, out, frame_size, timeout_ms, + &done); + if (ret) + return ret; + + remain -= frame_size; + out += frame_size; + } + + hdr = (struct xe_sysctrl_mailbox_msg_hdr *)buffer; + + if (!XE_SYSCTRL_HDR_IS_RESPONSE(hdr) || + XE_SYSCTRL_HDR_GROUP_ID(hdr) != XE_SYSCTRL_HDR_GROUP_ID(req) || + XE_SYSCTRL_HDR_COMMAND(hdr) != XE_SYSCTRL_HDR_COMMAND(req)) { + xe_err(xe, "sysctrl: Response header mismatch\n"); + return -EPROTO; + } + + if (XE_SYSCTRL_HDR_RESULT(hdr) != 0) { + xe_err(xe, "sysctrl: Firmware error: 0x%02lx\n", + XE_SYSCTRL_HDR_RESULT(hdr)); + return -EIO; + } + + memcpy(data_out, hdr + 1, data_out_len); + *rdata_len = out - buffer - sizeof(*hdr); + + return 0; +} + +static int sysctrl_send_command(struct xe_sysctrl *sc, + const u8 *mbox_cmd, size_t cmd_size, + void *data_out, size_t data_out_len, + size_t *rdata_len, unsigned int timeout_ms) +{ + const struct xe_sysctrl_mailbox_msg_hdr *hdr; + size_t received; + int ret; + + ret = sysctrl_send_frames(sc, mbox_cmd, cmd_size, timeout_ms); + if (ret) + return ret; + + if (!data_out || !rdata_len) + return 0; + + hdr = (const struct xe_sysctrl_mailbox_msg_hdr *)mbox_cmd; + + ret = sysctrl_receive_frames(sc, hdr, data_out, data_out_len, + &received, timeout_ms); + if (ret) + return ret; + + *rdata_len = received; + + return 0; +} + +/** + * xe_sysctrl_mailbox_init - Initialize System Controller mailbox interface + * @sc: System controller structure + * + * Initialize system controller mailbox interface for communication. + */ +void xe_sysctrl_mailbox_init(struct xe_sysctrl *sc) +{ + u32 ctrl_reg; + + ctrl_reg = xe_mmio_read32(sc->mmio, SYSCTRL_MB_CTRL); + sc->phase_bit = (ctrl_reg & SYSCTRL_FRAME_PHASE) ? 1 : 0; +} + +/** + * xe_sysctrl_send_command() - Send mailbox command to System Controller + * @sc: System Controller instance + * @cmd: Command descriptor containing request header and payload buffers + * @rdata_len: Pointer to store actual response data length + * + * Sends a mailbox command to System Controller firmware using + * System Controller mailbox and waits for a response. + * + * Request payload is provided via @cmd->data_in and @cmd->data_in_len. + * If a response is expected, @cmd->data_out must point to a buffer of + * size @cmd->data_out_len supplied by caller. + * + * On success, @rdata_len is updated with number of valid response bytes + * returned by firmware, bounded by @cmd->data_out_len. + * + * Return: 0 on success, or negative errno on failure. + */ +int xe_sysctrl_send_command(struct xe_sysctrl *sc, + struct xe_sysctrl_mailbox_command *cmd, + size_t *rdata_len) +{ + struct xe_device *xe = sc_to_xe(sc); + u8 group_id, command_code; + u8 *mbox_cmd = NULL; + size_t cmd_size = 0; + int ret; + + guard(xe_pm_runtime_noresume)(xe); + + if (!xe->info.has_sysctrl) + return -ENODEV; + + xe_assert(xe, cmd->data_in || cmd->data_out); + xe_assert(xe, !cmd->data_in || cmd->data_in_len); + xe_assert(xe, !cmd->data_out || cmd->data_out_len); + + group_id = XE_SYSCTRL_APP_HDR_GROUP_ID(&cmd->header); + command_code = XE_SYSCTRL_APP_HDR_COMMAND(&cmd->header); + + might_sleep(); + + ret = sysctrl_prepare_command(xe, group_id, command_code, + cmd->data_in, cmd->data_in_len, + &mbox_cmd, &cmd_size); + if (ret) { + xe_err(xe, "sysctrl: Failed to prepare command: %pe\n", ERR_PTR(ret)); + return ret; + } + + guard(mutex)(&sc->cmd_lock); + + ret = sysctrl_send_command(sc, mbox_cmd, cmd_size, + cmd->data_out, cmd->data_out_len, rdata_len, + XE_SYSCTRL_MB_DEFAULT_TIMEOUT_MS); + if (ret) + xe_err(xe, "sysctrl: Mailbox command failed: %pe\n", ERR_PTR(ret)); + + kfree(mbox_cmd); + + return ret; +} From 02eca6edcb324bc37495930c344e235a90f42d72 Mon Sep 17 00:00:00 2001 From: Anoop Vijay Date: Fri, 27 Mar 2026 06:18:43 -0700 Subject: [PATCH 014/120] drm/xe/xe_sysctrl: Add System Controller power management support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add resume handling for System Controller to support system (S3/S4) and runtime power management transitions. On resume, restore SoC remapper configuration and mailbox interface to re‑establish communication with firmware. Signed-off-by: Anoop Vijay Reviewed-by: Umesh Nerlige Ramappa Reviewed-by: Badal Nilawar Signed-off-by: Umesh Nerlige Ramappa Link: https://patch.msgid.link/20260327131837.2192929-15-anoop.c.vijay@intel.com --- drivers/gpu/drm/xe/xe_pm.c | 6 ++++++ drivers/gpu/drm/xe/xe_sysctrl.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/xe/xe_sysctrl.h | 1 + 3 files changed, 29 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c index 01185f10a883..d4672eb07476 100644 --- a/drivers/gpu/drm/xe/xe_pm.c +++ b/drivers/gpu/drm/xe/xe_pm.c @@ -26,6 +26,7 @@ #include "xe_pcode.h" #include "xe_pxp.h" #include "xe_sriov_vf_ccs.h" +#include "xe_sysctrl.h" #include "xe_trace.h" #include "xe_vm.h" #include "xe_wa.h" @@ -259,6 +260,8 @@ int xe_pm_resume(struct xe_device *xe) xe_i2c_pm_resume(xe, true); + xe_sysctrl_pm_resume(xe); + xe_irq_resume(xe); for_each_gt(gt, xe, id) { @@ -670,6 +673,9 @@ int xe_pm_runtime_resume(struct xe_device *xe) xe_i2c_pm_resume(xe, xe->d3cold.allowed); + if (xe->d3cold.allowed) + xe_sysctrl_pm_resume(xe); + xe_irq_resume(xe); for_each_gt(gt, xe, id) { diff --git a/drivers/gpu/drm/xe/xe_sysctrl.c b/drivers/gpu/drm/xe/xe_sysctrl.c index 850f9dd7e9f0..2bcef304eb9a 100644 --- a/drivers/gpu/drm/xe/xe_sysctrl.c +++ b/drivers/gpu/drm/xe/xe_sysctrl.c @@ -77,3 +77,25 @@ int xe_sysctrl_init(struct xe_device *xe) return 0; } + +/** + * xe_sysctrl_pm_resume() - System Controller resume handler + * @xe: xe device instance + * + * Invoked during system resume (S3/S4 to S0) and runtime resume from D3cold. + * Restores SoC remapper configuration and reinitializes mailbox interface. + */ +void xe_sysctrl_pm_resume(struct xe_device *xe) +{ + struct xe_sysctrl *sc = &xe->sc; + + if (!xe->info.has_soc_remapper_sysctrl) + return; + + if (!xe->info.has_sysctrl) + return; + + xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX); + + xe_sysctrl_mailbox_init(sc); +} diff --git a/drivers/gpu/drm/xe/xe_sysctrl.h b/drivers/gpu/drm/xe/xe_sysctrl.h index d5d8735038ae..f3b0f3716b2f 100644 --- a/drivers/gpu/drm/xe/xe_sysctrl.h +++ b/drivers/gpu/drm/xe/xe_sysctrl.h @@ -17,5 +17,6 @@ static inline struct xe_device *sc_to_xe(struct xe_sysctrl *sc) } int xe_sysctrl_init(struct xe_device *xe); +void xe_sysctrl_pm_resume(struct xe_device *xe); #endif From a902767f91ba9818b792f1137d3a835310c7d265 Mon Sep 17 00:00:00 2001 From: Anoop Vijay Date: Fri, 27 Mar 2026 06:18:44 -0700 Subject: [PATCH 015/120] drm/xe/xe_pci: Enable System Controller support on CRI platform Enable System Controller support on CRI by setting has_sysctrl capability flag in device descriptor and runtime device information. This allows sysctrl subsystem and mailbox communication to be initialized on CRI platforms. Signed-off-by: Anoop Vijay Reviewed-by: Umesh Nerlige Ramappa Signed-off-by: Umesh Nerlige Ramappa Link: https://patch.msgid.link/20260327131837.2192929-16-anoop.c.vijay@intel.com --- drivers/gpu/drm/xe/xe_pci.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index 01673d2b2464..26eb58e11056 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -465,6 +465,7 @@ static const struct xe_device_desc cri_desc = { .has_soc_remapper_sysctrl = true, .has_soc_remapper_telem = true, .has_sriov = true, + .has_sysctrl = true, .max_gt_per_tile = 2, MULTI_LRC_MASK, .require_force_probe = true, @@ -763,6 +764,7 @@ static int xe_info_init_early(struct xe_device *xe, xe->info.has_soc_remapper_telem = desc->has_soc_remapper_telem; xe->info.has_sriov = xe_configfs_primary_gt_allowed(to_pci_dev(xe->drm.dev)) && desc->has_sriov; + xe->info.has_sysctrl = desc->has_sysctrl; xe->info.skip_guc_pc = desc->skip_guc_pc; xe->info.skip_mtcfg = desc->skip_mtcfg; xe->info.skip_pcode = desc->skip_pcode; @@ -959,6 +961,12 @@ static int xe_info_init(struct xe_device *xe, xe->info.has_64bit_timestamp = graphics_desc->has_64bit_timestamp; xe->info.has_mem_copy_instr = GRAPHICS_VER(xe) >= 20; + if (IS_SRIOV_VF(xe)) { + xe->info.has_sysctrl = 0; + xe->info.has_soc_remapper_sysctrl = 0; + xe->info.has_soc_remapper_telem = 0; + } + xe_info_probe_tile_count(xe); for_each_remote_tile(tile, xe, id) { From 72d918472886b6e1b998b756303816737929ef0a Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Mon, 16 Mar 2026 22:27:23 +0000 Subject: [PATCH 016/120] drm/xe/ggtt: Remove duplicate XE_GGTT_FLAGS_64K macro definition XE_GGTT_FLAGS_64K is defined twice in xe_ggtt.c: once at file scope (alongside XE_GGTT_FLAGS_ONLINE) and once inside struct xe_ggtt. The duplicate inside the struct was originally the only definition when the struct lived in xe_ggtt_types.h, but when commit 4f3a998a173b ("drm/xe: Open-code GGTT MMIO access protection") added the file-scope definitions for both FLAGS_64K and FLAGS_ONLINE, it did not remove the pre-existing one inside the struct. Remove the redundant definition inside struct xe_ggtt, keeping only the file-scope pair at the top of the file. Cc: Matthew Brost Reviewed-by: Zongyao Bai Signed-off-by: Shuicheng Lin Link: https://patch.msgid.link/20260316222723.1722591-2-shuicheng.lin@intel.com --- drivers/gpu/drm/xe/xe_ggtt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index a848d1a41b9b..3552fa3cac4b 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -115,7 +115,6 @@ struct xe_ggtt { /** @size: Total usable size of this GGTT */ u64 size; -#define XE_GGTT_FLAGS_64K BIT(0) /** * @flags: Flags for this GGTT * Acceptable flags: From f47bf47a1afaf5a8ad3629f1fd4a5a0150ae59e9 Mon Sep 17 00:00:00 2001 From: Chen Ni Date: Fri, 27 Mar 2026 11:29:23 +0800 Subject: [PATCH 017/120] drm/xe/vm: Convert comma to semicolon Using a ',' in place of a ';' can have unintended side effects. Although that is not the case here, it seems best to use ';' unless ',' is intended. Found by inspection. No functional change intended. Compile tested only. Signed-off-by: Chen Ni Reviewed-by: Shuicheng Lin Signed-off-by: Shuicheng Lin Link: https://patch.msgid.link/20260327032923.649869-1-nichen@iscas.ac.cn --- drivers/gpu/drm/xe/xe_vm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 56e2db50bb36..72559bd33946 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -634,9 +634,9 @@ void xe_vm_add_fault_entry_pf(struct xe_vm *vm, struct xe_pagefault *pf) e->address_precision = SZ_4K; e->access_type = pf->consumer.access_type; e->fault_type = FIELD_GET(XE_PAGEFAULT_TYPE_MASK, - pf->consumer.fault_type_level), + pf->consumer.fault_type_level); e->fault_level = FIELD_GET(XE_PAGEFAULT_LEVEL_MASK, - pf->consumer.fault_type_level), + pf->consumer.fault_type_level); list_add_tail(&e->list, &vm->faults.list); vm->faults.len++; From 28c83ed7ceea67b3b411ddb30ff1e3181fc3af94 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 27 Mar 2026 21:24:06 +0100 Subject: [PATCH 018/120] drm/xe/uc: Track uc firmware state changes Under CONFIG_DRM_XE_DEBUG_GUC print debug messages with each uc firmware state transition to better visualize the changes. [drm:xe_uc_fw_change_status [xe]] Tile0: GT0: GuC UNINITIALIZED->SELECTED [drm:xe_uc_fw_change_status [xe]] Tile0: GT0: GuC SELECTED->AVAILABLE [drm:xe_uc_fw_change_status [xe]] Tile0: GT0: GuC AVAILABLE->LOADABLE [drm:xe_uc_fw_change_status [xe]] Tile0: GT0: GuC LOADABLE->TRANSFERRED [drm:xe_uc_fw_change_status [xe]] Tile0: GT0: GuC TRANSFERRED->RUNNING Signed-off-by: Michal Wajdeczko Reviewed-by: Matthew Brost Link: https://patch.msgid.link/20260327202407.563-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_uc_fw.c | 11 +++++++++++ drivers/gpu/drm/xe/xe_uc_fw.h | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c index 9cebb2490245..df2aa196f6f9 100644 --- a/drivers/gpu/drm/xe/xe_uc_fw.c +++ b/drivers/gpu/drm/xe/xe_uc_fw.c @@ -214,6 +214,17 @@ static struct xe_device *uc_fw_to_xe(struct xe_uc_fw *uc_fw) return gt_to_xe(uc_fw_to_gt(uc_fw)); } +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC) +void xe_uc_fw_change_status(struct xe_uc_fw *uc_fw, enum xe_uc_fw_status status) +{ + xe_gt_dbg(uc_fw_to_gt(uc_fw), "%s %s->%s\n", + xe_uc_fw_type_repr(uc_fw->type), + xe_uc_fw_status_repr(uc_fw->status), + xe_uc_fw_status_repr(status)); + uc_fw->__status = status; +} +#endif + static void uc_fw_auto_select(struct xe_device *xe, struct xe_uc_fw *uc_fw) { diff --git a/drivers/gpu/drm/xe/xe_uc_fw.h b/drivers/gpu/drm/xe/xe_uc_fw.h index 6195e353f269..bb281b72a677 100644 --- a/drivers/gpu/drm/xe/xe_uc_fw.h +++ b/drivers/gpu/drm/xe/xe_uc_fw.h @@ -25,11 +25,15 @@ static inline u32 xe_uc_fw_rsa_offset(struct xe_uc_fw *uc_fw) return sizeof(struct uc_css_header) + uc_fw->ucode_size + uc_fw->css_offset; } +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC) +void xe_uc_fw_change_status(struct xe_uc_fw *uc_fw, enum xe_uc_fw_status status); +#else static inline void xe_uc_fw_change_status(struct xe_uc_fw *uc_fw, enum xe_uc_fw_status status) { uc_fw->__status = status; } +#endif static inline const char *xe_uc_fw_status_repr(enum xe_uc_fw_status status) From d0672008cde3a8616c517d53d657300dce3c36a7 Mon Sep 17 00:00:00 2001 From: Nareshkumar Gollakoti Date: Thu, 26 Mar 2026 12:04:09 +0530 Subject: [PATCH 019/120] drm/xe: Set GT rp min frequency as 1.2GHz default for BMG/CRI While previously applied only to both tiles GT0(Graphics) and Media(GT1) the BMG G21(Battle image) platform via workaround Wa_14022085890, this 1.2 GHz minimum is now the default for GT0(Graphics) tile of BMG and CRI platforms. Setting this frequency floor(1.2GHz) default is critical in multi GPU environment for supporting effective Peer-to-Peer(P2P) transactions. v2: - Fix Indentation(Thomas) - Add comment about power impact(Stuart) v3:(Thomas/Ankur/Matt Roper) - Add setting frequency to only GT0(Graphics) Tile of BMG/CRI v4:(Stuart) - Move WA check to pc_needs_min_freq_change function Signed-off-by: Nareshkumar Gollakoti Reviewed-by: Vinay Belgaumkar Link: https://patch.msgid.link/20260326063407.985568-4-naresh.kumar.g@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_guc_pc.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c index bb8c4e793492..7ecd91ad6192 100644 --- a/drivers/gpu/drm/xe/xe_guc_pc.c +++ b/drivers/gpu/drm/xe/xe_guc_pc.c @@ -890,9 +890,26 @@ void xe_guc_pc_init_early(struct xe_guc_pc *pc) pc_init_fused_rp_values(pc); } +static bool pc_needs_min_freq_change(struct xe_guc_pc *pc) +{ + struct xe_device *xe = pc_to_xe(pc); + struct xe_gt *gt = pc_to_gt(pc); + + if (XE_DEVICE_WA(xe, 14022085890)) + return true; + + if (xe_gt_is_media_type(gt)) + return false; + + if (xe->info.platform == XE_BATTLEMAGE || + xe->info.platform == XE_CRESCENTISLAND) + return true; + + return false; +} + static int pc_adjust_freq_bounds(struct xe_guc_pc *pc) { - struct xe_tile *tile = gt_to_tile(pc_to_gt(pc)); int ret; lockdep_assert_held(&pc->freq_lock); @@ -919,7 +936,18 @@ static int pc_adjust_freq_bounds(struct xe_guc_pc *pc) if (pc_get_min_freq(pc) > pc->rp0_freq) ret = pc_set_min_freq(pc, pc->rp0_freq); - if (XE_DEVICE_WA(tile_to_xe(tile), 14022085890)) + /* + * Setting GT RP min frequency to 1.2GHz by default for + * GT0(Graphics) Tile of BMG and CRI. + * + * While BMG G21 WA will apply min frequency for + * both GT0(Graphics) and GT1(Media) Tile. + * + * This is an active frequency, so if the device is idle + * we aren't expecting high power output across board + * + */ + if (pc_needs_min_freq_change(pc)) ret = pc_set_min_freq(pc, max(BMG_MIN_FREQ, pc_get_min_freq(pc))); out: From 9e7585fb70b24b96de7c444e56c1baf28c0f71a2 Mon Sep 17 00:00:00 2001 From: Mallesh Koujalagi Date: Fri, 27 Mar 2026 15:54:15 +0530 Subject: [PATCH 020/120] drm/xe: Apply WA_14026999295 to engine Apply WA_14026999295 to following IPs: Xe3p_XPC v2: - Move WA to "Xe3p_XPC" section at bottom of table. (Matt) Reviewed-by: Matt Roper Signed-off-by: Mallesh Koujalagi Link: https://patch.msgid.link/20260327102414.780515-2-mallesh.koujalagi@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/regs/xe_gt_regs.h | 1 + drivers/gpu/drm/xe/xe_wa.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h index 4ebaa0888a43..aa267c2f6162 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -528,6 +528,7 @@ #define ROW_CHICKEN3 XE_REG_MCR(0xe49c, XE_REG_OPTION_MASKED) #define XE2_EUPEND_CHK_FLUSH_DIS REG_BIT(14) +#define DIS_EU_GRF_POISON_TO_LSC REG_BIT(13) #define DIS_FIX_EOT1_FLUSH REG_BIT(9) #define TDL_TSL_CHICKEN XE_REG_MCR(0xe4c4, XE_REG_OPTION_MASKED) diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c index 546296f0220b..c3fef8fd73f7 100644 --- a/drivers/gpu/drm/xe/xe_wa.c +++ b/drivers/gpu/drm/xe/xe_wa.c @@ -601,6 +601,14 @@ static const struct xe_rtp_entry_sr engine_was[] = { FUNC(xe_rtp_match_first_render_or_compute)), XE_RTP_ACTIONS(SET(ROW_CHICKEN5, CPSS_AWARE_DIS)) }, + + /* Xe3p_XPC */ + + { XE_RTP_NAME("14026999295"), + XE_RTP_RULES(GRAPHICS_VERSION(3511), + FUNC(xe_rtp_match_first_render_or_compute)), + XE_RTP_ACTIONS(SET(ROW_CHICKEN3, DIS_EU_GRF_POISON_TO_LSC)) + }, }; static const struct xe_rtp_entry_sr lrc_was[] = { From 81ca36e0beaafe5f62fc1eadd99f8dcdf51161c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20Kempczy=C5=84ski?= Date: Tue, 31 Mar 2026 15:43:31 +0200 Subject: [PATCH 021/120] drm/xe/pat: Print PAT_ATS during register dump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For Xe2 and beyond we miss printing PAT_ATS register. Signed-off-by: Zbigniew Kempczyński Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patch.msgid.link/20260331134330.2535519-2-zbigniew.kempczynski@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_pat.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_pat.c b/drivers/gpu/drm/xe/xe_pat.c index 356f53bdb83c..75aaae7b003d 100644 --- a/drivers/gpu/drm/xe/xe_pat.c +++ b/drivers/gpu/drm/xe/xe_pat.c @@ -531,6 +531,14 @@ static int xe2_dump(struct xe_gt *gt, struct drm_printer *p) drm_printf(p, "Page Table Access:\n"); xe->pat.ops->entry_dump(p, "PTA_MODE", pat, false); + if (xe_gt_is_media_type(gt)) + pat = xe_mmio_read32(>->mmio, XE_REG(_PAT_ATS)); + else + pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_ATS)); + + drm_printf(p, "PCIe ATS/PASID:\n"); + xe->pat.ops->entry_dump(p, "PAT_ATS ", pat, false); + return 0; } From 896070686b16cc45cca7854be2049923b2b303d3 Mon Sep 17 00:00:00 2001 From: Jonathan Cavitt Date: Tue, 31 Mar 2026 18:12:17 +0000 Subject: [PATCH 022/120] drm/xe/vm: Add missing pad and extensions check Add missing pad and extensions check to xe_vm_get_property_ioctl v2: - Combine with other check (Auld) Fixes: 50c577eab051 ("drm/xe/xe_vm: Implement xe_vm_get_property_ioctl") Suggested-by: Matthew Auld Signed-off-by: Jonathan Cavitt Reviewed-by: Matthew Auld Reviewed-by: Matthew Brost Signed-off-by: Matthew Auld Link: https://patch.msgid.link/20260331181216.37775-2-jonathan.cavitt@intel.com --- drivers/gpu/drm/xe/xe_vm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 72559bd33946..2408b547ca3d 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -4156,7 +4156,8 @@ int xe_vm_get_property_ioctl(struct drm_device *drm, void *data, int ret = 0; if (XE_IOCTL_DBG(xe, (args->reserved[0] || args->reserved[1] || - args->reserved[2]))) + args->reserved[2] || args->extensions || + args->pad))) return -EINVAL; vm = xe_vm_lookup(xef, args->vm_id); From b82a225e57a334335a21462b75ee2223bc6efe6d Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Wed, 25 Mar 2026 16:16:08 -0700 Subject: [PATCH 023/120] drm/gpusvm: Reject VMAs with VM_IO or VM_PFNMAP when creating SVM ranges MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VMAs marked with VM_IO or VM_PFNMAP are not backed by struct page objects, which GPUSVM requires in order to operate correctly. In particular, get_pages() relies on hmm_range_fault() to resolve struct pages for the target range. Attempting to create an SVM range on such VMAs results in repeated get_pages() failures and can lead to an infinite loop inside a driver’s page‑fault handler. Prevent this by rejecting ranges on VM_IO or VM_PFNMAP VMAs and returning -EIO. Fixes: 99624bdff867 ("drm/gpusvm: Add support for GPU Shared Virtual Memory") Signed-off-by: Matthew Brost Reviewed-by: Himal Prasad Ghimiray Link: https://patch.msgid.link/20260325231608.25581-1-matthew.brost@intel.com --- drivers/gpu/drm/drm_gpusvm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index 4b928fda5b12..7993e85c0566 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -1065,6 +1065,11 @@ drm_gpusvm_range_find_or_insert(struct drm_gpusvm *gpusvm, goto err_notifier_remove; } + if (vas->vm_flags & (VM_IO | VM_PFNMAP)) { + err = -EIO; + goto err_notifier_remove; + } + range = drm_gpusvm_range_find(notifier, fault_addr, fault_addr + 1); if (range) goto out_mmunlock; From c79bc999442ff3c0908ab8bce92b2a3cb7d59861 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Wed, 1 Apr 2026 13:12:44 -0700 Subject: [PATCH 024/120] drm/xe: Drop redundant rtp entries for Wa_14019988906 & Wa_14019877138 There appears to have been a silent merge conflict between some commits updating the workaround tables on Xe's -fixes and -next branches: - Commit bc6387a2e0c1 ("drm/xe/xe2_hpg: Fix handling of Wa_14019988906 & Wa_14019877138") from the fixes branch moved the Xe2_HPG instance of two workarounds touching the PSS_CHICKEN register from the engine_was[] table to the lrc_was[] table; the equivalent implementation for all other platforms/IPs were already properly located on lrc_was[]. This commit on the fixes branch is a cherry-pick of commit e04c609eedf4 ("drm/xe/xe2_hpg: Fix handling of Wa_14019988906 & Wa_14019877138") that already existed on the next branch. - Commit 55b19abb6c44 ("drm/xe: Consolidate workaround entries for Wa_14019877138") and commit c2142a1a8415 ("drm/xe: Consolidate workaround entries for Wa_14019988906") consolidated the individual entries per IP generation for each workaround into single, larger range-based entries. During merge conflict resolution the Xe2_HPG-specific entries (i.e., those with rule "GRAPHICS_VERSION_RANGE(2001, 2002)") were accidentally resurrected, even though the table already contains the consolidated entries that match a superset of thse ranges. These redundant entries don't cause any build failures but do trigger a dmesg error during probe on BMG-G21 devices: xe 0000:03:00.0: [drm] *ERROR* Tile0: GT0: discarding save-restore reg 7044 (clear: 00000400, set: 00000400, masked: yes, mcr: yes): ret=-22 xe 0000:03:00.0: [drm] *ERROR* Tile0: GT0: discarding save-restore reg 7044 (clear: 00000020, set: 00000020, masked: yes, mcr: yes): ret=-22 Re-drop the Xe2_HPG-specific table entries to eliminate the error. Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/work_items/7433 Fixes: 17b95278ae6a ("Merge tag 'drm-xe-next-2026-03-02' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-next") Cc: Dave Airlie Signed-off-by: Matt Roper Reviewed-by: Shuicheng Lin Link: https://patch.msgid.link/20260401-wa_merge_conflict-v1-1-b477ab53fedc@intel.com Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/xe/xe_wa.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c index c3fef8fd73f7..2ec70be78bf9 100644 --- a/drivers/gpu/drm/xe/xe_wa.c +++ b/drivers/gpu/drm/xe/xe_wa.c @@ -751,14 +751,6 @@ static const struct xe_rtp_entry_sr lrc_was[] = { XE_RTP_RULES(GRAPHICS_VERSION(2001), ENGINE_CLASS(RENDER)), XE_RTP_ACTIONS(SET(WM_CHICKEN3, HIZ_PLANE_COMPRESSION_DIS)) }, - { XE_RTP_NAME("14019988906"), - XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2002), ENGINE_CLASS(RENDER)), - XE_RTP_ACTIONS(SET(XEHP_PSS_CHICKEN, FLSH_IGNORES_PSD)) - }, - { XE_RTP_NAME("14019877138"), - XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2002), ENGINE_CLASS(RENDER)), - XE_RTP_ACTIONS(SET(XEHP_PSS_CHICKEN, FD_END_COLLECT)) - }, { XE_RTP_NAME("14021490052"), XE_RTP_RULES(GRAPHICS_VERSION(2001), ENGINE_CLASS(RENDER)), XE_RTP_ACTIONS(SET(FF_MODE, From 72d0c064564192d4fba2bf00f78ae303206fa2cc Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Thu, 2 Apr 2026 11:05:50 -0700 Subject: [PATCH 025/120] drm/xe: improve readability of debugfs engine info output Improve the readability of the info debugfs output by replacing raw numeric engine masks with human-readable engine and class names. Also print per-GT engine capability data in a form that is easier for a human to interpret directly, and as a side effect simpler for IGT tests to use when validating engine capabilities. Reviewed-by: Niranjana Vishwanathapura Reviewed-by: Matt Roper Signed-off-by: Xin Wang Link: https://patch.msgid.link/20260402180552.24121-2-x.wang@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_debugfs.c | 41 +++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c index 844cfafe1ec7..490d7ef7e812 100644 --- a/drivers/gpu/drm/xe/xe_debugfs.c +++ b/drivers/gpu/drm/xe/xe_debugfs.c @@ -15,9 +15,11 @@ #include "xe_bo.h" #include "xe_device.h" #include "xe_force_wake.h" +#include "xe_gt.h" #include "xe_gt_debugfs.h" #include "xe_gt_printk.h" #include "xe_guc_ads.h" +#include "xe_hw_engine.h" #include "xe_mmio.h" #include "xe_pm.h" #include "xe_psmi.h" @@ -61,6 +63,37 @@ static struct xe_device *node_to_xe(struct drm_info_node *node) return to_xe_device(node->minor->dev); } +static void print_engine_class_mask(struct drm_printer *p, u16 mask) +{ + if (!mask) { + drm_printf(p, " none\n"); + return; + } + + for (enum xe_engine_class ec = 0; ec < XE_ENGINE_CLASS_MAX; ec++) { + if (mask & BIT(ec)) + drm_printf(p, " %s", xe_hw_engine_class_to_str(ec)); + } + drm_printf(p, "\n"); +} + +static void print_engine_mask(struct drm_printer *p, struct xe_gt *gt, u64 mask) +{ + struct xe_hw_engine *hwe; + enum xe_hw_engine_id id; + + if (!mask) { + drm_printf(p, " none\n"); + return; + } + + for_each_hw_engine(hwe, gt, id) { + if (mask & BIT_ULL(id)) + drm_printf(p, " %s", hwe->name); + } + drm_printf(p, "\n"); +} + static int info(struct seq_file *m, void *data) { struct xe_device *xe = node_to_xe(m->private); @@ -91,10 +124,10 @@ static int info(struct seq_file *m, void *data) for_each_gt(gt, xe, id) { drm_printf(&p, "gt%d force wake %d\n", id, xe_force_wake_ref(gt_to_fw(gt), XE_FW_GT)); - drm_printf(&p, "gt%d engine_mask 0x%llx\n", id, - gt->info.engine_mask); - drm_printf(&p, "gt%d multi_queue_engine_class_mask 0x%x\n", id, - gt->info.multi_queue_engine_class_mask); + drm_printf(&p, "gt%d engines", id); + print_engine_mask(&p, gt, gt->info.engine_mask); + drm_printf(&p, "gt%d multi_queue_engine_classes", id); + print_engine_class_mask(&p, gt->info.multi_queue_engine_class_mask); } return 0; From cc708deedf686c68e84851e89a2f7844dc0536ae Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Thu, 2 Apr 2026 11:05:51 -0700 Subject: [PATCH 026/120] drm/xe: expose multi-lrc engine classes in debugfs info Expose multi_lrc_engine_classes in the info debugfs output as a useful extra piece of information for debugging. Reviewed-by: Niranjana Vishwanathapura Signed-off-by: Xin Wang Link: https://patch.msgid.link/20260402180552.24121-3-x.wang@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_debugfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c index 490d7ef7e812..c9d4484821af 100644 --- a/drivers/gpu/drm/xe/xe_debugfs.c +++ b/drivers/gpu/drm/xe/xe_debugfs.c @@ -121,6 +121,8 @@ static int info(struct seq_file *m, void *data) drm_printf(&p, "has_flat_ccs %s\n", str_yes_no(xe->info.has_flat_ccs)); drm_printf(&p, "has_usm %s\n", str_yes_no(xe->info.has_usm)); drm_printf(&p, "skip_guc_pc %s\n", str_yes_no(xe->info.skip_guc_pc)); + drm_printf(&p, "multi_lrc_engine_classes"); + print_engine_class_mask(&p, xe->info.multi_lrc_mask); for_each_gt(gt, xe, id) { drm_printf(&p, "gt%d force wake %d\n", id, xe_force_wake_ref(gt_to_fw(gt), XE_FW_GT)); From f9a21696e37b069c96b81fa0ad8392b7b6d4a47e Mon Sep 17 00:00:00 2001 From: Julia Filipchuk Date: Tue, 3 Mar 2026 16:34:24 -0800 Subject: [PATCH 027/120] drm/xe: Enable Wa_14025515070 Corrects a failure on context switch. On registration of context with indirect ring state will correct state of targeted and idle command streamers. This Wa requires GuC 70.53+ (uapi 1.26+). If indirect_ring_state is enabled and Wa is unavailable, notify and disable indirect_ring_state. Added additional XE_RTP_PASTE macros for expansion of longer rules. Reviewed-by: Daniele Ceraolo Spurio Signed-off-by: Julia Filipchuk Signed-off-by: Vinay Belgaumkar Link: https://patch.msgid.link/20260304003431.758201-4-julia.filipchuk@intel.com --- drivers/gpu/drm/xe/abi/guc_klvs_abi.h | 1 + drivers/gpu/drm/xe/xe_guc.c | 8 ++++++++ drivers/gpu/drm/xe/xe_guc_ads.c | 3 +++ drivers/gpu/drm/xe/xe_rtp_helpers.h | 2 ++ drivers/gpu/drm/xe/xe_wa_oob.rules | 7 +++++++ 5 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/xe/abi/guc_klvs_abi.h b/drivers/gpu/drm/xe/abi/guc_klvs_abi.h index e33bd622ab44..f0815500177b 100644 --- a/drivers/gpu/drm/xe/abi/guc_klvs_abi.h +++ b/drivers/gpu/drm/xe/abi/guc_klvs_abi.h @@ -496,6 +496,7 @@ enum xe_guc_klv_ids { GUC_WA_KLV_WAKE_POWER_DOMAINS_FOR_OUTBOUND_MMIO = 0x900a, GUC_WA_KLV_RESET_BB_STACK_PTR_ON_VF_SWITCH = 0x900b, GUC_WA_KLV_RESTORE_UNSAVED_MEDIA_CONTROL_REG = 0x900c, + GUC_WA_KLV_CLR_CS_INDIRECT_RING_STATE_IF_IDLE_AT_CTX_REG = 0x900e, }; #endif diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c index ccebb437e37f..e762eada21db 100644 --- a/drivers/gpu/drm/xe/xe_guc.c +++ b/drivers/gpu/drm/xe/xe_guc.c @@ -780,6 +780,14 @@ int xe_guc_init(struct xe_guc *guc) if (GUC_SUBMIT_VER(guc) < MAKE_GUC_VER(1, 14, 0)) xe->info.has_page_reclaim_hw_assist = false; + /* Disable indirect_ring_state if missing GuC 70.53+ WA 14025515070. */ + if (gt->info.has_indirect_ring_state && + XE_GT_WA(gt, 14025515070) && + GUC_SUBMIT_VER(guc) < MAKE_GUC_VER(1, 26, 0)) { + gt->info.has_indirect_ring_state = 0; + xe_gt_notice(gt, "indirect ring state requires WA in GuC submit ver 1.26+\n"); + } + if (IS_SRIOV_VF(xe)) { ret = devm_add_action_or_reset(xe->drm.dev, vf_guc_fini_hw, guc); if (ret) diff --git a/drivers/gpu/drm/xe/xe_guc_ads.c b/drivers/gpu/drm/xe/xe_guc_ads.c index 81b5f01b1f65..92c6981fe220 100644 --- a/drivers/gpu/drm/xe/xe_guc_ads.c +++ b/drivers/gpu/drm/xe/xe_guc_ads.c @@ -360,6 +360,9 @@ static void guc_waklv_init(struct xe_guc_ads *ads) if (XE_GT_WA(gt, 14020001231)) guc_waklv_enable(ads, NULL, 0, &offset, &remain, GUC_WORKAROUND_KLV_DISABLE_PSMI_INTERRUPTS_AT_C6_ENTRY_RESTORE_AT_EXIT); + if (XE_GT_WA(gt, 14025515070) && GUC_FIRMWARE_VER_AT_LEAST(>->uc.guc, 70, 53)) + guc_waklv_enable(ads, NULL, 0, &offset, &remain, + GUC_WA_KLV_CLR_CS_INDIRECT_RING_STATE_IF_IDLE_AT_CTX_REG); size = guc_ads_waklv_size(ads) - remain; if (!size) diff --git a/drivers/gpu/drm/xe/xe_rtp_helpers.h b/drivers/gpu/drm/xe/xe_rtp_helpers.h index a33b0ae98bbc..86eee60c04a1 100644 --- a/drivers/gpu/drm/xe/xe_rtp_helpers.h +++ b/drivers/gpu/drm/xe/xe_rtp_helpers.h @@ -66,6 +66,8 @@ #define XE_RTP_PASTE_10(prefix_, sep_, args_) _XE_RTP_CONCAT(prefix_, FIRST_ARG args_) __XE_RTP_PASTE_SEP_ ## sep_ XE_RTP_PASTE_9(prefix_, sep_, _XE_TUPLE_TAIL args_) #define XE_RTP_PASTE_11(prefix_, sep_, args_) _XE_RTP_CONCAT(prefix_, FIRST_ARG args_) __XE_RTP_PASTE_SEP_ ## sep_ XE_RTP_PASTE_10(prefix_, sep_, _XE_TUPLE_TAIL args_) #define XE_RTP_PASTE_12(prefix_, sep_, args_) _XE_RTP_CONCAT(prefix_, FIRST_ARG args_) __XE_RTP_PASTE_SEP_ ## sep_ XE_RTP_PASTE_11(prefix_, sep_, _XE_TUPLE_TAIL args_) +#define XE_RTP_PASTE_13(prefix_, sep_, args_) _XE_RTP_CONCAT(prefix_, FIRST_ARG args_) __XE_RTP_PASTE_SEP_ ## sep_ XE_RTP_PASTE_12(prefix_, sep_, _XE_TUPLE_TAIL args_) +#define XE_RTP_PASTE_14(prefix_, sep_, args_) _XE_RTP_CONCAT(prefix_, FIRST_ARG args_) __XE_RTP_PASTE_SEP_ ## sep_ XE_RTP_PASTE_13(prefix_, sep_, _XE_TUPLE_TAIL args_) /* * XE_RTP_DROP_CAST - Drop cast to convert a compound statement to a initializer diff --git a/drivers/gpu/drm/xe/xe_wa_oob.rules b/drivers/gpu/drm/xe/xe_wa_oob.rules index 80b54b195f20..f8a185103b80 100644 --- a/drivers/gpu/drm/xe/xe_wa_oob.rules +++ b/drivers/gpu/drm/xe/xe_wa_oob.rules @@ -51,6 +51,13 @@ MEDIA_VERSION_RANGE(2000, 3002), FUNC(xe_rtp_match_psmi_enabled) 16023683509 MEDIA_VERSION(2000), FUNC(xe_rtp_match_psmi_enabled) MEDIA_VERSION(3000), MEDIA_STEP(A0, B0), FUNC(xe_rtp_match_psmi_enabled) +14025515070 GRAPHICS_VERSION(2004) + MEDIA_VERSION_RANGE(1301, 3000) + MEDIA_VERSION(3002) + GRAPHICS_VERSION_RANGE(3000, 3001) + GRAPHICS_VERSION_RANGE(3003, 3005) + MEDIA_VERSION(3500) + GRAPHICS_VERSION(3510), GRAPHICS_STEP(A0, B0) 15015404425_disable PLATFORM(PANTHERLAKE), MEDIA_STEP(B0, FOREVER) 16026007364 MEDIA_VERSION(3000) From 13743bd628bc9d9a0e2fe53488b2891aedf7cc74 Mon Sep 17 00:00:00 2001 From: Vinay Belgaumkar Date: Tue, 31 Mar 2026 18:27:10 -0700 Subject: [PATCH 028/120] drm/xe: Fix bug in idledly unit conversion We only need to convert to picosecond units before writing to RING_IDLEDLY. Fixes: 7c53ff050ba8 ("drm/xe: Apply Wa_16023105232") Cc: Tangudu Tilak Tirumalesh Acked-by: Tangudu Tilak Tirumalesh Signed-off-by: Vinay Belgaumkar Link: https://patch.msgid.link/20260401012710.4165547-1-vinay.belgaumkar@intel.com --- drivers/gpu/drm/xe/xe_hw_engine.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index 337baf0a6e87..6dd05fac6595 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -597,9 +597,8 @@ static void adjust_idledly(struct xe_hw_engine *hwe) maxcnt *= maxcnt_units_ns; if (xe_gt_WARN_ON(gt, idledly >= maxcnt || inhibit_switch)) { - idledly = DIV_ROUND_CLOSEST(((maxcnt - 1) * maxcnt_units_ns), + idledly = DIV_ROUND_CLOSEST(((maxcnt - 1) * 1000), idledly_units_ps); - idledly = DIV_ROUND_CLOSEST(idledly, 1000); xe_mmio_write32(>->mmio, RING_IDLEDLY(hwe->mmio_base), idledly); } } From ec4f4970eb744fd7d6d135f40f5c83bd05982e72 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Wed, 1 Apr 2026 19:10:51 -0300 Subject: [PATCH 029/120] drm/xe/xe3p_lpg: Add missing indirect ring state feature flag Even though commit 8fcb7dfb8bbf ("drm/xe/xe3p_lpg: Add support for graphics IP 35.10") mentions that the support for Indirect Ring State exists for Xe3p_LPG, it missed actually setting the feature flag in graphics_xe3p_lpg. Fix that by adding the missing member. Fixes: 8fcb7dfb8bbf ("drm/xe/xe3p_lpg: Add support for graphics IP 35.10") Reviewed-by: Matt Roper Link: https://patch.msgid.link/20260401-xe3p_lpg-indirect-ring-state-v1-1-0e4b5edf6898@intel.com Signed-off-by: Gustavo Sousa --- drivers/gpu/drm/xe/xe_pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index 26eb58e11056..b1b89d09e42b 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -118,6 +118,7 @@ static const struct xe_graphics_desc graphics_xe2 = { static const struct xe_graphics_desc graphics_xe3p_lpg = { XE2_GFX_FEATURES, + .has_indirect_ring_state = 1, .multi_queue_engine_class_mask = BIT(XE_ENGINE_CLASS_COPY) | BIT(XE_ENGINE_CLASS_COMPUTE), .num_geometry_xecore_fuse_regs = 3, .num_compute_xecore_fuse_regs = 3, From e7ac8ddfefa3729e858ac9c5a0c9af3a53d4c699 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 17 Mar 2026 21:57:17 +0000 Subject: [PATCH 030/120] drm/xe: Add missing include guards to unprotected headers Two headers lack include guards entirely, which can cause duplicate definition errors if they are included more than once (directly or transitively). Add standard _XE__H_ include guards to: - xe_dep_scheduler.h: forward declarations and function prototypes - xe_pcode_api.h: PCODE mailbox register definitions No functional change. Suggested-by: Nitin Gote Assisted-by: GitHub Copilot:claude-opus-4.6 Reviewed-by: Nitin Gote Link: https://patch.msgid.link/20260317215732.2208976-8-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_dep_scheduler.h | 5 +++++ drivers/gpu/drm/xe/xe_pcode_api.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_dep_scheduler.h b/drivers/gpu/drm/xe/xe_dep_scheduler.h index 853961eec64b..f314fb5d80f5 100644 --- a/drivers/gpu/drm/xe/xe_dep_scheduler.h +++ b/drivers/gpu/drm/xe/xe_dep_scheduler.h @@ -3,6 +3,9 @@ * Copyright © 2025 Intel Corporation */ +#ifndef _XE_DEP_SCHEDULER_H_ +#define _XE_DEP_SCHEDULER_H_ + #include struct drm_sched_entity; @@ -19,3 +22,5 @@ void xe_dep_scheduler_fini(struct xe_dep_scheduler *dep_scheduler); struct drm_sched_entity * xe_dep_scheduler_entity(struct xe_dep_scheduler *dep_scheduler); + +#endif diff --git a/drivers/gpu/drm/xe/xe_pcode_api.h b/drivers/gpu/drm/xe/xe_pcode_api.h index 85cc7478b787..b619030b9e17 100644 --- a/drivers/gpu/drm/xe/xe_pcode_api.h +++ b/drivers/gpu/drm/xe/xe_pcode_api.h @@ -3,6 +3,9 @@ * Copyright © 2022 Intel Corporation */ +#ifndef _XE_PCODE_API_H_ +#define _XE_PCODE_API_H_ + /* Internal to xe_pcode */ #include "regs/xe_reg_defs.h" @@ -101,3 +104,5 @@ #define BMG_PCIE_CAP XE_REG(0x138340) #define LINK_DOWNGRADE REG_GENMASK(1, 0) #define DOWNGRADE_CAPABLE 2 + +#endif From d45c7454ee32ca91c9e00427ae08ac221765c7b5 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 17 Mar 2026 21:57:18 +0000 Subject: [PATCH 031/120] drm/xe: Add missing _H to include guard suffixes Ten headers use _XE__ or __XE___ as their include guard but omit the _H that the rest of the xe codebase uses. Normalize them to _XE__H_ to follow the dominant convention (_XE__H_) used by ~232 of ~260 xe headers. Files fixed: - xe_migrate.h: _XE_MIGRATE_ -> _XE_MIGRATE_H_ - xe_pt_walk.h: __XE_PT_WALK__ -> _XE_PT_WALK_H_ - xe_reg_sr.h: _XE_REG_SR_ -> _XE_REG_SR_H_ - xe_reg_sr_types.h: _XE_REG_SR_TYPES_ -> _XE_REG_SR_TYPES_H_ - xe_reg_whitelist.h: _XE_REG_WHITELIST_ -> _XE_REG_WHITELIST_H_ - xe_rtp.h: _XE_RTP_ -> _XE_RTP_H_ - xe_rtp_helpers.h: _XE_RTP_HELPERS_ -> _XE_RTP_HELPERS_H_ - xe_rtp_types.h: _XE_RTP_TYPES_ -> _XE_RTP_TYPES_H_ - xe_tuning.h: _XE_TUNING_ -> _XE_TUNING_H_ - xe_wa.h: _XE_WA_ -> _XE_WA_H_ No functional change. Suggested-by: Nitin Gote Assisted-by: GitHub Copilot:claude-opus-4.6 Reviewed-by: Nitin Gote Link: https://patch.msgid.link/20260317215732.2208976-9-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_migrate.h | 4 ++-- drivers/gpu/drm/xe/xe_pt_walk.h | 4 ++-- drivers/gpu/drm/xe/xe_reg_sr.h | 4 ++-- drivers/gpu/drm/xe/xe_reg_sr_types.h | 4 ++-- drivers/gpu/drm/xe/xe_reg_whitelist.h | 4 ++-- drivers/gpu/drm/xe/xe_rtp.h | 4 ++-- drivers/gpu/drm/xe/xe_rtp_helpers.h | 4 ++-- drivers/gpu/drm/xe/xe_rtp_types.h | 4 ++-- drivers/gpu/drm/xe/xe_tuning.h | 4 ++-- drivers/gpu/drm/xe/xe_wa.h | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h index 169279d9d8c2..965c45889c72 100644 --- a/drivers/gpu/drm/xe/xe_migrate.h +++ b/drivers/gpu/drm/xe/xe_migrate.h @@ -3,8 +3,8 @@ * Copyright © 2020 Intel Corporation */ -#ifndef _XE_MIGRATE_ -#define _XE_MIGRATE_ +#ifndef _XE_MIGRATE_H_ +#define _XE_MIGRATE_H_ #include diff --git a/drivers/gpu/drm/xe/xe_pt_walk.h b/drivers/gpu/drm/xe/xe_pt_walk.h index 5c02c244f7de..07c8f409f236 100644 --- a/drivers/gpu/drm/xe/xe_pt_walk.h +++ b/drivers/gpu/drm/xe/xe_pt_walk.h @@ -2,8 +2,8 @@ /* * Copyright © 2022 Intel Corporation */ -#ifndef __XE_PT_WALK__ -#define __XE_PT_WALK__ +#ifndef _XE_PT_WALK_H_ +#define _XE_PT_WALK_H_ #include #include diff --git a/drivers/gpu/drm/xe/xe_reg_sr.h b/drivers/gpu/drm/xe/xe_reg_sr.h index 1ec6e8ecf278..d26cf4713383 100644 --- a/drivers/gpu/drm/xe/xe_reg_sr.h +++ b/drivers/gpu/drm/xe/xe_reg_sr.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _XE_REG_SR_ -#define _XE_REG_SR_ +#ifndef _XE_REG_SR_H_ +#define _XE_REG_SR_H_ /* * Reg save/restore bookkeeping diff --git a/drivers/gpu/drm/xe/xe_reg_sr_types.h b/drivers/gpu/drm/xe/xe_reg_sr_types.h index ebe11f237fa2..0a6695db2967 100644 --- a/drivers/gpu/drm/xe/xe_reg_sr_types.h +++ b/drivers/gpu/drm/xe/xe_reg_sr_types.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _XE_REG_SR_TYPES_ -#define _XE_REG_SR_TYPES_ +#ifndef _XE_REG_SR_TYPES_H_ +#define _XE_REG_SR_TYPES_H_ #include #include diff --git a/drivers/gpu/drm/xe/xe_reg_whitelist.h b/drivers/gpu/drm/xe/xe_reg_whitelist.h index 69b121d377da..3b64b42fe96e 100644 --- a/drivers/gpu/drm/xe/xe_reg_whitelist.h +++ b/drivers/gpu/drm/xe/xe_reg_whitelist.h @@ -3,8 +3,8 @@ * Copyright © 2023 Intel Corporation */ -#ifndef _XE_REG_WHITELIST_ -#define _XE_REG_WHITELIST_ +#ifndef _XE_REG_WHITELIST_H_ +#define _XE_REG_WHITELIST_H_ #include diff --git a/drivers/gpu/drm/xe/xe_rtp.h b/drivers/gpu/drm/xe/xe_rtp.h index 7d6daa7eb1e4..4537ff46a17f 100644 --- a/drivers/gpu/drm/xe/xe_rtp.h +++ b/drivers/gpu/drm/xe/xe_rtp.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _XE_RTP_ -#define _XE_RTP_ +#ifndef _XE_RTP_H_ +#define _XE_RTP_H_ #include #include diff --git a/drivers/gpu/drm/xe/xe_rtp_helpers.h b/drivers/gpu/drm/xe/xe_rtp_helpers.h index 86eee60c04a1..ffa8b2f8828d 100644 --- a/drivers/gpu/drm/xe/xe_rtp_helpers.h +++ b/drivers/gpu/drm/xe/xe_rtp_helpers.h @@ -3,8 +3,8 @@ * Copyright © 2023 Intel Corporation */ -#ifndef _XE_RTP_HELPERS_ -#define _XE_RTP_HELPERS_ +#ifndef _XE_RTP_HELPERS_H_ +#define _XE_RTP_HELPERS_H_ #ifndef _XE_RTP_INCLUDE_PRIVATE_HELPERS #error "This header is supposed to be included by xe_rtp.h only" diff --git a/drivers/gpu/drm/xe/xe_rtp_types.h b/drivers/gpu/drm/xe/xe_rtp_types.h index 166251615be1..0265c16d2762 100644 --- a/drivers/gpu/drm/xe/xe_rtp_types.h +++ b/drivers/gpu/drm/xe/xe_rtp_types.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _XE_RTP_TYPES_ -#define _XE_RTP_TYPES_ +#ifndef _XE_RTP_TYPES_H_ +#define _XE_RTP_TYPES_H_ #include diff --git a/drivers/gpu/drm/xe/xe_tuning.h b/drivers/gpu/drm/xe/xe_tuning.h index c1cc5927fda7..d18e187debf6 100644 --- a/drivers/gpu/drm/xe/xe_tuning.h +++ b/drivers/gpu/drm/xe/xe_tuning.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _XE_TUNING_ -#define _XE_TUNING_ +#ifndef _XE_TUNING_H_ +#define _XE_TUNING_H_ struct drm_printer; struct xe_gt; diff --git a/drivers/gpu/drm/xe/xe_wa.h b/drivers/gpu/drm/xe/xe_wa.h index 8fd6a5af0910..a5f7d33c1b32 100644 --- a/drivers/gpu/drm/xe/xe_wa.h +++ b/drivers/gpu/drm/xe/xe_wa.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _XE_WA_ -#define _XE_WA_ +#ifndef _XE_WA_H_ +#define _XE_WA_H_ #include "xe_assert.h" From b85ff232d25128f7cea47021f419f5aa13101609 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 17 Mar 2026 21:57:19 +0000 Subject: [PATCH 032/120] drm/xe: Add missing trailing underscore to include guards Four headers use _XE__H (no trailing underscore) as their include guard. Normalize them to _XE__H_ to match the dominant convention used across the xe codebase. Files fixed: - xe_guc_capture.h: _XE_GUC_CAPTURE_H -> _XE_GUC_CAPTURE_H_ - xe_guc_capture_types.h: _XE_GUC_CAPTURE_TYPES_H -> _XE_GUC_CAPTURE_TYPES_H_ - xe_guc_fwif.h: _XE_GUC_FWIF_H -> _XE_GUC_FWIF_H_ - xe_uc_fw_abi.h: _XE_UC_FW_ABI_H -> _XE_UC_FW_ABI_H_ No functional change. Suggested-by: Nitin Gote Assisted-by: GitHub Copilot:claude-opus-4.6 Reviewed-by: Nitin Gote Link: https://patch.msgid.link/20260317215732.2208976-10-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_guc_capture.h | 4 ++-- drivers/gpu/drm/xe/xe_guc_capture_types.h | 4 ++-- drivers/gpu/drm/xe/xe_guc_fwif.h | 4 ++-- drivers/gpu/drm/xe/xe_uc_fw_abi.h | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_capture.h b/drivers/gpu/drm/xe/xe_guc_capture.h index 34d6fdc64f56..dca97d52b192 100644 --- a/drivers/gpu/drm/xe/xe_guc_capture.h +++ b/drivers/gpu/drm/xe/xe_guc_capture.h @@ -3,8 +3,8 @@ * Copyright © 2021-2024 Intel Corporation */ -#ifndef _XE_GUC_CAPTURE_H -#define _XE_GUC_CAPTURE_H +#ifndef _XE_GUC_CAPTURE_H_ +#define _XE_GUC_CAPTURE_H_ #include #include "abi/guc_capture_abi.h" diff --git a/drivers/gpu/drm/xe/xe_guc_capture_types.h b/drivers/gpu/drm/xe/xe_guc_capture_types.h index 6cb439115597..af7e21777b06 100644 --- a/drivers/gpu/drm/xe/xe_guc_capture_types.h +++ b/drivers/gpu/drm/xe/xe_guc_capture_types.h @@ -3,8 +3,8 @@ * Copyright © 2021-2024 Intel Corporation */ -#ifndef _XE_GUC_CAPTURE_TYPES_H -#define _XE_GUC_CAPTURE_TYPES_H +#ifndef _XE_GUC_CAPTURE_TYPES_H_ +#define _XE_GUC_CAPTURE_TYPES_H_ #include #include "regs/xe_reg_defs.h" diff --git a/drivers/gpu/drm/xe/xe_guc_fwif.h b/drivers/gpu/drm/xe/xe_guc_fwif.h index b73fae063fac..3fbda4798cff 100644 --- a/drivers/gpu/drm/xe/xe_guc_fwif.h +++ b/drivers/gpu/drm/xe/xe_guc_fwif.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _XE_GUC_FWIF_H -#define _XE_GUC_FWIF_H +#ifndef _XE_GUC_FWIF_H_ +#define _XE_GUC_FWIF_H_ #include diff --git a/drivers/gpu/drm/xe/xe_uc_fw_abi.h b/drivers/gpu/drm/xe/xe_uc_fw_abi.h index 3c9a63d13032..74b888904fdc 100644 --- a/drivers/gpu/drm/xe/xe_uc_fw_abi.h +++ b/drivers/gpu/drm/xe/xe_uc_fw_abi.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _XE_UC_FW_ABI_H -#define _XE_UC_FW_ABI_H +#ifndef _XE_UC_FW_ABI_H_ +#define _XE_UC_FW_ABI_H_ #include #include From 57aad39219d334c4b505aa37dad658005f8a58ec Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 17 Mar 2026 21:57:20 +0000 Subject: [PATCH 033/120] drm/xe: Add missing leading underscore to include guards Two headers use XE__H_ (no leading underscore) as their include guard. Normalize them to _XE__H_ to match the convention used across the xe codebase. Files fixed: - xe_drm_ras.h: XE_DRM_RAS_H_ -> _XE_DRM_RAS_H_ - xe_hw_error.h: XE_HW_ERROR_H_ -> _XE_HW_ERROR_H_ No functional change. Suggested-by: Nitin Gote Assisted-by: GitHub Copilot:claude-opus-4.6 Reviewed-by: Nitin Gote Link: https://patch.msgid.link/20260317215732.2208976-11-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_drm_ras.h | 4 ++-- drivers/gpu/drm/xe/xe_hw_error.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_drm_ras.h b/drivers/gpu/drm/xe/xe_drm_ras.h index 5cc8f0124411..365c70e93e82 100644 --- a/drivers/gpu/drm/xe/xe_drm_ras.h +++ b/drivers/gpu/drm/xe/xe_drm_ras.h @@ -2,8 +2,8 @@ /* * Copyright © 2026 Intel Corporation */ -#ifndef XE_DRM_RAS_H_ -#define XE_DRM_RAS_H_ +#ifndef _XE_DRM_RAS_H_ +#define _XE_DRM_RAS_H_ struct xe_device; diff --git a/drivers/gpu/drm/xe/xe_hw_error.h b/drivers/gpu/drm/xe/xe_hw_error.h index d86e28c5180c..5e3a11424108 100644 --- a/drivers/gpu/drm/xe/xe_hw_error.h +++ b/drivers/gpu/drm/xe/xe_hw_error.h @@ -2,8 +2,8 @@ /* * Copyright © 2025 Intel Corporation */ -#ifndef XE_HW_ERROR_H_ -#define XE_HW_ERROR_H_ +#ifndef _XE_HW_ERROR_H_ +#define _XE_HW_ERROR_H_ #include From 62ef3e610b347b743042c9ab3b942b4be7aab501 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 17 Mar 2026 21:57:21 +0000 Subject: [PATCH 034/120] drm/xe: Normalize double-underscore include guards to single-underscore Six headers use __XE__H__ (double-underscore prefix and suffix) as their include guards. Normalize them to the single-underscore _XE__H_ convention used by the rest of the xe codebase. Files fixed: - xe_eu_stall.h: __XE_EU_STALL_H__ -> _XE_EU_STALL_H_ - xe_nvm.h: __XE_NVM_H__ -> _XE_NVM_H_ - xe_pxp.h: __XE_PXP_H__ -> _XE_PXP_H_ - xe_pxp_debugfs.h: __XE_PXP_DEBUGFS_H__ -> _XE_PXP_DEBUGFS_H_ - xe_pxp_submit.h: __XE_PXP_SUBMIT_H__ -> _XE_PXP_SUBMIT_H_ - xe_pxp_types.h: __XE_PXP_TYPES_H__ -> _XE_PXP_TYPES_H_ No functional change. Suggested-by: Nitin Gote Assisted-by: GitHub Copilot:claude-opus-4.6 Reviewed-by: Nitin Gote Link: https://patch.msgid.link/20260317215732.2208976-12-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_eu_stall.h | 4 ++-- drivers/gpu/drm/xe/xe_nvm.h | 4 ++-- drivers/gpu/drm/xe/xe_pxp.h | 6 +++--- drivers/gpu/drm/xe/xe_pxp_debugfs.h | 6 +++--- drivers/gpu/drm/xe/xe_pxp_submit.h | 6 +++--- drivers/gpu/drm/xe/xe_pxp_types.h | 6 +++--- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_eu_stall.h b/drivers/gpu/drm/xe/xe_eu_stall.h index d1c76e503799..842bef9f6872 100644 --- a/drivers/gpu/drm/xe/xe_eu_stall.h +++ b/drivers/gpu/drm/xe/xe_eu_stall.h @@ -3,8 +3,8 @@ * Copyright © 2025 Intel Corporation */ -#ifndef __XE_EU_STALL_H__ -#define __XE_EU_STALL_H__ +#ifndef _XE_EU_STALL_H_ +#define _XE_EU_STALL_H_ #include "xe_gt_types.h" #include "xe_sriov.h" diff --git a/drivers/gpu/drm/xe/xe_nvm.h b/drivers/gpu/drm/xe/xe_nvm.h index fd3467ad35a4..b14722103f81 100644 --- a/drivers/gpu/drm/xe/xe_nvm.h +++ b/drivers/gpu/drm/xe/xe_nvm.h @@ -3,8 +3,8 @@ * Copyright(c) 2019-2025 Intel Corporation. All rights reserved. */ -#ifndef __XE_NVM_H__ -#define __XE_NVM_H__ +#ifndef _XE_NVM_H_ +#define _XE_NVM_H_ struct xe_device; diff --git a/drivers/gpu/drm/xe/xe_pxp.h b/drivers/gpu/drm/xe/xe_pxp.h index 71a23280b900..4fb6e0afffd2 100644 --- a/drivers/gpu/drm/xe/xe_pxp.h +++ b/drivers/gpu/drm/xe/xe_pxp.h @@ -3,8 +3,8 @@ * Copyright(c) 2024, Intel Corporation. All rights reserved. */ -#ifndef __XE_PXP_H__ -#define __XE_PXP_H__ +#ifndef _XE_PXP_H_ +#define _XE_PXP_H_ #include @@ -32,4 +32,4 @@ int xe_pxp_key_assign(struct xe_pxp *pxp, struct xe_bo *bo); int xe_pxp_bo_key_check(struct xe_pxp *pxp, struct xe_bo *bo); int xe_pxp_obj_key_check(struct drm_gem_object *obj); -#endif /* __XE_PXP_H__ */ +#endif /* _XE_PXP_H_ */ diff --git a/drivers/gpu/drm/xe/xe_pxp_debugfs.h b/drivers/gpu/drm/xe/xe_pxp_debugfs.h index 988466aad50b..2997de0c90b2 100644 --- a/drivers/gpu/drm/xe/xe_pxp_debugfs.h +++ b/drivers/gpu/drm/xe/xe_pxp_debugfs.h @@ -3,11 +3,11 @@ * Copyright © 2024 Intel Corporation */ -#ifndef __XE_PXP_DEBUGFS_H__ -#define __XE_PXP_DEBUGFS_H__ +#ifndef _XE_PXP_DEBUGFS_H_ +#define _XE_PXP_DEBUGFS_H_ struct xe_pxp; void xe_pxp_debugfs_register(struct xe_pxp *pxp); -#endif /* __XE_PXP_DEBUGFS_H__ */ +#endif /* _XE_PXP_DEBUGFS_H_ */ diff --git a/drivers/gpu/drm/xe/xe_pxp_submit.h b/drivers/gpu/drm/xe/xe_pxp_submit.h index c9efda02f4b0..dbbbe6b92bb2 100644 --- a/drivers/gpu/drm/xe/xe_pxp_submit.h +++ b/drivers/gpu/drm/xe/xe_pxp_submit.h @@ -3,8 +3,8 @@ * Copyright(c) 2024, Intel Corporation. All rights reserved. */ -#ifndef __XE_PXP_SUBMIT_H__ -#define __XE_PXP_SUBMIT_H__ +#ifndef _XE_PXP_SUBMIT_H_ +#define _XE_PXP_SUBMIT_H_ #include @@ -19,4 +19,4 @@ int xe_pxp_submit_session_termination(struct xe_pxp *pxp, u32 id); int xe_pxp_submit_session_invalidation(struct xe_pxp_gsc_client_resources *gsc_res, u32 id); -#endif /* __XE_PXP_SUBMIT_H__ */ +#endif /* _XE_PXP_SUBMIT_H_ */ diff --git a/drivers/gpu/drm/xe/xe_pxp_types.h b/drivers/gpu/drm/xe/xe_pxp_types.h index 53e9d48d10fb..ec86306e16f4 100644 --- a/drivers/gpu/drm/xe/xe_pxp_types.h +++ b/drivers/gpu/drm/xe/xe_pxp_types.h @@ -3,8 +3,8 @@ * Copyright(c) 2024, Intel Corporation. All rights reserved. */ -#ifndef __XE_PXP_TYPES_H__ -#define __XE_PXP_TYPES_H__ +#ifndef _XE_PXP_TYPES_H_ +#define _XE_PXP_TYPES_H_ #include #include @@ -132,4 +132,4 @@ struct xe_pxp { u32 last_suspend_key_instance; }; -#endif /* __XE_PXP_TYPES_H__ */ +#endif /* _XE_PXP_TYPES_H_ */ From 764c0e2abf3b7c8611a3695af26febfffe236c68 Mon Sep 17 00:00:00 2001 From: Tejas Upadhyay Date: Tue, 7 Apr 2026 11:21:08 +0530 Subject: [PATCH 035/120] Use xe_map_resource_to_region helper instead of direct access Renaming: The helper function res_to_mem_region is now xe_map_resource_to_region. Abstraction: The patch removes instances where block->private was accessed directly to obtain VRAM region data allowing VRAM manager to own block->private for future use cases. V2(MattB): Add more detail about patch also adjust variable placement Reviewed-by: Matthew Brost Link: https://patch.msgid.link/20260407055107.2782450-2-tejas.upadhyay@intel.com Signed-off-by: Tejas Upadhyay --- drivers/gpu/drm/xe/xe_bo.c | 21 ++++----------------- drivers/gpu/drm/xe/xe_svm.c | 10 ++-------- drivers/gpu/drm/xe/xe_vram.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/xe/xe_vram.h | 2 ++ 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index a7c2dc7f224c..daac53168dba 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -173,19 +173,6 @@ mem_type_to_migrate(struct xe_device *xe, u32 mem_type) return tile->migrate; } -static struct xe_vram_region *res_to_mem_region(struct ttm_resource *res) -{ - struct xe_device *xe = ttm_to_xe_device(res->bo->bdev); - struct ttm_resource_manager *mgr; - struct xe_ttm_vram_mgr *vram_mgr; - - xe_assert(xe, resource_is_vram(res)); - mgr = ttm_manager_type(&xe->ttm, res->mem_type); - vram_mgr = to_xe_ttm_vram_mgr(mgr); - - return container_of(vram_mgr, struct xe_vram_region, ttm); -} - static void try_add_system(struct xe_device *xe, struct xe_bo *bo, u32 bo_flags, u32 *c) { @@ -635,7 +622,7 @@ static int xe_ttm_io_mem_reserve(struct ttm_device *bdev, return 0; case XE_PL_VRAM0: case XE_PL_VRAM1: { - struct xe_vram_region *vram = res_to_mem_region(mem); + struct xe_vram_region *vram = xe_map_resource_to_region(mem); if (!xe_ttm_resource_visible(mem)) return -EINVAL; @@ -1642,7 +1629,7 @@ static unsigned long xe_ttm_io_mem_pfn(struct ttm_buffer_object *ttm_bo, if (ttm_bo->resource->mem_type == XE_PL_STOLEN) return xe_ttm_stolen_io_offset(bo, page_offset << PAGE_SHIFT) >> PAGE_SHIFT; - vram = res_to_mem_region(ttm_bo->resource); + vram = xe_map_resource_to_region(ttm_bo->resource); xe_res_first(ttm_bo->resource, (u64)page_offset << PAGE_SHIFT, 0, &cursor); return (vram->io_start + cursor.start) >> PAGE_SHIFT; } @@ -1782,7 +1769,7 @@ static int xe_ttm_access_memory(struct ttm_buffer_object *ttm_bo, goto out; } - vram = res_to_mem_region(ttm_bo->resource); + vram = xe_map_resource_to_region(ttm_bo->resource); xe_res_first(ttm_bo->resource, offset & PAGE_MASK, xe_bo_size(bo) - (offset & PAGE_MASK), &cursor); @@ -2923,7 +2910,7 @@ uint64_t vram_region_gpu_offset(struct ttm_resource *res) case XE_PL_SYSTEM: return 0; default: - return res_to_mem_region(res)->dpa_base; + return xe_map_resource_to_region(res)->dpa_base; } return 0; } diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 5933b2b6392b..ba67355f64cb 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -786,12 +786,12 @@ static int xe_svm_populate_devmem_pfn(struct drm_pagemap_devmem *devmem_allocati struct xe_bo *bo = to_xe_bo(devmem_allocation); struct ttm_resource *res = bo->ttm.resource; struct list_head *blocks = &to_xe_ttm_vram_mgr_resource(res)->blocks; + struct xe_vram_region *vr = xe_map_resource_to_region(res); + struct gpu_buddy *buddy = vram_to_buddy(vr); struct gpu_buddy_block *block; int j = 0; list_for_each_entry(block, blocks, link) { - struct xe_vram_region *vr = block->private; - struct gpu_buddy *buddy = vram_to_buddy(vr); u64 block_pfn = block_offset_to_pfn(devmem_allocation->dpagemap, gpu_buddy_block_offset(block)); int i; @@ -1061,9 +1061,7 @@ static int xe_drm_pagemap_populate_mm(struct drm_pagemap *dpagemap, struct dma_fence *pre_migrate_fence = NULL; struct xe_device *xe = vr->xe; struct device *dev = xe->drm.dev; - struct gpu_buddy_block *block; struct xe_validation_ctx vctx; - struct list_head *blocks; struct drm_exec exec; struct xe_bo *bo; int err = 0, idx; @@ -1100,10 +1098,6 @@ static int xe_drm_pagemap_populate_mm(struct drm_pagemap *dpagemap, &dpagemap_devmem_ops, dpagemap, end - start, pre_migrate_fence); - blocks = &to_xe_ttm_vram_mgr_resource(bo->ttm.resource)->blocks; - list_for_each_entry(block, blocks, link) - block->private = vr; - xe_bo_get(bo); /* Ensure the device has a pm ref while there are device pages active. */ diff --git a/drivers/gpu/drm/xe/xe_vram.c b/drivers/gpu/drm/xe/xe_vram.c index 0538dcb8b18c..23eb7edbdd57 100644 --- a/drivers/gpu/drm/xe/xe_vram.c +++ b/drivers/gpu/drm/xe/xe_vram.c @@ -13,6 +13,7 @@ #include "regs/xe_gt_regs.h" #include "regs/xe_regs.h" #include "xe_assert.h" +#include "xe_bo.h" #include "xe_device.h" #include "xe_force_wake.h" #include "xe_gt_mcr.h" @@ -249,6 +250,27 @@ static int vram_region_init(struct xe_device *xe, struct xe_vram_region *vram, return 0; } +/** + * xe_map_resource_to_region - Map ttm resource to vram memory region + * @res: The ttm resource + * + * Get vram memory region using vram memory manager managing this resource + * + * Returns: pointer to xe_vram_region + */ +struct xe_vram_region *xe_map_resource_to_region(struct ttm_resource *res) +{ + struct xe_device *xe = ttm_to_xe_device(res->bo->bdev); + struct ttm_resource_manager *mgr; + struct xe_ttm_vram_mgr *vram_mgr; + + xe_assert(xe, mem_type_is_vram(res->mem_type)); + mgr = ttm_manager_type(&xe->ttm, res->mem_type); + vram_mgr = to_xe_ttm_vram_mgr(mgr); + + return container_of(vram_mgr, struct xe_vram_region, ttm); +} + /** * xe_vram_probe() - Probe VRAM configuration * @xe: the &xe_device diff --git a/drivers/gpu/drm/xe/xe_vram.h b/drivers/gpu/drm/xe/xe_vram.h index 72860f714fc6..dd1c8bf17922 100644 --- a/drivers/gpu/drm/xe/xe_vram.h +++ b/drivers/gpu/drm/xe/xe_vram.h @@ -10,7 +10,9 @@ struct xe_device; struct xe_vram_region; +struct ttm_resource; +struct xe_vram_region *xe_map_resource_to_region(struct ttm_resource *res); int xe_vram_probe(struct xe_device *xe); struct xe_vram_region *xe_vram_region_alloc(struct xe_device *xe, u8 id, u32 placement); From 2b923203b0f0ad1f1f56b956fd0b23dc4fcc73dd Mon Sep 17 00:00:00 2001 From: Jonathan Cavitt Date: Mon, 16 Mar 2026 16:20:04 +0000 Subject: [PATCH 036/120] drm/xe/tlb: Init range tilemask err to zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initialize err = 0 in xe_tlb_inval_range_tilemask_submit to prevent a possible uninitialized value return in the case where the tile_mask somehow doesn't match any available tile ids. This targets a static analysis issue. Signed-off-by: Jonathan Cavitt Reviewed-by: Thomas Hellström Link: https://patch.msgid.link/20260316162003.64643-2-jonathan.cavitt@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_tlb_inval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_tlb_inval.c b/drivers/gpu/drm/xe/xe_tlb_inval.c index 10dcd4abb00f..bbd21d393062 100644 --- a/drivers/gpu/drm/xe/xe_tlb_inval.c +++ b/drivers/gpu/drm/xe/xe_tlb_inval.c @@ -529,7 +529,7 @@ int xe_tlb_inval_range_tilemask_submit(struct xe_device *xe, u32 asid, struct xe_tile *tile; u32 fence_id = 0; u8 id; - int err; + int err = 0; batch->num_fences = 0; if (!tile_mask) From 3233db7682e759d101028285386ee7a11183fa2a Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 7 Apr 2026 03:00:41 +0000 Subject: [PATCH 037/120] drm/xe/uapi: Fix typos and spelling errors in xe_drm.h documentation Fix the following typos and spelling errors in doc comments: - creaed -> created (drm_xe_query_config) - mmaping -> mmapping (drm_xe_gem_create) - 0xdeadbeaf -> 0xdeadbeef (drm_xe_gem_mmap_offset) - x2 and xe3 platform -> Xe2 and Xe3 platforms - flat -> flag (drm_xe_wait_user_fence) - MONOTONIC_CLOCK -> CLOCK_MONOTONIC (correct POSIX name) - neverending -> never ending (drm_xe_wait_user_fence) Assisted-by: GitHub Copilot:claude-opus-4.6 Reviewed-by: Xin Wang Link: https://patch.msgid.link/20260407030046.3394004-2-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- include/uapi/drm/xe_drm.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index ae2fda23ce7c..f17355684083 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -410,7 +410,7 @@ struct drm_xe_query_mem_regions { * device supports the userspace hint %DRM_XE_GEM_CREATE_FLAG_NO_COMPRESSION. * This is exposed only on Xe2+. * - %DRM_XE_QUERY_CONFIG_FLAG_HAS_DISABLE_STATE_CACHE_PERF_FIX - Flag is set - * if a queue can be creaed with + * if a queue can be created with * %DRM_XE_EXEC_QUEUE_SET_DISABLE_STATE_CACHE_PERF_FIX * - %DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT - Minimal memory alignment * required by this device, typically SZ_4K or SZ_64K @@ -888,7 +888,7 @@ struct drm_xe_gem_create { #define DRM_XE_GEM_CPU_CACHING_WC 2 /** * @cpu_caching: The CPU caching mode to select for this object. If - * mmaping the object the mode selected here will also be used. The + * mmapping the object the mode selected here will also be used. The * exception is when mapping system memory (including data evicted * to system) on discrete GPUs. The caching mode selected will * then be overridden to DRM_XE_GEM_CPU_CACHING_WB, and coherency @@ -931,7 +931,7 @@ struct drm_xe_gem_create { * * err = ioctl(fd, DRM_IOCTL_XE_GEM_MMAP_OFFSET, &mmo); * map = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, mmo.offset); - * map[i] = 0xdeadbeaf; // issue barrier + * map[i] = 0xdeadbeef; // issue barrier */ struct drm_xe_gem_mmap_offset { /** @extensions: Pointer to the first extension struct, if any */ @@ -958,8 +958,8 @@ struct drm_xe_gem_mmap_offset { * - %DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE - Map the whole virtual address * space of the VM to scratch page. A vm_bind would overwrite the scratch * page mapping. This flag is mutually exclusive with the - * %DRM_XE_VM_CREATE_FLAG_FAULT_MODE flag, with an exception of on x2 and - * xe3 platform. + * %DRM_XE_VM_CREATE_FLAG_FAULT_MODE flag, with an exception on Xe2 and + * Xe3 platforms. * - %DRM_XE_VM_CREATE_FLAG_LR_MODE - An LR, or Long Running VM accepts * exec submissions to its exec_queues that don't have an upper time * limit on the job execution time. But exec submissions to these @@ -1695,9 +1695,9 @@ struct drm_xe_wait_user_fence { * Without DRM_XE_UFENCE_WAIT_FLAG_ABSTIME flag set (relative timeout) * it contains timeout expressed in nanoseconds to wait (fence will * expire at now() + timeout). - * When DRM_XE_UFENCE_WAIT_FLAG_ABSTIME flat is set (absolute timeout) wait - * will end at timeout (uses system MONOTONIC_CLOCK). - * Passing negative timeout leads to neverending wait. + * When DRM_XE_UFENCE_WAIT_FLAG_ABSTIME flag is set (absolute timeout) wait + * will end at timeout (uses system CLOCK_MONOTONIC). + * Passing negative timeout leads to never ending wait. * * On relative timeout this value is updated with timeout left * (for restarting the call in case of signal delivery). From 65d53c13d43b8b5690c326807c1535b1d19138e8 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 7 Apr 2026 03:00:42 +0000 Subject: [PATCH 038/120] drm/xe/uapi: Fix grammar errors in xe_drm.h documentation Fix various grammar issues in doc comments: - flag are only valid -> flag is only valid - should only ever used -> should only ever be used - if isn't already -> if it isn't already - Type of the this -> Type of this - When sync passed in -> When sync is passed in - the users responsibility -> the user's responsibility - must qword aligned -> must be qword aligned - for a observation -> for an observation - a memory ranges -> memory ranges - for each memory ranges -> for each memory range. - Second ioctl call -> second ioctl call Assisted-by: GitHub Copilot:claude-opus-4.6 Reviewed-by: Xin Wang Link: https://patch.msgid.link/20260407030046.3394004-3-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- include/uapi/drm/xe_drm.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index f17355684083..1d3406416d8c 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -1045,7 +1045,7 @@ struct drm_xe_vm_destroy { * set, no mappings are created rather the range is reserved for CPU address * mirroring which will be populated on GPU page faults or prefetches. Only * valid on VMs with DRM_XE_VM_CREATE_FLAG_FAULT_MODE set. The CPU address - * mirror flag are only valid for DRM_XE_VM_BIND_OP_MAP operations, the BO + * mirror flag is only valid for DRM_XE_VM_BIND_OP_MAP operations, the BO * handle MBZ, and the BO offset MBZ. * - %DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET - Can be used in combination with * %DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR to reset madvises when the underlying @@ -1109,7 +1109,7 @@ struct drm_xe_vm_bind_op { * ppGTT WT -> COH_NONE * ppGTT WB -> COH_AT_LEAST_1WAY * - * In practice UC/WC/WT should only ever used for scanout surfaces on + * In practice UC/WC/WT should only ever be used for scanout surfaces on * such platforms (or perhaps in general for dma-buf if shared with * another device) since it is only the display engine that is actually * incoherent. Everything else should typically use WB given that we @@ -1366,7 +1366,7 @@ struct drm_xe_vm_get_property { * drm_xe_pxp_session_type. %DRM_XE_PXP_TYPE_NONE is the default behavior, so * there is no need to explicitly set that. When a queue of type * %DRM_XE_PXP_TYPE_HWDRM is created, the PXP default HWDRM session - * (%XE_PXP_HWDRM_DEFAULT_SESSION) will be started, if isn't already running. + * (%XE_PXP_HWDRM_DEFAULT_SESSION) will be started, if it isn't already running. * The user is expected to query the PXP status via the query ioctl (see * %DRM_XE_DEVICE_QUERY_PXP_STATUS) and to wait for PXP to be ready before * attempting to create a queue with this property. When a queue is created @@ -1546,7 +1546,7 @@ struct drm_xe_sync { #define DRM_XE_SYNC_TYPE_SYNCOBJ 0x0 #define DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ 0x1 #define DRM_XE_SYNC_TYPE_USER_FENCE 0x2 - /** @type: Type of the this sync object */ + /** @type: Type of this sync object */ __u32 type; #define DRM_XE_SYNC_FLAG_SIGNAL (1 << 0) @@ -1559,9 +1559,9 @@ struct drm_xe_sync { /** * @addr: Address of user fence. When sync is passed in via exec - * IOCTL this is a GPU address in the VM. When sync passed in via + * IOCTL this is a GPU address in the VM. When sync is passed in via * VM bind IOCTL this is a user pointer. In either case, it is - * the users responsibility that this address is present and + * the user's responsibility that this address is present and * mapped when the user fence is signalled. Must be qword * aligned. */ @@ -1664,7 +1664,7 @@ struct drm_xe_wait_user_fence { __u64 extensions; /** - * @addr: user pointer address to wait on, must qword aligned + * @addr: user pointer address to wait on, must be qword aligned */ __u64 addr; @@ -1769,7 +1769,7 @@ enum drm_xe_observation_ioctls { /** @DRM_XE_OBSERVATION_IOCTL_ENABLE: Enable data capture for an observation stream */ DRM_XE_OBSERVATION_IOCTL_ENABLE = _IO('i', 0x0), - /** @DRM_XE_OBSERVATION_IOCTL_DISABLE: Disable data capture for a observation stream */ + /** @DRM_XE_OBSERVATION_IOCTL_DISABLE: Disable data capture for an observation stream */ DRM_XE_OBSERVATION_IOCTL_DISABLE = _IO('i', 0x1), /** @DRM_XE_OBSERVATION_IOCTL_CONFIG: Change observation stream configuration */ @@ -2373,12 +2373,12 @@ struct drm_xe_madvise { * * This structure is provided by userspace and filled by KMD in response to the * DRM_IOCTL_XE_VM_QUERY_MEM_RANGES_ATTRS ioctl. It describes memory attributes of - * a memory ranges within a user specified address range in a VM. + * memory ranges within a user specified address range in a VM. * * The structure includes information such as atomic access policy, * page attribute table (PAT) index, and preferred memory location. * Userspace allocates an array of these structures and passes a pointer to the - * ioctl to retrieve attributes for each memory ranges + * ioctl to retrieve attributes for each memory range. * * @extensions: Pointer to the first extension struct, if any * @start: Start address of the memory range @@ -2443,7 +2443,7 @@ struct drm_xe_mem_range_attr { * If second call fails with -ENOSPC, it means memory ranges changed between * first call and now, retry IOCTL again with @num_mem_ranges = 0, * @sizeof_mem_ranges_attr = 0 and @vector_of_vma_mem_attr = NULL followed by - * Second ioctl call. + * second ioctl call. * * Example: * From ea842c235828152258fc5197212e896bc59d7b83 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 7 Apr 2026 03:00:43 +0000 Subject: [PATCH 039/120] drm/xe/uapi: Fix wrong names and references in xe_drm.h Fix incorrect field names, struct names, ioctl names, and descriptions in doc comments: - probed_size -> @cpu_visible_size (correct field name) - @flags description was copy of @placement -> fix to reference DRM_XE_GEM_CREATE_FLAG_* - %XE_PXP_HWDRM_DEFAULT_SESSION -> %DRM_XE_PXP_HWDRM_DEFAULT_SESSION (missing DRM_ prefix) - Remove undefined %DRM_XE_UFENCE_WAIT_FLAG_SOFT_OP - &DRM_XE_OBSERVATION -> &DRM_IOCTL_XE_OBSERVATION - id's/struct's -> IDs/structs (fix incorrect possessive forms) - drm_xe_query_oa_units -> drm_xe_oa_unit - DRM_IOCTL_XE_VM_QUERY_MEM_RANGES_ATTRS -> DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS - DRM_IOCTL_XE_VM_QUERY_MEM_ATTRIBUTES -> DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS - @sizeof_mem_ranges_attr -> @sizeof_mem_range_attr - @vector_of_vma_mem_attr -> @vector_of_mem_attr v3: id -> ID. (Xin) split cross-reference fix to seperate patch. Assisted-by: GitHub Copilot:claude-opus-4.6 Cc: Xin Wang Reviewed-by: Xin Wang Link: https://patch.msgid.link/20260407030046.3394004-4-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- include/uapi/drm/xe_drm.h | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index 1d3406416d8c..ad8e3b69a3d7 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -349,7 +349,7 @@ struct drm_xe_mem_region { * is smaller than @total_size then this is referred to as a * small BAR system. * - * On systems without small BAR (full BAR), the probed_size will + * On systems without small BAR (full BAR), the @cpu_visible_size will * always equal the @total_size, since all of it will be CPU * accessible. * @@ -862,8 +862,7 @@ struct drm_xe_gem_create { #define DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM (1 << 2) #define DRM_XE_GEM_CREATE_FLAG_NO_COMPRESSION (1 << 3) /** - * @flags: Flags, currently a mask of memory instances of where BO can - * be placed + * @flags: Flags for the GEM object, see DRM_XE_GEM_CREATE_FLAG_* */ __u32 flags; @@ -1366,7 +1365,7 @@ struct drm_xe_vm_get_property { * drm_xe_pxp_session_type. %DRM_XE_PXP_TYPE_NONE is the default behavior, so * there is no need to explicitly set that. When a queue of type * %DRM_XE_PXP_TYPE_HWDRM is created, the PXP default HWDRM session - * (%XE_PXP_HWDRM_DEFAULT_SESSION) will be started, if it isn't already running. + * (%DRM_XE_PXP_HWDRM_DEFAULT_SESSION) will be started, if it isn't already running. * The user is expected to query the PXP status via the query ioctl (see * %DRM_XE_DEVICE_QUERY_PXP_STATUS) and to wait for PXP to be ready before * attempting to create a queue with this property. When a queue is created @@ -1651,7 +1650,6 @@ struct drm_xe_exec { * * and the @flags can be: * - %DRM_XE_UFENCE_WAIT_FLAG_ABSTIME - * - %DRM_XE_UFENCE_WAIT_FLAG_SOFT_OP * * The @mask values can be for example: * - 0xffu for u8 @@ -1741,7 +1739,7 @@ enum drm_xe_observation_op { }; /** - * struct drm_xe_observation_param - Input of &DRM_XE_OBSERVATION + * struct drm_xe_observation_param - Input of &DRM_IOCTL_XE_OBSERVATION * * The observation layer enables multiplexing observation streams of * multiple types. The actual params for a particular stream operation are @@ -1902,10 +1900,10 @@ enum drm_xe_oa_format_type { }; /** - * enum drm_xe_oa_property_id - OA stream property id's + * enum drm_xe_oa_property_id - OA stream property IDs * * Stream params are specified as a chain of @drm_xe_ext_set_property - * struct's, with @property values from enum @drm_xe_oa_property_id and + * structs, with @property values from enum @drm_xe_oa_property_id and * @drm_xe_user_extension base.name set to @DRM_XE_OA_EXTENSION_SET_PROPERTY. * @param field in struct @drm_xe_observation_param points to the first * @drm_xe_ext_set_property struct. @@ -1919,7 +1917,7 @@ enum drm_xe_oa_property_id { /** * @DRM_XE_OA_PROPERTY_OA_UNIT_ID: ID of the OA unit on which to open * the OA stream, see @oa_unit_id in 'struct - * drm_xe_query_oa_units'. Defaults to 0 if not provided. + * drm_xe_oa_unit'. Defaults to 0 if not provided. */ DRM_XE_OA_PROPERTY_OA_UNIT_ID = 1, @@ -2369,10 +2367,10 @@ struct drm_xe_madvise { }; /** - * struct drm_xe_mem_range_attr - Output of &DRM_IOCTL_XE_VM_QUERY_MEM_RANGES_ATTRS + * struct drm_xe_mem_range_attr - Output of &DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS * * This structure is provided by userspace and filled by KMD in response to the - * DRM_IOCTL_XE_VM_QUERY_MEM_RANGES_ATTRS ioctl. It describes memory attributes of + * DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS ioctl. It describes memory attributes of * memory ranges within a user specified address range in a VM. * * The structure includes information such as atomic access policy, @@ -2427,7 +2425,7 @@ struct drm_xe_mem_range_attr { }; /** - * struct drm_xe_vm_query_mem_range_attr - Input of &DRM_IOCTL_XE_VM_QUERY_MEM_ATTRIBUTES + * struct drm_xe_vm_query_mem_range_attr - Input of &DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS * * This structure is used to query memory attributes of memory regions * within a user specified address range in a VM. It provides detailed @@ -2435,14 +2433,14 @@ struct drm_xe_mem_range_attr { * page attribute table (PAT) index, and preferred memory location. * * Userspace first calls the ioctl with @num_mem_ranges = 0, - * @sizeof_mem_ranges_attr = 0 and @vector_of_vma_mem_attr = NULL to retrieve + * @sizeof_mem_range_attr = 0 and @vector_of_mem_attr = NULL to retrieve * the number of memory regions and size of each memory range attribute. * Then, it allocates a buffer of that size and calls the ioctl again to fill * the buffer with memory range attributes. * * If second call fails with -ENOSPC, it means memory ranges changed between * first call and now, retry IOCTL again with @num_mem_ranges = 0, - * @sizeof_mem_ranges_attr = 0 and @vector_of_vma_mem_attr = NULL followed by + * @sizeof_mem_range_attr = 0 and @vector_of_mem_attr = NULL followed by * second ioctl call. * * Example: From 4bd87e7c4d467ce1f9e3b56abebeffc2ba45a2fb Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 7 Apr 2026 03:00:44 +0000 Subject: [PATCH 040/120] drm/xe/uapi: Fix kernel-doc cross-reference syntax in xe_drm.h Fix incorrect kernel-doc cross-reference markup syntax throughout xe_drm.h: - @struct_name -> &struct name for cross-references to other structs (19 occurrences) - struct @name -> &struct name where struct keyword was mixed with @ syntax (8 occurrences) - enum @name -> &enum name for cross-references to other enums (5 occurrences) - &CONSTANT / @CONSTANT -> %CONSTANT for defines and enum values (15 occurrences) - @field references to members of other structs -> plain text, since @ only applies to the current struct's members (9 occurrences) Per kernel-doc conventions (Documentation/doc-guide/kernel-doc.rst): - '&struct name' creates hyperlinks to struct definitions - '&enum name' creates hyperlinks to enum definitions - '%NAME' references constants and defines - '@name' is only for parameters/members of the current context Assisted-by: GitHub Copilot:claude-opus-4.6 Suggested-by: Xin Wang Reviewed-by: Xin Wang Link: https://patch.msgid.link/20260407030046.3394004-5-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- include/uapi/drm/xe_drm.h | 106 +++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index ad8e3b69a3d7..8751ad7b845f 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -229,9 +229,9 @@ struct drm_xe_ext_set_property { /** * struct drm_xe_engine_class_instance - instance of an engine class * - * It is returned as part of the @drm_xe_engine, but it also is used as - * the input of engine selection for both @drm_xe_exec_queue_create and - * @drm_xe_query_engine_cycles + * It is returned as part of the &struct drm_xe_engine, but it also is used as + * the input of engine selection for both &struct drm_xe_exec_queue_create and + * &struct drm_xe_query_engine_cycles * * The @engine_class can be: * - %DRM_XE_ENGINE_CLASS_RENDER @@ -264,7 +264,7 @@ struct drm_xe_engine_class_instance { * struct drm_xe_engine - describe hardware engine */ struct drm_xe_engine { - /** @instance: The @drm_xe_engine_class_instance */ + /** @instance: The &struct drm_xe_engine_class_instance */ struct drm_xe_engine_class_instance instance; /** @reserved: Reserved */ @@ -274,9 +274,9 @@ struct drm_xe_engine { /** * struct drm_xe_query_engines - describe engines * - * If a query is made with a struct @drm_xe_device_query where .query + * If a query is made with a &struct drm_xe_device_query where .query * is equal to %DRM_XE_DEVICE_QUERY_ENGINES, then the reply uses an array of - * struct @drm_xe_query_engines in .data. + * &struct drm_xe_query_engines in .data. */ struct drm_xe_query_engines { /** @num_engines: number of engines returned in @engines */ @@ -825,7 +825,7 @@ struct drm_xe_device_query { * * This ioctl supports setting the following properties via the * %DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY extension, which uses the - * generic @drm_xe_ext_set_property struct: + * generic &struct drm_xe_ext_set_property: * * - %DRM_XE_GEM_CREATE_SET_PROPERTY_PXP_TYPE - set the type of PXP session * this object will be used with. Valid values are listed in enum @@ -1198,10 +1198,10 @@ struct drm_xe_vm_bind_op { /** * struct drm_xe_vm_bind - Input of &DRM_IOCTL_XE_VM_BIND * - * Below is an example of a minimal use of @drm_xe_vm_bind to + * Below is an example of a minimal use of &struct drm_xe_vm_bind to * asynchronously bind the buffer `data` at address `BIND_ADDRESS` to * illustrate `userptr`. It can be synchronized by using the example - * provided for @drm_xe_sync. + * provided for &struct drm_xe_sync. * * .. code-block:: C * @@ -1354,7 +1354,7 @@ struct drm_xe_vm_get_property { * * This ioctl supports setting the following properties via the * %DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY extension, which uses the - * generic @drm_xe_ext_set_property struct: + * generic &struct drm_xe_ext_set_property: * * - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY - set the queue priority. * CAP_SYS_NICE is required to set a value above normal. @@ -1389,9 +1389,9 @@ struct drm_xe_vm_get_property { * enable render color cache keying on BTP+BTI instead of just BTI * (only valid for render queues). * - * The example below shows how to use @drm_xe_exec_queue_create to create + * The example below shows how to use &struct drm_xe_exec_queue_create to create * a simple exec_queue (no parallel submission) of class - * &DRM_XE_ENGINE_CLASS_RENDER. + * %DRM_XE_ENGINE_CLASS_RENDER. * * .. code-block:: C * @@ -1514,7 +1514,7 @@ struct drm_xe_exec_queue_get_property { * and the @flags can be: * - %DRM_XE_SYNC_FLAG_SIGNAL * - * A minimal use of @drm_xe_sync looks like this: + * A minimal use of &struct drm_xe_sync looks like this: * * .. code-block:: C * @@ -1580,10 +1580,10 @@ struct drm_xe_sync { /** * struct drm_xe_exec - Input of &DRM_IOCTL_XE_EXEC * - * This is an example to use @drm_xe_exec for execution of the object - * at BIND_ADDRESS (see example in @drm_xe_vm_bind) by an exec_queue - * (see example in @drm_xe_exec_queue_create). It can be synchronized - * by using the example provided for @drm_xe_sync. + * This is an example to use &struct drm_xe_exec for execution of the object + * at BIND_ADDRESS (see example in &struct drm_xe_vm_bind) by an exec_queue + * (see example in &struct drm_xe_exec_queue_create). It can be synchronized + * by using the example provided for &struct drm_xe_sync. * * .. code-block:: C * @@ -1749,9 +1749,9 @@ enum drm_xe_observation_op { struct drm_xe_observation_param { /** @extensions: Pointer to the first extension struct, if any */ __u64 extensions; - /** @observation_type: observation stream type, of enum @drm_xe_observation_type */ + /** @observation_type: observation stream type, of &enum drm_xe_observation_type */ __u64 observation_type; - /** @observation_op: observation stream op, of enum @drm_xe_observation_op */ + /** @observation_op: observation stream op, of &enum drm_xe_observation_op */ __u64 observation_op; /** @param: Pointer to actual stream params */ __u64 param; @@ -1810,7 +1810,7 @@ struct drm_xe_oa_unit { /** @oa_unit_id: OA unit ID */ __u32 oa_unit_id; - /** @oa_unit_type: OA unit type of @drm_xe_oa_unit_type */ + /** @oa_unit_type: OA unit type of &enum drm_xe_oa_unit_type */ __u32 oa_unit_type; /** @capabilities: OA capabilities bit-mask */ @@ -1873,7 +1873,7 @@ struct drm_xe_query_oa_units { /** @pad: MBZ */ __u32 pad; /** - * @oa_units: struct @drm_xe_oa_unit array returned for this device. + * @oa_units: &struct drm_xe_oa_unit array returned for this device. * Written below as a u64 array to avoid problems with nested flexible * arrays with some compilers */ @@ -1902,22 +1902,22 @@ enum drm_xe_oa_format_type { /** * enum drm_xe_oa_property_id - OA stream property IDs * - * Stream params are specified as a chain of @drm_xe_ext_set_property - * structs, with @property values from enum @drm_xe_oa_property_id and - * @drm_xe_user_extension base.name set to @DRM_XE_OA_EXTENSION_SET_PROPERTY. - * @param field in struct @drm_xe_observation_param points to the first - * @drm_xe_ext_set_property struct. + * Stream params are specified as a chain of &struct drm_xe_ext_set_property + * structs, with property values from &enum drm_xe_oa_property_id and + * &struct drm_xe_user_extension base.name set to %DRM_XE_OA_EXTENSION_SET_PROPERTY. + * The param field in &struct drm_xe_observation_param points to the first + * &struct drm_xe_ext_set_property struct. * * Exactly the same mechanism is also used for stream reconfiguration using the - * @DRM_XE_OBSERVATION_IOCTL_CONFIG observation stream fd ioctl, though only a + * %DRM_XE_OBSERVATION_IOCTL_CONFIG observation stream fd ioctl, though only a * subset of properties below can be specified for stream reconfiguration. */ enum drm_xe_oa_property_id { #define DRM_XE_OA_EXTENSION_SET_PROPERTY 0 /** * @DRM_XE_OA_PROPERTY_OA_UNIT_ID: ID of the OA unit on which to open - * the OA stream, see @oa_unit_id in 'struct - * drm_xe_oa_unit'. Defaults to 0 if not provided. + * the OA stream, see oa_unit_id in &struct drm_xe_oa_unit. + * Defaults to 0 if not provided. */ DRM_XE_OA_PROPERTY_OA_UNIT_ID = 1, @@ -1930,7 +1930,7 @@ enum drm_xe_oa_property_id { /** * @DRM_XE_OA_PROPERTY_OA_METRIC_SET: OA metrics defining contents of OA - * reports, previously added via @DRM_XE_OBSERVATION_OP_ADD_CONFIG. + * reports, previously added via %DRM_XE_OBSERVATION_OP_ADD_CONFIG. */ DRM_XE_OA_PROPERTY_OA_METRIC_SET, @@ -1938,7 +1938,7 @@ enum drm_xe_oa_property_id { DRM_XE_OA_PROPERTY_OA_FORMAT, /* * OA_FORMAT's are specified the same way as in PRM/Bspec 52198/60942, - * in terms of the following quantities: a. enum @drm_xe_oa_format_type + * in terms of the following quantities: a. &enum drm_xe_oa_format_type * b. Counter select c. Counter size and d. BC report. Also refer to the * oa_formats array in drivers/gpu/drm/xe/xe_oa.c. */ @@ -1955,19 +1955,19 @@ enum drm_xe_oa_property_id { /** * @DRM_XE_OA_PROPERTY_OA_DISABLED: A value of 1 will open the OA - * stream in a DISABLED state (see @DRM_XE_OBSERVATION_IOCTL_ENABLE). + * stream in a DISABLED state (see %DRM_XE_OBSERVATION_IOCTL_ENABLE). */ DRM_XE_OA_PROPERTY_OA_DISABLED, /** * @DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID: Open the stream for a specific - * @exec_queue_id. OA queries can be executed on this exec queue. + * exec_queue_id. OA queries can be executed on this exec queue. */ DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID, /** * @DRM_XE_OA_PROPERTY_OA_ENGINE_INSTANCE: Optional engine instance to - * pass along with @DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID or will default to 0. + * pass along with %DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID or will default to 0. */ DRM_XE_OA_PROPERTY_OA_ENGINE_INSTANCE, @@ -1979,16 +1979,16 @@ enum drm_xe_oa_property_id { /** * @DRM_XE_OA_PROPERTY_NUM_SYNCS: Number of syncs in the sync array - * specified in @DRM_XE_OA_PROPERTY_SYNCS + * specified in %DRM_XE_OA_PROPERTY_SYNCS */ DRM_XE_OA_PROPERTY_NUM_SYNCS, /** - * @DRM_XE_OA_PROPERTY_SYNCS: Pointer to struct @drm_xe_sync array - * with array size specified via @DRM_XE_OA_PROPERTY_NUM_SYNCS. OA + * @DRM_XE_OA_PROPERTY_SYNCS: Pointer to &struct drm_xe_sync array + * with array size specified via %DRM_XE_OA_PROPERTY_NUM_SYNCS. OA * configuration will wait till input fences signal. Output fences * will signal after the new OA configuration takes effect. For - * @DRM_XE_SYNC_TYPE_USER_FENCE, @addr is a user pointer, similar + * %DRM_XE_SYNC_TYPE_USER_FENCE, addr is a user pointer, similar * to the VM bind case. */ DRM_XE_OA_PROPERTY_SYNCS, @@ -2011,9 +2011,9 @@ enum drm_xe_oa_property_id { /** * struct drm_xe_oa_config - OA metric configuration * - * Multiple OA configs can be added using @DRM_XE_OBSERVATION_OP_ADD_CONFIG. A + * Multiple OA configs can be added using %DRM_XE_OBSERVATION_OP_ADD_CONFIG. A * particular config can be specified when opening an OA stream using - * @DRM_XE_OA_PROPERTY_OA_METRIC_SET property. + * %DRM_XE_OA_PROPERTY_OA_METRIC_SET property. */ struct drm_xe_oa_config { /** @extensions: Pointer to the first extension struct, if any */ @@ -2034,7 +2034,7 @@ struct drm_xe_oa_config { /** * struct drm_xe_oa_stream_status - OA stream status returned from - * @DRM_XE_OBSERVATION_IOCTL_STATUS observation stream fd ioctl. Userspace can + * %DRM_XE_OBSERVATION_IOCTL_STATUS observation stream fd ioctl. Userspace can * call the ioctl to query stream status in response to EIO errno from * observation fd read(). */ @@ -2055,7 +2055,7 @@ struct drm_xe_oa_stream_status { /** * struct drm_xe_oa_stream_info - OA stream info returned from - * @DRM_XE_OBSERVATION_IOCTL_INFO observation stream fd ioctl + * %DRM_XE_OBSERVATION_IOCTL_INFO observation stream fd ioctl */ struct drm_xe_oa_stream_info { /** @extensions: Pointer to the first extension struct, if any */ @@ -2092,27 +2092,27 @@ enum drm_xe_pxp_session_type { * enum drm_xe_eu_stall_property_id - EU stall sampling input property ids. * * These properties are passed to the driver at open as a chain of - * @drm_xe_ext_set_property structures with @property set to these - * properties' enums and @value set to the corresponding values of these - * properties. @drm_xe_user_extension base.name should be set to - * @DRM_XE_EU_STALL_EXTENSION_SET_PROPERTY. + * &struct drm_xe_ext_set_property structures with property set to these + * properties' enums and value set to the corresponding values of these + * properties. &struct drm_xe_user_extension base.name should be set to + * %DRM_XE_EU_STALL_EXTENSION_SET_PROPERTY. * * With the file descriptor obtained from open, user space must enable - * the EU stall stream fd with @DRM_XE_OBSERVATION_IOCTL_ENABLE before + * the EU stall stream fd with %DRM_XE_OBSERVATION_IOCTL_ENABLE before * calling read(). EIO errno from read() indicates HW dropped data * due to full buffer. */ enum drm_xe_eu_stall_property_id { #define DRM_XE_EU_STALL_EXTENSION_SET_PROPERTY 0 /** - * @DRM_XE_EU_STALL_PROP_GT_ID: @gt_id of the GT on which + * @DRM_XE_EU_STALL_PROP_GT_ID: gt_id of the GT on which * EU stall data will be captured. */ DRM_XE_EU_STALL_PROP_GT_ID = 1, /** * @DRM_XE_EU_STALL_PROP_SAMPLE_RATE: Sampling rate in - * GPU cycles from @sampling_rates in struct @drm_xe_query_eu_stall + * GPU cycles from sampling_rates in &struct drm_xe_query_eu_stall */ DRM_XE_EU_STALL_PROP_SAMPLE_RATE, @@ -2127,9 +2127,9 @@ enum drm_xe_eu_stall_property_id { /** * struct drm_xe_query_eu_stall - Information about EU stall sampling. * - * If a query is made with a struct @drm_xe_device_query where .query - * is equal to @DRM_XE_DEVICE_QUERY_EU_STALL, then the reply uses - * struct @drm_xe_query_eu_stall in .data. + * If a query is made with a &struct drm_xe_device_query where .query + * is equal to %DRM_XE_DEVICE_QUERY_EU_STALL, then the reply uses + * &struct drm_xe_query_eu_stall in .data. */ struct drm_xe_query_eu_stall { /** @extensions: Pointer to the first extension struct, if any */ @@ -2240,7 +2240,7 @@ struct drm_xe_madvise { /** * @preferred_mem_loc.region_instance : Region instance. - * MBZ if @devmem_fd <= &DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE. + * MBZ if @devmem_fd <= %DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE. * Otherwise should point to the desired device * VRAM instance of the device indicated by * @preferred_mem_loc.devmem_fd. From 96cc9d79df5f7092c3807fad0d2fc3415cbd66b2 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 7 Apr 2026 03:00:45 +0000 Subject: [PATCH 041/120] drm/xe/uapi: Fix code examples in xe_drm.h documentation Fix incorrect field names and formatting in code examples: - .num_bb_per_exec -> .width (renamed struct field in exec_queue_create examples) - .num_eng_per_bb -> .num_placements (renamed struct field in exec_queue_create examples) - .atomic_val -> .atomic.val (correct nested struct field access in madvise example) - Remove unnecessary backslash escaping in UUID format string (%\08x -> %08x) - Fix descriptive text trapped inside code-block in exec_queue_create doc (split into two code blocks) v3: one more fix of split code-block in exec_queue_create doc. Assisted-by: GitHub Copilot:claude-opus-4.6 Cc: Xin Wang Reviewed-by: Xin Wang Link: https://patch.msgid.link/20260407030046.3394004-6-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- include/uapi/drm/xe_drm.h | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index 8751ad7b845f..58614f62d65b 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -1401,23 +1401,25 @@ struct drm_xe_vm_get_property { * struct drm_xe_exec_queue_create exec_queue_create = { * .extensions = 0, * .vm_id = vm, - * .num_bb_per_exec = 1, - * .num_eng_per_bb = 1, + * .width = 1, + * .num_placements = 1, * .instances = to_user_pointer(&instance), * }; * ioctl(fd, DRM_IOCTL_XE_EXEC_QUEUE_CREATE, &exec_queue_create); * - * Allow users to provide a hint to kernel for cases demanding low latency - * profile. Please note it will have impact on power consumption. User can - * indicate low latency hint with flag while creating exec queue as - * mentioned below, + * Allow users to provide a hint to kernel for cases demanding low latency + * profile. Please note it will have impact on power consumption. User can + * indicate low latency hint with flag while creating exec queue as + * mentioned below: + * + * .. code-block:: C * * struct drm_xe_exec_queue_create exec_queue_create = { * .flags = DRM_XE_EXEC_QUEUE_LOW_LATENCY_HINT, * .extensions = 0, * .vm_id = vm, - * .num_bb_per_exec = 1, - * .num_eng_per_bb = 1, + * .width = 1, + * .num_placements = 1, * .instances = to_user_pointer(&instance), * }; * ioctl(fd, DRM_IOCTL_XE_EXEC_QUEUE_CREATE, &exec_queue_create); @@ -2019,7 +2021,7 @@ struct drm_xe_oa_config { /** @extensions: Pointer to the first extension struct, if any */ __u64 extensions; - /** @uuid: String formatted like "%\08x-%\04x-%\04x-%\04x-%\012x" */ + /** @uuid: String formatted like "%08x-%04x-%04x-%04x-%012x" */ char uuid[36]; /** @n_regs: Number of regs in @regs_ptr */ @@ -2181,7 +2183,7 @@ struct drm_xe_query_eu_stall { * .start = 0x100000, * .range = 0x2000, * .type = DRM_XE_MEM_RANGE_ATTR_ATOMIC, - * .atomic_val = DRM_XE_ATOMIC_DEVICE, + * .atomic.val = DRM_XE_ATOMIC_DEVICE, * }; * * ioctl(fd, DRM_IOCTL_XE_MADVISE, &madvise); From 5150b57dacf9563ab29661c8e8a37a73f5a9fc54 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 7 Apr 2026 03:00:46 +0000 Subject: [PATCH 042/120] drm/xe/uapi: Fix doc formatting and completeness in xe_drm.h - Fix missing leading space before closing */ in comment block - Add DRM_IOCTL_XE_EXEC_QUEUE_SET_PROPERTY to the IOCTL overview list - Add missing query types to the device query doc list: DRM_XE_DEVICE_QUERY_UC_FW_VERSION, DRM_XE_DEVICE_QUERY_OA_UNITS, DRM_XE_DEVICE_QUERY_EU_STALL - Fix ioctl's -> ioctls (not possessive, 2 occurrences) - Remove duplicate parameter docs from drm_xe_mem_range_attr overview (already documented as inline member comments) - Fix extra whitespace before /** on 2 lines in drm_xe_mem_range_attr - Add missing blank line before DRM_XE_VM_BIND_FLAG_DECOMPRESS bullet to fix RST block quote warning v3: more fix (item 4 to 7). Assisted-by: GitHub Copilot:claude-opus-4.6 Cc: Xin Wang Reviewed-by: Xin Wang Link: https://patch.msgid.link/20260407030046.3394004-7-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- include/uapi/drm/xe_drm.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index 58614f62d65b..48e9f1fdb78d 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -83,6 +83,7 @@ extern "C" { * - &DRM_IOCTL_XE_OBSERVATION * - &DRM_IOCTL_XE_MADVISE * - &DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS + * - &DRM_IOCTL_XE_EXEC_QUEUE_SET_PROPERTY * - &DRM_IOCTL_XE_VM_GET_PROPERTY */ @@ -167,7 +168,7 @@ extern "C" { * Typically the struct drm_xe_user_extension would be embedded in some uAPI * struct, and in this case we would feed it the head of the chain(i.e ext1), * which would then apply all of the above extensions. -*/ + */ /** * struct drm_xe_user_extension - Base class for defining a chain of extensions @@ -705,7 +706,10 @@ struct drm_xe_query_pxp_status { * attributes. * - %DRM_XE_DEVICE_QUERY_GT_TOPOLOGY * - %DRM_XE_DEVICE_QUERY_ENGINE_CYCLES + * - %DRM_XE_DEVICE_QUERY_UC_FW_VERSION + * - %DRM_XE_DEVICE_QUERY_OA_UNITS * - %DRM_XE_DEVICE_QUERY_PXP_STATUS + * - %DRM_XE_DEVICE_QUERY_EU_STALL * * If size is set to 0, the driver fills it with the required size for * the requested type of data to query. If size is equal to the required @@ -1060,6 +1064,7 @@ struct drm_xe_vm_destroy { * not invoke autoreset. Neither will stack variables going out of scope. * Therefore it's recommended to always explicitly reset the madvises when * freeing the memory backing a region used in a &DRM_IOCTL_XE_MADVISE call. + * * - %DRM_XE_VM_BIND_FLAG_DECOMPRESS - Request on-device decompression for a MAP. * When set on a MAP bind operation, request the driver schedule an on-device * in-place decompression (via the migrate/resolve path) for the GPU mapping @@ -1760,10 +1765,10 @@ struct drm_xe_observation_param { }; /** - * enum drm_xe_observation_ioctls - Observation stream fd ioctl's + * enum drm_xe_observation_ioctls - Observation stream fd ioctls * * Information exchanged between userspace and kernel for observation fd - * ioctl's is stream type specific + * ioctls is stream type specific */ enum drm_xe_observation_ioctls { /** @DRM_XE_OBSERVATION_IOCTL_ENABLE: Enable data capture for an observation stream */ @@ -2379,14 +2384,9 @@ struct drm_xe_madvise { * page attribute table (PAT) index, and preferred memory location. * Userspace allocates an array of these structures and passes a pointer to the * ioctl to retrieve attributes for each memory range. - * - * @extensions: Pointer to the first extension struct, if any - * @start: Start address of the memory range - * @end: End address of the virtual memory range - * */ struct drm_xe_mem_range_attr { - /** @extensions: Pointer to the first extension struct, if any */ + /** @extensions: Pointer to the first extension struct, if any */ __u64 extensions; /** @start: start of the memory range */ @@ -2413,7 +2413,7 @@ struct drm_xe_mem_range_attr { __u32 reserved; } atomic; - /** @pat_index: Page attribute table index */ + /** @pat_index: Page attribute table index */ struct { /** @pat_index.val: PAT index */ __u32 val; From b71dee88e4b544d8b2f5d1406ca290f329a30ce4 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 30 Mar 2026 16:02:34 +0300 Subject: [PATCH 043/120] drm/xe/step: switch to the shared step definitions with i915 Use the shared stepping enums from include/drm/intel/step.h. For now, define xe_step as intel_step to avoid mass renames at the same time. For compat, we can remove the reverse macro. Reviewed-by: Luca Coelho Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/8173d9d753b343ba127d86277344248a6b1d0c3f.1774875688.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../drm/xe/compat-i915-headers/intel_step.h | 4 +- drivers/gpu/drm/xe/xe_step_types.h | 63 ++----------------- 2 files changed, 5 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/xe/compat-i915-headers/intel_step.h b/drivers/gpu/drm/xe/compat-i915-headers/intel_step.h index 0eabe2866f5f..cb55a659856b 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/intel_step.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/intel_step.h @@ -6,8 +6,6 @@ #ifndef __INTEL_STEP_H__ #define __INTEL_STEP_H__ -#include "xe_step_types.h" - -#define intel_step xe_step +#include #endif /* __INTEL_STEP_H__ */ diff --git a/drivers/gpu/drm/xe/xe_step_types.h b/drivers/gpu/drm/xe/xe_step_types.h index 43ca73850739..808385f81804 100644 --- a/drivers/gpu/drm/xe/xe_step_types.h +++ b/drivers/gpu/drm/xe/xe_step_types.h @@ -8,6 +8,10 @@ #include +#include + +#define xe_step intel_step + struct xe_step_info { u8 platform; u8 graphics; @@ -15,63 +19,4 @@ struct xe_step_info { u8 basedie; }; -#define STEP_ENUM_VAL(name) STEP_##name, - -/* - * Always define four minor steppings 0-3 for each stepping to match GMD ID - * spacing of values. See xe_step_gmdid_get(). - */ -#define STEP_NAME_LIST(func) \ - func(A0) \ - func(A1) \ - func(A2) \ - func(A3) \ - func(B0) \ - func(B1) \ - func(B2) \ - func(B3) \ - func(C0) \ - func(C1) \ - func(C2) \ - func(C3) \ - func(D0) \ - func(D1) \ - func(D2) \ - func(D3) \ - func(E0) \ - func(E1) \ - func(E2) \ - func(E3) \ - func(F0) \ - func(F1) \ - func(F2) \ - func(F3) \ - func(G0) \ - func(G1) \ - func(G2) \ - func(G3) \ - func(H0) \ - func(H1) \ - func(H2) \ - func(H3) \ - func(I0) \ - func(I1) \ - func(I2) \ - func(I3) \ - func(J0) \ - func(J1) \ - func(J2) \ - func(J3) - -/* - * Symbolic steppings that do not match the hardware. These are valid both as gt - * and display steppings as symbolic names. - */ -enum xe_step { - STEP_NONE = 0, - STEP_NAME_LIST(STEP_ENUM_VAL) - STEP_FUTURE, - STEP_FOREVER, -}; - #endif From 90788699d8ff81f1b1056c5e506392737340b78f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 30 Mar 2026 16:02:35 +0300 Subject: [PATCH 044/120] drm/xe/step: switch from enum xe_step to intel_step naming Remove the xe_step macro, and use the enum intel_step name directly. Reviewed-by: Luca Coelho Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/87530eaa2052ae4a3c97c7fb87e261d1f73341a7.1774875688.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/tests/xe_pci.c | 4 ++-- drivers/gpu/drm/xe/xe_step.c | 2 +- drivers/gpu/drm/xe/xe_step.h | 4 ++-- drivers/gpu/drm/xe/xe_step_types.h | 2 -- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/tests/xe_pci.c b/drivers/gpu/drm/xe/tests/xe_pci.c index f3179b31f13e..860409c579f8 100644 --- a/drivers/gpu/drm/xe/tests/xe_pci.c +++ b/drivers/gpu/drm/xe/tests/xe_pci.c @@ -131,12 +131,12 @@ static const char *subplatform_prefix(enum xe_subplatform s) return s == XE_SUBPLATFORM_NONE ? "" : " "; } -static const char *step_prefix(enum xe_step step) +static const char *step_prefix(enum intel_step step) { return step == STEP_NONE ? "" : " "; } -static const char *step_name(enum xe_step step) +static const char *step_name(enum intel_step step) { return step == STEP_NONE ? "" : xe_step_name(step); } diff --git a/drivers/gpu/drm/xe/xe_step.c b/drivers/gpu/drm/xe/xe_step.c index d0f888c31831..fb9c31613ca7 100644 --- a/drivers/gpu/drm/xe/xe_step.c +++ b/drivers/gpu/drm/xe/xe_step.c @@ -278,7 +278,7 @@ void xe_step_gmdid_get(struct xe_device *xe, case STEP_##name: \ return #name; -const char *xe_step_name(enum xe_step step) +const char *xe_step_name(enum intel_step step) { switch (step) { STEP_NAME_LIST(STEP_NAME_CASE); diff --git a/drivers/gpu/drm/xe/xe_step.h b/drivers/gpu/drm/xe/xe_step.h index 41f1c95c46e5..ea36b22cc297 100644 --- a/drivers/gpu/drm/xe/xe_step.h +++ b/drivers/gpu/drm/xe/xe_step.h @@ -18,8 +18,8 @@ void xe_step_pre_gmdid_get(struct xe_device *xe); void xe_step_gmdid_get(struct xe_device *xe, u32 graphics_gmdid_revid, u32 media_gmdid_revid); -static inline u32 xe_step_to_gmdid(enum xe_step step) { return step - STEP_A0; } +static inline u32 xe_step_to_gmdid(enum intel_step step) { return step - STEP_A0; } -const char *xe_step_name(enum xe_step step); +const char *xe_step_name(enum intel_step step); #endif diff --git a/drivers/gpu/drm/xe/xe_step_types.h b/drivers/gpu/drm/xe/xe_step_types.h index 808385f81804..f60572b93523 100644 --- a/drivers/gpu/drm/xe/xe_step_types.h +++ b/drivers/gpu/drm/xe/xe_step_types.h @@ -10,8 +10,6 @@ #include -#define xe_step intel_step - struct xe_step_info { u8 platform; u8 graphics; From baf310b9836445ca9056f04ec347293963a1cc6e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 30 Mar 2026 16:02:36 +0300 Subject: [PATCH 045/120] drm/i915/display: switch to including common step file directly Instead of using the proxy intel_step.h in display, just include the common step file directly where needed. This allows us to remove the compat intel_step.h header. Reviewed-by: Luca Coelho Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/83b5f13b7f863b9cbc61499bcff22af5cd822a0b.1774875688.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_cdclk.c | 2 +- drivers/gpu/drm/i915/display/intel_ddi.c | 2 +- drivers/gpu/drm/i915/display/intel_display_device.c | 2 +- drivers/gpu/drm/i915/display/intel_display_power.c | 2 +- drivers/gpu/drm/i915/display/intel_display_wa.c | 2 +- drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 2 +- drivers/gpu/drm/i915/display/intel_fbc.c | 2 +- drivers/gpu/drm/i915/display/intel_flipq.c | 2 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 2 +- drivers/gpu/drm/i915/display/intel_pmdemand.c | 2 +- drivers/gpu/drm/i915/display/intel_psr.c | 2 +- drivers/gpu/drm/i915/display/skl_universal_plane.c | 2 +- drivers/gpu/drm/xe/compat-i915-headers/intel_step.h | 11 ----------- 14 files changed, 13 insertions(+), 24 deletions(-) delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/intel_step.h diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index a47736613f6e..e3b044ee3e16 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "hsw_ips.h" #include "intel_atomic.h" @@ -46,7 +47,6 @@ #include "intel_pci_config.h" #include "intel_plane.h" #include "intel_psr.h" -#include "intel_step.h" #include "intel_vdsc.h" #include "skl_watermark.h" #include "skl_watermark_regs.h" diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index ebefa889bc8c..178074316a2c 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "icl_dsi.h" #include "intel_alpm.h" @@ -81,7 +82,6 @@ #include "intel_psr.h" #include "intel_quirks.h" #include "intel_snps_phy.h" -#include "intel_step.h" #include "intel_tc.h" #include "intel_vdsc.h" #include "intel_vdsc_regs.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c b/drivers/gpu/drm/i915/display/intel_display_device.c index be55ef8ea617..7260990038dd 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.c +++ b/drivers/gpu/drm/i915/display/intel_display_device.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "intel_cx0_phy_regs.h" #include "intel_de.h" @@ -21,7 +22,6 @@ #include "intel_display_types.h" #include "intel_display_wa.h" #include "intel_fbc.h" -#include "intel_step.h" __diag_push(); __diag_ignore_all("-Woverride-init", "Allow field initialization overrides for display info"); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index ec96b141c74c..1a2de99ad78f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -8,6 +8,7 @@ #include #include +#include #include "intel_backlight_regs.h" #include "intel_cdclk.h" @@ -30,7 +31,6 @@ #include "intel_pmdemand.h" #include "intel_pps_regs.h" #include "intel_snps_phy.h" -#include "intel_step.h" #include "skl_watermark.h" #include "skl_watermark_regs.h" #include "vlv_sideband.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.c b/drivers/gpu/drm/i915/display/intel_display_wa.c index 081a4092cd13..7d3d63a59882 100644 --- a/drivers/gpu/drm/i915/display/intel_display_wa.c +++ b/drivers/gpu/drm/i915/display/intel_display_wa.c @@ -4,12 +4,12 @@ */ #include +#include #include "intel_de.h" #include "intel_display_core.h" #include "intel_display_regs.h" #include "intel_display_wa.h" -#include "intel_step.h" static void gen11_display_wa_apply(struct intel_display *display) { diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 887b6de14e46..96c5bcf7e21e 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "intel_atomic.h" #include "intel_audio.h" @@ -56,7 +57,6 @@ #include "intel_link_bw.h" #include "intel_pfit.h" #include "intel_psr.h" -#include "intel_step.h" #include "intel_vdsc.h" #include "intel_vrr.h" #include "skl_scaler.h" diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index f5d4f7146fbc..e97b38f5d98e 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -25,6 +25,7 @@ #include #include +#include #include "bxt_dpio_phy_regs.h" #include "intel_cx0_phy.h" @@ -41,7 +42,6 @@ #include "intel_lt_phy.h" #include "intel_mg_phy_regs.h" #include "intel_pch_refclk.h" -#include "intel_step.h" #include "intel_tc.h" /** diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index ea0ce00c8474..55cb3ceb3523 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -44,6 +44,7 @@ #include #include #include +#include #include "i9xx_plane_regs.h" #include "intel_de.h" @@ -58,7 +59,6 @@ #include "intel_fbc_regs.h" #include "intel_frontbuffer.h" #include "intel_parent.h" -#include "intel_step.h" #define for_each_fbc_id(__display, __fbc_id) \ for ((__fbc_id) = INTEL_FBC_A; (__fbc_id) < I915_MAX_FBCS; (__fbc_id)++) \ diff --git a/drivers/gpu/drm/i915/display/intel_flipq.c b/drivers/gpu/drm/i915/display/intel_flipq.c index 253dc2e96d2d..333d28faf4ca 100644 --- a/drivers/gpu/drm/i915/display/intel_flipq.c +++ b/drivers/gpu/drm/i915/display/intel_flipq.c @@ -6,6 +6,7 @@ #include #include +#include #include "intel_crtc.h" #include "intel_de.h" @@ -17,7 +18,6 @@ #include "intel_dmc_regs.h" #include "intel_dsb.h" #include "intel_flipq.h" -#include "intel_step.h" #include "intel_vblank.h" #include "intel_vrr.h" diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 892eab4b6f92..9b4ff3b80b05 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "intel_connector.h" #include "intel_de.h" @@ -33,7 +34,6 @@ #include "intel_hdcp_regs.h" #include "intel_hdcp_shim.h" #include "intel_parent.h" -#include "intel_step.h" #define USE_HDCP_GSC(__display) (DISPLAY_VER(__display) >= 14) diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.c b/drivers/gpu/drm/i915/display/intel_pmdemand.c index 244806a26da3..7819b724795b 100644 --- a/drivers/gpu/drm/i915/display/intel_pmdemand.c +++ b/drivers/gpu/drm/i915/display/intel_pmdemand.c @@ -6,6 +6,7 @@ #include #include +#include #include "intel_atomic.h" #include "intel_bw.h" @@ -17,7 +18,6 @@ #include "intel_display_utils.h" #include "intel_display_wa.h" #include "intel_pmdemand.h" -#include "intel_step.h" #include "skl_watermark.h" struct pmdemand_params { diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 2f1b48cd8efd..7750a0282d60 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "intel_alpm.h" #include "intel_atomic.h" @@ -51,7 +52,6 @@ #include "intel_psr_regs.h" #include "intel_quirks.h" #include "intel_snps_phy.h" -#include "intel_step.h" #include "intel_vblank.h" #include "intel_vdsc.h" #include "intel_vrr.h" diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 11ba42c67e3e..7a9d494334b5 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "intel_bo.h" #include "intel_color.h" @@ -25,7 +26,6 @@ #include "intel_plane.h" #include "intel_psr.h" #include "intel_psr_regs.h" -#include "intel_step.h" #include "skl_scaler.h" #include "skl_universal_plane.h" #include "skl_universal_plane_regs.h" diff --git a/drivers/gpu/drm/xe/compat-i915-headers/intel_step.h b/drivers/gpu/drm/xe/compat-i915-headers/intel_step.h deleted file mode 100644 index cb55a659856b..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/intel_step.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#ifndef __INTEL_STEP_H__ -#define __INTEL_STEP_H__ - -#include - -#endif /* __INTEL_STEP_H__ */ From 45334d5c364498629b314391c7d1eac0b64c882f Mon Sep 17 00:00:00 2001 From: Anoop Vijay Date: Wed, 8 Apr 2026 04:07:59 -0700 Subject: [PATCH 046/120] drm/xe/xe_sysctrl: Drop redundant endian conversions in mailbox header macros Remove unnecessary le32_to_cpu() conversions from XE_SYSCTRL_APP_HDR_* macros. Fixes: 37ace5254a2b ("drm/xe/xe_sysctrl: Add ABI and mailbox interface headers") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202604010228.Z20DhK4g-lkp@intel.com/ Signed-off-by: Anoop Vijay Signed-off-by: Umesh Nerlige Ramappa Reviewed-by: Umesh Nerlige Ramappa Reviewed-by: Riana Tauro Link: https://patch.msgid.link/20260408110759.1407342-2-anoop.c.vijay@intel.com --- drivers/gpu/drm/xe/xe_sysctrl_mailbox.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_sysctrl_mailbox.h b/drivers/gpu/drm/xe/xe_sysctrl_mailbox.h index 91460be9e22c..f67e9234de48 100644 --- a/drivers/gpu/drm/xe/xe_sysctrl_mailbox.h +++ b/drivers/gpu/drm/xe/xe_sysctrl_mailbox.h @@ -15,13 +15,13 @@ struct xe_sysctrl; struct xe_sysctrl_mailbox_command; #define XE_SYSCTRL_APP_HDR_GROUP_ID(hdr) \ - FIELD_GET(APP_HDR_GROUP_ID_MASK, le32_to_cpu((hdr)->data)) + FIELD_GET(APP_HDR_GROUP_ID_MASK, (hdr)->data) #define XE_SYSCTRL_APP_HDR_COMMAND(hdr) \ - FIELD_GET(APP_HDR_COMMAND_MASK, le32_to_cpu((hdr)->data)) + FIELD_GET(APP_HDR_COMMAND_MASK, (hdr)->data) #define XE_SYSCTRL_APP_HDR_VERSION(hdr) \ - FIELD_GET(APP_HDR_VERSION_MASK, le32_to_cpu((hdr)->data)) + FIELD_GET(APP_HDR_VERSION_MASK, (hdr)->data) void xe_sysctrl_mailbox_init(struct xe_sysctrl *sc); int xe_sysctrl_send_command(struct xe_sysctrl *sc, From 4d33314decfeac8b82d771a1bd083a59f4ac6fae Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 10 Apr 2026 13:04:57 +0200 Subject: [PATCH 047/120] drm/xe/guc: Add support for NO_RESPONSE_BUSY in CTB We only have support for G2H NO_RESPONSE_BUSY messages over MMIO, but it turned out that GuC also uses that type of messages in CTB. The following error was recently observed on BMG after adding VGT policy updates to the GT restart sequence: [] xe 0000:03:00.0: [drm] *ERROR* Tile0: GT1: G2H channel broken on read, type=3, reset required [] xe 0000:03:00.0: [drm] *ERROR* Tile0: GT1: CT dequeue failed: -95 ... [] xe 0000:03:00.0: [drm] *ERROR* Tile0: GT1: Timed out wait for G2H, fence 21965, action 5502, done no [] xe 0000:03:00.0: [drm] PF: Tile0: GT1: Failed to push 1 policy KLV (-ETIME) [] xe 0000:03:00.0: [drm] Tile0: GT1: { key 0x8004 : no value } # engine_group_config where type=3 was this unrecognized NO_RESPONSE_BUSY message. Note that GuC might send the real RESPONSE message right after the BUSY message, so we must be prepared to update our g2h_fence data twice before sender actually wakes up and clears the flags. Signed-off-by: Michal Wajdeczko Cc: Daniele Ceraolo Spurio Reviewed-by: Daniele Ceraolo Spurio Link: https://patch.msgid.link/20260410110457.573-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_guc_ct.c | 38 ++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c index a11cff7a20be..21e0dad9a481 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.c +++ b/drivers/gpu/drm/xe/xe_guc_ct.c @@ -186,13 +186,16 @@ static void fast_req_track(struct xe_guc_ct *ct, u16 fence, u16 action) { } struct g2h_fence { u32 *response_buffer; u32 seqno; + /* fields below this point are setup based on the response */ u32 response_data; u16 response_len; u16 error; u16 hint; u16 reason; + u32 counter; bool cancel; bool retry; + bool wait; bool fail; bool done; }; @@ -204,6 +207,11 @@ static void g2h_fence_init(struct g2h_fence *g2h_fence, u32 *response_buffer) g2h_fence->seqno = ~0x0; } +static void g2h_fence_reinit(struct g2h_fence *g2h_fence) +{ + memset_after(g2h_fence, 0, seqno); +} + static void g2h_fence_cancel(struct g2h_fence *g2h_fence) { g2h_fence->cancel = true; @@ -1331,6 +1339,7 @@ static int guc_ct_send_recv(struct xe_guc_ct *ct, const u32 *action, u32 len, /* READ_ONCEs pairs with WRITE_ONCEs in parse_g2h_response * and g2h_fence_cancel. */ +wait_again: ret = wait_event_timeout(ct->g2h_fence_wq, READ_ONCE(g2h_fence.done), HZ); if (!ret) { LNL_FLUSH_WORK(&ct->g2h_worker); @@ -1356,6 +1365,14 @@ static int guc_ct_send_recv(struct xe_guc_ct *ct, const u32 *action, u32 len, return -ETIME; } + if (g2h_fence.wait) { + xe_gt_dbg(gt, "H2G action %#x busy: counter %u\n", + action[0], g2h_fence.counter); + /* we can't leave any response data if we want to wait again */ + g2h_fence_reinit(&g2h_fence); + mutex_unlock(&ct->lock); + goto wait_again; + } if (g2h_fence.retry) { xe_gt_dbg(gt, "H2G action %#x retrying: reason %#x\n", action[0], g2h_fence.reason); @@ -1508,7 +1525,12 @@ static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len) return -EPROTO; } - g2h_fence = xa_erase(&ct->fence_lookup, fence); + /* don't erase as we still expect a final response with the same fence */ + if (type == GUC_HXG_TYPE_NO_RESPONSE_BUSY) + g2h_fence = xa_load(&ct->fence_lookup, fence); + else + g2h_fence = xa_erase(&ct->fence_lookup, fence); + if (unlikely(!g2h_fence)) { /* Don't tear down channel, as send could've timed out */ /* CT_DEAD(ct, NULL, PARSE_G2H_UNKNOWN); */ @@ -1519,6 +1541,12 @@ static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len) xe_gt_assert(gt, fence == g2h_fence->seqno); + /* + * reinit as we might have already process this g2h_fence before + * if we received a NO_RESPONSE_BUSY reply + */ + g2h_fence_reinit(g2h_fence); + if (type == GUC_HXG_TYPE_RESPONSE_FAILURE) { g2h_fence->fail = true; g2h_fence->error = FIELD_GET(GUC_HXG_FAILURE_MSG_0_ERROR, hxg[0]); @@ -1526,6 +1554,9 @@ static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len) } else if (type == GUC_HXG_TYPE_NO_RESPONSE_RETRY) { g2h_fence->retry = true; g2h_fence->reason = FIELD_GET(GUC_HXG_RETRY_MSG_0_REASON, hxg[0]); + } else if (type == GUC_HXG_TYPE_NO_RESPONSE_BUSY) { + g2h_fence->wait = true; + g2h_fence->counter = FIELD_GET(GUC_HXG_BUSY_MSG_0_COUNTER, hxg[0]); } else if (g2h_fence->response_buffer) { g2h_fence->response_len = hxg_len; memcpy(g2h_fence->response_buffer, hxg, hxg_len * sizeof(u32)); @@ -1533,7 +1564,9 @@ static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len) g2h_fence->response_data = FIELD_GET(GUC_HXG_RESPONSE_MSG_0_DATA0, hxg[0]); } - g2h_release_space(ct, GUC_CTB_HXG_MSG_MAX_LEN); + /* don't release any space if it was an intermediate message */ + if (!g2h_fence->wait) + g2h_release_space(ct, GUC_CTB_HXG_MSG_MAX_LEN); /* WRITE_ONCE pairs with READ_ONCEs in guc_ct_send_recv. */ WRITE_ONCE(g2h_fence->done, true); @@ -1570,6 +1603,7 @@ static int parse_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len) case GUC_HXG_TYPE_RESPONSE_SUCCESS: case GUC_HXG_TYPE_RESPONSE_FAILURE: case GUC_HXG_TYPE_NO_RESPONSE_RETRY: + case GUC_HXG_TYPE_NO_RESPONSE_BUSY: ret = parse_g2h_response(ct, msg, len); break; default: From 3fb4d2c10702695f33eee9f00a94d2d5e91a5755 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 2 Apr 2026 21:17:14 +0200 Subject: [PATCH 048/120] drm/xe/guc: Update POLICY_SCHED_IF_IDLE documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Starting from the GuC firmware version 70.12.0 the meaning of the POLICY_SCHED_IF_IDLE has changed, which now acts as a bulk update of the VF_CFG_SCHED_PRIORITY configurations of all VFs. Signed-off-by: Michal Wajdeczko Reviewed-by: Piotr Piórkowski Link: https://patch.msgid.link/20260402191726.4932-2-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/abi/guc_klvs_abi.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/xe/abi/guc_klvs_abi.h b/drivers/gpu/drm/xe/abi/guc_klvs_abi.h index f0815500177b..644f5a4226d7 100644 --- a/drivers/gpu/drm/xe/abi/guc_klvs_abi.h +++ b/drivers/gpu/drm/xe/abi/guc_klvs_abi.h @@ -192,6 +192,13 @@ enum { * `GuC KLV`_ keys available for use with PF2GUC_UPDATE_VGT_POLICY. * * _`GUC_KLV_VGT_POLICY_SCHED_IF_IDLE` : 0x8001 + * [From 70.12.0] + * This config allows to update scheduling priority of PF and all VFs at once. + * Setting this policy to 0 updates all VFs scheduling priorities to LOW, and + * setting this policy to 1 updates all VFs scheduling priorities to NORMAL. + * Those changes will take effect on the next VF-Switch event. + * + * [Before 70.12.0] * This config sets whether strict scheduling is enabled whereby any VF * that doesn’t have work to submit is still allocated a fixed execution * time-slice to ensure active VFs execution is always consistent even From a438423409692833e3b0f56a1d8440ac1761e594 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 2 Apr 2026 21:17:15 +0200 Subject: [PATCH 049/120] drm/xe/pf: Fix pf_get_sched_priority() function signature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pf_get_sched_priority() function returns scheduling priority that we defined as u32 so while it works we shouldn't return int. Signed-off-by: Michal Wajdeczko Reviewed-by: Piotr Piórkowski Link: https://patch.msgid.link/20260402191726.4932-3-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index 2f376b5fb088..658e9b048751 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -2500,7 +2500,7 @@ static int pf_provision_sched_priority(struct xe_gt *gt, unsigned int vfid, u32 return 0; } -static int pf_get_sched_priority(struct xe_gt *gt, unsigned int vfid) +static u32 pf_get_sched_priority(struct xe_gt *gt, unsigned int vfid) { struct xe_gt_sriov_config *config = pf_pick_vf_config(gt, vfid); From fbbf73a81b845ea6fd40688a63570298298d03c1 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 2 Apr 2026 21:17:16 +0200 Subject: [PATCH 050/120] drm/xe/pf: Force new VFs prorities only once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We should force change of VFs scheduling priorities only after initial change of the SCHED_IF_IDLE policy. Doing that also during any later policy reprovisioning will overwrite changes done on the individual per-VF scheduling priorities (currently only for PF). While around also move priority change code to the _config component to maintain a proper isolation. Also document our expectation about the GuC version where the new meaning of the policy KLV is present. Signed-off-by: Michal Wajdeczko Reviewed-by: Piotr Piórkowski Link: https://patch.msgid.link/20260402191726.4932-4-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 29 ++++++++++++++ drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h | 1 + drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c | 46 ++++++++++------------ 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index 658e9b048751..c74745642a92 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -2550,6 +2550,35 @@ u32 xe_gt_sriov_pf_config_get_sched_priority(struct xe_gt *gt, unsigned int vfid return priority; } +/** + * xe_gt_sriov_pf_config_force_sched_priority_locked() - Force update scheduling priority. + * @gt: the &xe_gt + * @priority: new scheduling priority to set + * + * This function allows to update cached values of the scheduling priorities of all + * VFs (and PF) as result of applying the `GUC_KLV_VGT_POLICY_SCHED_IF_IDLE`_ policy. + * + * This function can only be called on PF. + */ +void xe_gt_sriov_pf_config_force_sched_priority_locked(struct xe_gt *gt, u32 priority) +{ + unsigned int total_vfs = 1 + xe_gt_sriov_pf_get_totalvfs(gt); + struct xe_gt_sriov_config *config; + unsigned int n; + + xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); + + for (n = 0; n < total_vfs; n++) { + config = pf_pick_vf_config(gt, VFID(n)); + config->sched_priority = priority; + } + + pf_config_bulk_set_u32_done(gt, PFID, 1 + total_vfs, priority, + pf_get_sched_priority, "scheduling priority", + sched_priority_unit, n, 0); +} + static void pf_reset_config_sched(struct xe_gt *gt, struct xe_gt_sriov_config *config) { int i; diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h index 4a004ecd6140..e9314f0a9b4e 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h @@ -71,6 +71,7 @@ int xe_gt_sriov_pf_config_set_groups_preempt_timeouts(struct xe_gt *gt, unsigned u32 xe_gt_sriov_pf_config_get_sched_priority(struct xe_gt *gt, unsigned int vfid); int xe_gt_sriov_pf_config_set_sched_priority(struct xe_gt *gt, unsigned int vfid, u32 priority); +void xe_gt_sriov_pf_config_force_sched_priority_locked(struct xe_gt *gt, u32 priority); u32 xe_gt_sriov_pf_config_get_threshold(struct xe_gt *gt, unsigned int vfid, enum xe_guc_klv_threshold_index index); diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c index 848e24926ecd..6ab02e96e46c 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c @@ -8,6 +8,7 @@ #include "abi/guc_actions_sriov_abi.h" #include "xe_gt.h" +#include "xe_gt_sriov_pf_config.h" #include "xe_gt_sriov_pf_helpers.h" #include "xe_gt_sriov_pf_policy.h" #include "xe_gt_sriov_printk.h" @@ -153,33 +154,14 @@ static int pf_update_policy_u32(struct xe_gt *gt, u16 key, u32 *policy, u32 valu return 0; } -static void pf_bulk_reset_sched_priority(struct xe_gt *gt, u32 priority) -{ - unsigned int total_vfs = 1 + xe_gt_sriov_pf_get_totalvfs(gt); - unsigned int n; - - xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); - lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); - - for (n = 0; n < total_vfs; n++) - gt->sriov.pf.vfs[n].config.sched_priority = priority; -} - static int pf_provision_sched_if_idle(struct xe_gt *gt, bool enable) { - int err; - xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); - err = pf_update_policy_bool(gt, GUC_KLV_VGT_POLICY_SCHED_IF_IDLE_KEY, - >->sriov.pf.policy.guc.sched_if_idle, - enable); - - if (!err) - pf_bulk_reset_sched_priority(gt, enable ? GUC_SCHED_PRIORITY_NORMAL : - GUC_SCHED_PRIORITY_LOW); - return err; + return pf_update_policy_bool(gt, GUC_KLV_VGT_POLICY_SCHED_IF_IDLE_KEY, + >->sriov.pf.policy.guc.sched_if_idle, + enable); } static int pf_reprovision_sched_if_idle(struct xe_gt *gt) @@ -209,13 +191,25 @@ static void pf_sanitize_sched_if_idle(struct xe_gt *gt) */ int xe_gt_sriov_pf_policy_set_sched_if_idle(struct xe_gt *gt, bool enable) { + u32 priority; int err; - mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); - err = pf_provision_sched_if_idle(gt, enable); - mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); + guard(mutex)(xe_gt_sriov_pf_master_mutex(gt)); - return err; + err = pf_provision_sched_if_idle(gt, enable); + if (err) + return err; + + /* + * As of GuC 70.12 a change of this policy impacts individual configs + * of all VFs. See `GUC_KLV_VGT_POLICY_SCHED_IF_IDLE`_ for details. + */ + xe_gt_assert(gt, GUC_FIRMWARE_VER_AT_LEAST(>->uc.guc, 70, 12)); + + priority = enable ? GUC_SCHED_PRIORITY_NORMAL : GUC_SCHED_PRIORITY_LOW; + xe_gt_sriov_pf_config_force_sched_priority_locked(gt, priority); + + return 0; } /** From 980bb387fb08163d0692f25892d8b3e34542349c Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 2 Apr 2026 21:17:17 +0200 Subject: [PATCH 051/120] drm/xe/pf: Print applied policy KLVs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Under CONFIG_DRM_XE_DEBUG_SRIOV print all policy KLVs sent to the GuC for better diagnostics. This is similar what we are already doing with VF configuration KLVs. Signed-off-by: Michal Wajdeczko Reviewed-by: Piotr Piórkowski Link: https://patch.msgid.link/20260402191726.4932-5-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c index 6ab02e96e46c..c88c4e6a9b61 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c @@ -68,6 +68,15 @@ static int pf_push_policy_buf_klvs(struct xe_gt *gt, u32 num_klvs, return err; } + if (IS_ENABLED(CONFIG_DRM_XE_DEBUG_SRIOV)) { + struct drm_printer p = xe_gt_dbg_printer(gt); + void *klvs = xe_guc_buf_cpu_ptr(buf); + + xe_gt_sriov_dbg(gt, "pushed policy update with %u KLV%s:\n", + num_klvs, str_plural(num_klvs)); + xe_guc_klv_print(klvs, num_dwords, &p); + } + return 0; } From b23883a0874fbca9ada07b75509c6126fb5f3575 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 2 Apr 2026 21:17:18 +0200 Subject: [PATCH 052/120] drm/xe/pf: Reprovision policy settings after GT reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In addition to the reprovisioning of individual VFs configurations, we should also reprovision GuC global policy settings. Note that we already had a draft function for that but we missed to call it once we started handling GT reset. Reuse it now but don't take extra RPM as this is now a caller responsibility and drop unused parameter. Signed-off-by: Michal Wajdeczko Reviewed-by: Piotr Piórkowski Link: https://patch.msgid.link/20260402191726.4932-6-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf.c | 1 + drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c | 14 +++----------- drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h | 2 +- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c index fb5c9101e275..7868056841b3 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c @@ -219,6 +219,7 @@ static void pf_restart(struct xe_gt *gt) xe_gt_assert(gt, !xe_pm_runtime_suspended(xe)); + xe_gt_sriov_pf_policy_restart(gt); xe_gt_sriov_pf_config_restart(gt); xe_gt_sriov_pf_control_restart(gt); diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c index c88c4e6a9b61..aa80b4abd42f 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c @@ -17,7 +17,6 @@ #include "xe_guc_ct.h" #include "xe_guc_klv_helpers.h" #include "xe_guc_submit.h" -#include "xe_pm.h" /* * Return: number of KLVs that were successfully parsed and saved, @@ -692,30 +691,23 @@ void xe_gt_sriov_pf_policy_sanitize(struct xe_gt *gt) } /** - * xe_gt_sriov_pf_policy_reprovision - Reprovision (and optionally reset) policy settings. + * xe_gt_sriov_pf_policy_restart() - Reprovision policy settings. * @gt: the &xe_gt - * @reset: if true will reprovision using default values instead of latest * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure. */ -int xe_gt_sriov_pf_policy_reprovision(struct xe_gt *gt, bool reset) +int xe_gt_sriov_pf_policy_restart(struct xe_gt *gt) { int err = 0; - xe_pm_runtime_get_noresume(gt_to_xe(gt)); + guard(mutex)(xe_gt_sriov_pf_master_mutex(gt)); - mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); - if (reset) - pf_sanitize_guc_policies(gt); err |= pf_reprovision_sched_if_idle(gt); err |= pf_reprovision_reset_engine(gt); err |= pf_reprovision_sample_period(gt); err |= pf_reprovision_sched_groups(gt); - mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); - - xe_pm_runtime_put(gt_to_xe(gt)); return err ? -ENXIO : 0; } diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h index bd73aa58f9ca..c9d4c4aaaf5d 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h @@ -29,7 +29,7 @@ bool xe_gt_sriov_pf_policy_sched_groups_enabled(struct xe_gt *gt); void xe_gt_sriov_pf_policy_init(struct xe_gt *gt); void xe_gt_sriov_pf_policy_sanitize(struct xe_gt *gt); -int xe_gt_sriov_pf_policy_reprovision(struct xe_gt *gt, bool reset); +int xe_gt_sriov_pf_policy_restart(struct xe_gt *gt); int xe_gt_sriov_pf_policy_print(struct xe_gt *gt, struct drm_printer *p); #endif From 689937c71cbbec927ba2c04f86fd1e59de5097f3 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 2 Apr 2026 21:17:19 +0200 Subject: [PATCH 053/120] drm/xe/pf: Don't reprovision policies if already default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to send policy updates to the GuC if policies were not changed from the default settings (usually zero value). Signed-off-by: Michal Wajdeczko Reviewed-by: Piotr Piórkowski Link: https://patch.msgid.link/20260402191726.4932-7-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c index aa80b4abd42f..0007ed7e0d38 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c @@ -177,6 +177,9 @@ static int pf_reprovision_sched_if_idle(struct xe_gt *gt) xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); + if (!gt->sriov.pf.policy.guc.sched_if_idle) + return 0; + return pf_provision_sched_if_idle(gt, gt->sriov.pf.policy.guc.sched_if_idle); } @@ -255,6 +258,9 @@ static int pf_reprovision_reset_engine(struct xe_gt *gt) xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); + if (!gt->sriov.pf.policy.guc.reset_engine) + return 0; + return pf_provision_reset_engine(gt, gt->sriov.pf.policy.guc.reset_engine); } @@ -321,6 +327,9 @@ static int pf_reprovision_sample_period(struct xe_gt *gt) xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); + if (!gt->sriov.pf.policy.guc.sample_period) + return 0; + return pf_provision_sample_period(gt, gt->sriov.pf.policy.guc.sample_period); } From 43533f75c4577885da1f2e6fddeb88ccf61005f0 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 2 Apr 2026 21:17:20 +0200 Subject: [PATCH 054/120] drm/xe/pf: Encode scheduling priority KLV if needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After a reset we missed to reprovision VFs scheduling priority config. But as of today, the GuC firmware allows to change scheduling priority using config SCHED_PRIORITY KLV only for the PF and configuration of all VFs relies on the previously applied value of the SCHED_IF_IDLE policy. Use this policy value to check and decide whether we need to encode VF priority KLV while reprovisioning this VF. Signed-off-by: Michal Wajdeczko Reviewed-by: Piotr Piórkowski Link: https://patch.msgid.link/20260402191726.4932-8-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 12 +++++++++++ drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c | 25 ++++++++++++++++------ drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h | 1 + 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index c74745642a92..703a954d78d5 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -285,6 +285,13 @@ static u32 encode_config_ggtt(u32 *cfg, const struct xe_gt_sriov_config *config, return encode_ggtt(cfg, xe_ggtt_node_addr(node), xe_ggtt_node_size(node), details); } +static bool custom_sched_priority(struct xe_gt *gt, u32 priority) +{ + return xe_gt_sriov_pf_policy_get_sched_if_idle_locked(gt) ? + priority != GUC_SCHED_PRIORITY_NORMAL : + priority != GUC_SCHED_PRIORITY_LOW; +} + static u32 encode_config_sched(struct xe_gt *gt, u32 *cfg, u32 n, const struct xe_gt_sriov_config *config) { @@ -313,6 +320,11 @@ static u32 encode_config_sched(struct xe_gt *gt, u32 *cfg, u32 n, cfg[n++] = config->preempt_timeout[0]; } + if (custom_sched_priority(gt, config->sched_priority)) { + cfg[n++] = PREP_GUC_KLV_TAG(VF_CFG_SCHED_PRIORITY); + cfg[n++] = config->sched_priority; + } + return n; } diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c index 0007ed7e0d38..63e6326d45f8 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c @@ -223,6 +223,22 @@ int xe_gt_sriov_pf_policy_set_sched_if_idle(struct xe_gt *gt, bool enable) return 0; } +/** + * xe_gt_sriov_pf_policy_get_sched_if_idle_locked() - Retrieve value of 'sched_if_idle' policy. + * @gt: the &xe_gt where to read the policy from + * + * This function can only be called on PF. + * + * Return: last value of 'sched_if_idle' policy applied. + */ +bool xe_gt_sriov_pf_policy_get_sched_if_idle_locked(struct xe_gt *gt) +{ + xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); + + return gt->sriov.pf.policy.guc.sched_if_idle; +} + /** * xe_gt_sriov_pf_policy_get_sched_if_idle - Retrieve value of 'sched_if_idle' policy. * @gt: the &xe_gt where to read the policy from @@ -233,15 +249,10 @@ int xe_gt_sriov_pf_policy_set_sched_if_idle(struct xe_gt *gt, bool enable) */ bool xe_gt_sriov_pf_policy_get_sched_if_idle(struct xe_gt *gt) { - bool enable; - xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); + guard(mutex)(xe_gt_sriov_pf_master_mutex(gt)); - mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); - enable = gt->sriov.pf.policy.guc.sched_if_idle; - mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); - - return enable; + return xe_gt_sriov_pf_policy_get_sched_if_idle_locked(gt); } static int pf_provision_reset_engine(struct xe_gt *gt, bool enable) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h index c9d4c4aaaf5d..f437dc1f5e90 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h @@ -15,6 +15,7 @@ struct xe_gt; int xe_gt_sriov_pf_policy_set_sched_if_idle(struct xe_gt *gt, bool enable); bool xe_gt_sriov_pf_policy_get_sched_if_idle(struct xe_gt *gt); +bool xe_gt_sriov_pf_policy_get_sched_if_idle_locked(struct xe_gt *gt); int xe_gt_sriov_pf_policy_set_reset_engine(struct xe_gt *gt, bool enable); bool xe_gt_sriov_pf_policy_get_reset_engine(struct xe_gt *gt); int xe_gt_sriov_pf_policy_set_sample_period(struct xe_gt *gt, u32 value); From 0701bf6fce0aa6f0f2122c9a324bd954d3d91b0b Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 2 Apr 2026 21:17:21 +0200 Subject: [PATCH 055/120] drm/xe/pf: Check EQ/PT/PRIO when testing VF config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In addition to the hard resources (like GGTT, CTXs, DBs) we should also check if VF was already configured (by sysfs or debugfs) with optional parameters like execution quantum (EQ), preemption timeout (PT) or scheduling priority (PRIO) as otherwise we might miss to send to the GuC updated latest values after a resume or GT reset. Signed-off-by: Michal Wajdeczko Reviewed-by: Piotr Piórkowski Link: https://patch.msgid.link/20260402191726.4932-9-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index 703a954d78d5..abc6b5e22048 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -2090,6 +2090,17 @@ static u32 pf_get_exec_quantum(struct xe_gt *gt, unsigned int vfid) return config->exec_quantum[0]; } +static bool pf_non_default_exec_quantum(struct xe_gt *gt, unsigned int vfid) +{ + struct xe_gt_sriov_config *config = pf_pick_vf_config(gt, vfid); + int i; + + for (i = 0; i < ARRAY_SIZE(config->exec_quantum); i++) + if (config->exec_quantum[i]) + return true; + return false; +} + /** * xe_gt_sriov_pf_config_set_exec_quantum_locked() - Configure PF/VF execution quantum. * @gt: the &xe_gt @@ -2305,6 +2316,17 @@ static u32 pf_get_preempt_timeout(struct xe_gt *gt, unsigned int vfid) return config->preempt_timeout[0]; } +static bool pf_non_default_preempt_timeout(struct xe_gt *gt, unsigned int vfid) +{ + struct xe_gt_sriov_config *config = pf_pick_vf_config(gt, vfid); + int i; + + for (i = 0; i < ARRAY_SIZE(config->preempt_timeout); i++) + if (config->preempt_timeout[i]) + return true; + return false; +} + /** * xe_gt_sriov_pf_config_set_preempt_timeout_locked() - Configure PF/VF preemption timeout. * @gt: the &xe_gt @@ -2603,6 +2625,13 @@ static void pf_reset_config_sched(struct xe_gt *gt, struct xe_gt_sriov_config *c } } +static bool pf_non_default_sched(struct xe_gt *gt, unsigned int vfid) +{ + return pf_non_default_exec_quantum(gt, vfid) || + pf_non_default_preempt_timeout(gt, vfid) || + custom_sched_priority(gt, pf_get_sched_priority(gt, vfid)); +} + static int pf_provision_threshold(struct xe_gt *gt, unsigned int vfid, enum xe_guc_klv_threshold_index index, u32 value) { @@ -2879,6 +2908,9 @@ static int pf_validate_vf_config(struct xe_gt *gt, unsigned int vfid) valid_all = valid_all && valid_lmem; } + /* also check optional EQ/PT/PRIO */ + valid_any = valid_any || pf_non_default_sched(gt, vfid); + return valid_all ? 0 : valid_any ? -ENOKEY : -ENODATA; } From 55d1945636583f2b88034e50458013f1a9165ee0 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 2 Apr 2026 21:17:22 +0200 Subject: [PATCH 056/120] drm/xe/pf: Allow to change sched_if_idle policy under lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In upcoming patch we will need to update sched_if_idle policy when we already hold the provisioning mutex. Split existing function into two variants to allow that. Signed-off-by: Michal Wajdeczko Reviewed-by: Piotr Piórkowski Link: https://patch.msgid.link/20260402191726.4932-10-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c | 23 +++++++++++++++++++--- drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h | 1 + 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c index 63e6326d45f8..e8458d63742d 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c @@ -192,7 +192,7 @@ static void pf_sanitize_sched_if_idle(struct xe_gt *gt) } /** - * xe_gt_sriov_pf_policy_set_sched_if_idle - Control the 'sched_if_idle' policy. + * xe_gt_sriov_pf_policy_set_sched_if_idle_locked() - Control the 'sched_if_idle' policy. * @gt: the &xe_gt where to apply the policy * @enable: the value of the 'sched_if_idle' policy * @@ -200,12 +200,12 @@ static void pf_sanitize_sched_if_idle(struct xe_gt *gt) * * Return: 0 on success or a negative error code on failure. */ -int xe_gt_sriov_pf_policy_set_sched_if_idle(struct xe_gt *gt, bool enable) +int xe_gt_sriov_pf_policy_set_sched_if_idle_locked(struct xe_gt *gt, bool enable) { u32 priority; int err; - guard(mutex)(xe_gt_sriov_pf_master_mutex(gt)); + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); err = pf_provision_sched_if_idle(gt, enable); if (err) @@ -223,6 +223,23 @@ int xe_gt_sriov_pf_policy_set_sched_if_idle(struct xe_gt *gt, bool enable) return 0; } +/** + * xe_gt_sriov_pf_policy_set_sched_if_idle() - Control the 'sched_if_idle' policy. + * @gt: the &xe_gt where to apply the policy + * @enable: the value of the 'sched_if_idle' policy + * + * This function can only be called on PF. + * + * Return: 0 on success or a negative error code on failure. + */ +int xe_gt_sriov_pf_policy_set_sched_if_idle(struct xe_gt *gt, bool enable) +{ + xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); + guard(mutex)(xe_gt_sriov_pf_master_mutex(gt)); + + return xe_gt_sriov_pf_policy_set_sched_if_idle_locked(gt, enable); +} + /** * xe_gt_sriov_pf_policy_get_sched_if_idle_locked() - Retrieve value of 'sched_if_idle' policy. * @gt: the &xe_gt where to read the policy from diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h index f437dc1f5e90..d667d66897b1 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h @@ -14,6 +14,7 @@ struct drm_printer; struct xe_gt; int xe_gt_sriov_pf_policy_set_sched_if_idle(struct xe_gt *gt, bool enable); +int xe_gt_sriov_pf_policy_set_sched_if_idle_locked(struct xe_gt *gt, bool enable); bool xe_gt_sriov_pf_policy_get_sched_if_idle(struct xe_gt *gt); bool xe_gt_sriov_pf_policy_get_sched_if_idle_locked(struct xe_gt *gt); int xe_gt_sriov_pf_policy_set_reset_engine(struct xe_gt *gt, bool enable); From 24ac010a97b6e6a65dc32ee2af1cdbe4a44daf7e Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 2 Apr 2026 21:17:23 +0200 Subject: [PATCH 057/120] drm/xe/pf: Reprovision scheduling to default when no VFs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Once we have disabled VFs there is no point in keeping potentially limited PF scheduling provisioning as we want to complete a cleanup of the VFs resources and return to the pure native mode, the same as before VFs were enabled, as soon as possible. Signed-off-by: Michal Wajdeczko Reviewed-by: Piotr Piórkowski Link: https://patch.msgid.link/20260402191726.4932-11-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_pci_sriov.c | 2 ++ drivers/gpu/drm/xe/xe_sriov_pf_provision.c | 39 ++++++++++++++++++++++ drivers/gpu/drm/xe/xe_sriov_pf_provision.h | 1 + 3 files changed, 42 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_pci_sriov.c b/drivers/gpu/drm/xe/xe_pci_sriov.c index 3fd22034f03e..35e6b53e18ce 100644 --- a/drivers/gpu/drm/xe/xe_pci_sriov.c +++ b/drivers/gpu/drm/xe/xe_pci_sriov.c @@ -191,6 +191,8 @@ static int pf_disable_vfs(struct xe_device *xe) pci_disable_sriov(pdev); + xe_sriov_pf_reprovision_default(xe); + pf_reset_vfs(xe, num_vfs); xe_sriov_pf_unprovision_vfs(xe, num_vfs); diff --git a/drivers/gpu/drm/xe/xe_sriov_pf_provision.c b/drivers/gpu/drm/xe/xe_sriov_pf_provision.c index abe3677d33ed..e11874d689fa 100644 --- a/drivers/gpu/drm/xe/xe_sriov_pf_provision.c +++ b/drivers/gpu/drm/xe/xe_sriov_pf_provision.c @@ -103,6 +103,45 @@ int xe_sriov_pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs) return 0; } +static int pf_reprovision_default(struct xe_device *xe) +{ + struct xe_gt *gt; + unsigned int id; + int result = 0; + int err; + + guard(mutex)(xe_sriov_pf_master_mutex(xe)); + + for_each_gt(gt, xe, id) { + err = xe_gt_sriov_pf_policy_set_sched_if_idle_locked(gt, false); + result = result ?: err; + err = xe_gt_sriov_pf_config_set_exec_quantum_locked(gt, PFID, 0); + result = result ?: err; + err = xe_gt_sriov_pf_config_set_preempt_timeout_locked(gt, PFID, 0); + result = result ?: err; + } + + return result; +} + +/** + * xe_sriov_pf_reprovision_default() - Reprovision default PF in auto-mode. + * @xe: the PF &xe_device + * + * This function can only be called on PF. + * + * Return: 0 on success or a negative error code on failure. + */ +int xe_sriov_pf_reprovision_default(struct xe_device *xe) +{ + xe_assert(xe, IS_SRIOV_PF(xe)); + + if (!pf_auto_provisioning_mode(xe)) + return 0; + + return pf_reprovision_default(xe); +} + /** * xe_sriov_pf_provision_set_mode() - Change VFs provision mode. * @xe: the PF &xe_device diff --git a/drivers/gpu/drm/xe/xe_sriov_pf_provision.h b/drivers/gpu/drm/xe/xe_sriov_pf_provision.h index f26f49539697..b15e4d7ad940 100644 --- a/drivers/gpu/drm/xe/xe_sriov_pf_provision.h +++ b/drivers/gpu/drm/xe/xe_sriov_pf_provision.h @@ -30,6 +30,7 @@ int xe_sriov_pf_provision_query_vf_vram(struct xe_device *xe, unsigned int vfid, int xe_sriov_pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs); int xe_sriov_pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs); +int xe_sriov_pf_reprovision_default(struct xe_device *xe); int xe_sriov_pf_provision_set_mode(struct xe_device *xe, enum xe_sriov_provisioning_mode mode); From 67a5fb1f9ada7c3d8b7f571be86554968084a4b9 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 2 Apr 2026 21:17:24 +0200 Subject: [PATCH 058/120] drm/xe/pf: Extract helper to show which VFs are provisioned MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In upcoming patches we will want to show which VFs were already provisioned with resources other than LMEM(VRAM). Convert code from the LMEM reporting function into a more generic helper that can handle both u32 and u64 resources and can report also PF. Signed-off-by: Michal Wajdeczko Reviewed-by: Piotr Piórkowski Link: https://patch.msgid.link/20260402191726.4932-12-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 30 +++++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index abc6b5e22048..2eda63b69b4e 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -1934,29 +1934,45 @@ static u64 pf_profile_fair_lmem(struct xe_gt *gt, unsigned int num_vfs) return ALIGN_DOWN(fair, alignment); } -static void __pf_show_provisioning_lmem(struct xe_gt *gt, unsigned int first_vf, - unsigned int num_vfs, bool provisioned) +static void __pf_show_provisioned(struct xe_gt *gt, unsigned int first_vf, + unsigned int num_vfs, bool provisioned, + u32 (*get32)(struct xe_gt *, unsigned int), + u64 (*get64)(struct xe_gt *, unsigned int), + const char *what) { unsigned int allvfs = 1 + xe_gt_sriov_pf_get_totalvfs(gt); /* PF plus VFs */ unsigned long *bitmap __free(bitmap) = bitmap_zalloc(allvfs, GFP_KERNEL); unsigned int weight; unsigned int n; + bool pf; + + xe_gt_assert(gt, get32 || get64); if (!bitmap) return; for (n = first_vf; n < first_vf + num_vfs; n++) { - if (!!pf_get_vf_config_lmem(gt, VFID(n)) == provisioned) + if ((get32 && (!!get32(gt, VFID(n)) == provisioned)) || + (get64 && (!!get64(gt, VFID(n)) == provisioned))) bitmap_set(bitmap, n, 1); } + pf = test_and_clear_bit(0, bitmap); weight = bitmap_weight(bitmap, allvfs); - if (!weight) + if (!pf && !weight) return; - xe_gt_sriov_info(gt, "VF%s%*pbl %s provisioned with VRAM\n", - weight > 1 ? "s " : "", allvfs, bitmap, - provisioned ? "already" : "not"); + xe_gt_sriov_info(gt, "%s%s%s%s%*pbl %s provisioned with %s\n", + pf ? "PF" : "", pf && weight ? " and " : "", + weight ? "VF" : "", weight > 1 ? "s " : "", + allvfs, bitmap, provisioned ? "already" : "not", what); +} + +static void __pf_show_provisioning_lmem(struct xe_gt *gt, unsigned int first_vf, + unsigned int num_vfs, bool provisioned) +{ + __pf_show_provisioned(gt, first_vf, num_vfs, provisioned, + NULL, pf_get_vf_config_lmem, "VRAM"); } static void pf_show_all_provisioned_lmem(struct xe_gt *gt) From 4f91e3a5b79f3962acff8038dfb89394496faa7d Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 2 Apr 2026 21:17:25 +0200 Subject: [PATCH 059/120] drm/xe/pf: Extract helpers for bulk EQ/PT provisioning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already have functions to bulk provision execution quantum and preemption timeout, but they are applying changes to all possible VFs, while in upcoming patch we would like to provision only subset of available VFs. Signed-off-by: Michal Wajdeczko Reviewed-by: Piotr Piórkowski Link: https://patch.msgid.link/20260402191726.4932-13-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 66 +++++++++++++--------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index 2eda63b69b4e..d02c96d3041a 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -2193,6 +2193,25 @@ u32 xe_gt_sriov_pf_config_get_exec_quantum(struct xe_gt *gt, unsigned int vfid) return pf_get_exec_quantum(gt, vfid); } +static int pf_bulk_set_exec_quantum(struct xe_gt *gt, u32 exec_quantum, + unsigned int first_vf, unsigned int num_vfs) +{ + unsigned int n; + int err = 0; + + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); + + for (n = first_vf; n < first_vf + num_vfs; n++) { + err = pf_provision_exec_quantum(gt, VFID(n), exec_quantum); + if (err) + break; + } + + return pf_config_bulk_set_u32_done(gt, first_vf, num_vfs, exec_quantum, + pf_get_exec_quantum, "execution quantum", + exec_quantum_unit, n, err); +} + /** * xe_gt_sriov_pf_config_bulk_set_exec_quantum_locked() - Configure EQ for PF and VFs. * @gt: the &xe_gt to configure @@ -2205,20 +2224,8 @@ u32 xe_gt_sriov_pf_config_get_exec_quantum(struct xe_gt *gt, unsigned int vfid) int xe_gt_sriov_pf_config_bulk_set_exec_quantum_locked(struct xe_gt *gt, u32 exec_quantum) { unsigned int totalvfs = xe_gt_sriov_pf_get_totalvfs(gt); - unsigned int n; - int err = 0; - lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); - - for (n = 0; n <= totalvfs; n++) { - err = pf_provision_exec_quantum(gt, VFID(n), exec_quantum); - if (err) - break; - } - - return pf_config_bulk_set_u32_done(gt, 0, 1 + totalvfs, exec_quantum, - pf_get_exec_quantum, "execution quantum", - exec_quantum_unit, n, err); + return pf_bulk_set_exec_quantum(gt, exec_quantum, PFID, 1 + totalvfs); } static int pf_provision_groups_exec_quantums(struct xe_gt *gt, unsigned int vfid, @@ -2418,6 +2425,25 @@ u32 xe_gt_sriov_pf_config_get_preempt_timeout(struct xe_gt *gt, unsigned int vfi return pf_get_preempt_timeout(gt, vfid); } +static int pf_bulk_set_preempt_timeout(struct xe_gt *gt, u32 preempt_timeout, + unsigned int first_vf, unsigned int num_vfs) +{ + unsigned int n; + int err = 0; + + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); + + for (n = first_vf; n < first_vf + num_vfs; n++) { + err = pf_provision_preempt_timeout(gt, VFID(n), preempt_timeout); + if (err) + break; + } + + return pf_config_bulk_set_u32_done(gt, first_vf, num_vfs, preempt_timeout, + pf_get_preempt_timeout, "preemption timeout", + preempt_timeout_unit, n, err); +} + /** * xe_gt_sriov_pf_config_bulk_set_preempt_timeout_locked() - Configure PT for PF and VFs. * @gt: the &xe_gt to configure @@ -2430,20 +2456,8 @@ u32 xe_gt_sriov_pf_config_get_preempt_timeout(struct xe_gt *gt, unsigned int vfi int xe_gt_sriov_pf_config_bulk_set_preempt_timeout_locked(struct xe_gt *gt, u32 preempt_timeout) { unsigned int totalvfs = xe_gt_sriov_pf_get_totalvfs(gt); - unsigned int n; - int err = 0; - lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); - - for (n = 0; n <= totalvfs; n++) { - err = pf_provision_preempt_timeout(gt, VFID(n), preempt_timeout); - if (err) - break; - } - - return pf_config_bulk_set_u32_done(gt, 0, 1 + totalvfs, preempt_timeout, - pf_get_preempt_timeout, "preemption timeout", - preempt_timeout_unit, n, err); + return pf_bulk_set_preempt_timeout(gt, preempt_timeout, PFID, 1 + totalvfs); } static int pf_provision_groups_preempt_timeouts(struct xe_gt *gt, unsigned int vfid, From afc480ff55c5244f3a1941096f232b57c354cc68 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 2 Apr 2026 21:17:26 +0200 Subject: [PATCH 060/120] drm/xe/pf: Perform fair scheduling auto-provisioning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Default VF scheduling configuration is the same as for the PF and includes unlimited execution quantum (EQ) and unlimited preemption timeout (PT). While this setup gives the most flexibility it does not protect the PF or VFs from other VF that could constantly submit workloads without any gaps that would let GuC do a VF-switch. To avoid that, do some trivial auto-provisioning and configure PF and all VFs with 16ms EQ and PT. This setup should allow GuC to perform a full round-robin with up to 63 VFs within 2s, which in turn should match expectations from most of the VMs using VFs. Signed-off-by: Michal Wajdeczko Reviewed-by: Piotr Piórkowski #v1 Reviewed-by: Michał Winiarski Link: https://patch.msgid.link/20260402191726.4932-14-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 91 ++++++++++++++++++++++ drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h | 1 + drivers/gpu/drm/xe/xe_sriov_pf_provision.c | 2 + 3 files changed, 94 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index d02c96d3041a..e112aa148dab 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -2662,6 +2662,97 @@ static bool pf_non_default_sched(struct xe_gt *gt, unsigned int vfid) custom_sched_priority(gt, pf_get_sched_priority(gt, vfid)); } +static void __pf_show_provisioned_sched(struct xe_gt *gt, unsigned int first_vf, + unsigned int num_vfs, bool provisioned) +{ + __pf_show_provisioned(gt, first_vf, num_vfs, provisioned, + pf_get_exec_quantum, NULL, "EQ"); + __pf_show_provisioned(gt, first_vf, num_vfs, provisioned, + pf_get_preempt_timeout, NULL, "PT"); + + /* we only care about non-default priorities */ + if (provisioned) + __pf_show_provisioned(gt, first_vf, num_vfs, true, + pf_get_sched_priority, NULL, "PRIORITY"); +} + +static void pf_show_all_provisioned_sched(struct xe_gt *gt) +{ + __pf_show_provisioned_sched(gt, PFID, 1 + xe_gt_sriov_pf_get_totalvfs(gt), true); +} + +static void pf_show_unprovisioned_sched(struct xe_gt *gt, unsigned int num_vfs) +{ + __pf_show_provisioned_sched(gt, PFID, 1 + num_vfs, false); +} + +static bool pf_needs_provision_sched(struct xe_gt *gt, unsigned int num_vfs) +{ + unsigned int vfid; + + for (vfid = PFID; vfid <= PFID + num_vfs; vfid++) { + if (pf_non_default_sched(gt, vfid)) { + pf_show_all_provisioned_sched(gt); + pf_show_unprovisioned_sched(gt, num_vfs); + return false; + } + } + + if (xe_gt_sriov_pf_policy_get_sched_if_idle_locked(gt)) { + pf_show_all_provisioned_sched(gt); + pf_show_unprovisioned_sched(gt, num_vfs); + return false; + } + + pf_show_all_provisioned_sched(gt); + return true; +} + +/* With 16ms EQ/PT GuC should be able to handle up to 63 VFs within 2s */ +#define XE_FAIR_EXEC_QUANTUM_MS 16 +#define XE_FAIR_PREEMPT_TIMEOUT_US 16000 +#define XE_FAIR_SCHED_PRIORITY GUC_SCHED_PRIORITY_LOW +#define XE_ADMIN_PF_SCHED_PRIORITY GUC_SCHED_PRIORITY_HIGH + +/** + * xe_gt_sriov_pf_config_set_fair_sched() - Provision PF and VFs with fair scheduling. + * @gt: the &xe_gt + * @num_vfs: number of VFs to provision (can't be 0) + * + * This function can only be called on PF. + * + * Return: 0 on success or a negative error code on failure. + */ +int xe_gt_sriov_pf_config_set_fair_sched(struct xe_gt *gt, unsigned int num_vfs) +{ + int result = 0; + int err; + + xe_gt_assert(gt, num_vfs); + xe_gt_assert(gt, XE_FAIR_EXEC_QUANTUM_MS); + xe_gt_assert(gt, XE_FAIR_PREEMPT_TIMEOUT_US); + + guard(mutex)(xe_gt_sriov_pf_master_mutex(gt)); + + if (!pf_needs_provision_sched(gt, num_vfs)) + return 0; + + err = pf_bulk_set_exec_quantum(gt, XE_FAIR_EXEC_QUANTUM_MS, PFID, 1 + num_vfs); + result = result ?: err; + err = pf_bulk_set_preempt_timeout(gt, XE_FAIR_PREEMPT_TIMEOUT_US, PFID, 1 + num_vfs); + result = result ?: err; + + xe_gt_assert(gt, XE_FAIR_SCHED_PRIORITY == GUC_SCHED_PRIORITY_LOW); + xe_gt_assert(gt, !xe_gt_sriov_pf_policy_get_sched_if_idle_locked(gt)); + + if (xe_sriov_pf_admin_only(gt_to_xe(gt))) { + err = pf_provision_sched_priority(gt, PFID, XE_ADMIN_PF_SCHED_PRIORITY); + result = result ?: err; + } + + return result; +} + static int pf_provision_threshold(struct xe_gt *gt, unsigned int vfid, enum xe_guc_klv_threshold_index index, u32 value) { diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h index e9314f0a9b4e..2ec62c12ad5c 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h @@ -78,6 +78,7 @@ u32 xe_gt_sriov_pf_config_get_threshold(struct xe_gt *gt, unsigned int vfid, int xe_gt_sriov_pf_config_set_threshold(struct xe_gt *gt, unsigned int vfid, enum xe_guc_klv_threshold_index index, u32 value); +int xe_gt_sriov_pf_config_set_fair_sched(struct xe_gt *gt, unsigned int num_vfs); int xe_gt_sriov_pf_config_set_fair(struct xe_gt *gt, unsigned int vfid, unsigned int num_vfs); int xe_gt_sriov_pf_config_sanitize(struct xe_gt *gt, unsigned int vfid, long timeout); int xe_gt_sriov_pf_config_release(struct xe_gt *gt, unsigned int vfid, bool force); diff --git a/drivers/gpu/drm/xe/xe_sriov_pf_provision.c b/drivers/gpu/drm/xe/xe_sriov_pf_provision.c index e11874d689fa..0ec7ea83f12a 100644 --- a/drivers/gpu/drm/xe/xe_sriov_pf_provision.c +++ b/drivers/gpu/drm/xe/xe_sriov_pf_provision.c @@ -41,6 +41,8 @@ static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs) int err; for_each_gt(gt, xe, id) { + err = xe_gt_sriov_pf_config_set_fair_sched(gt, num_vfs); + result = result ?: err; err = xe_gt_sriov_pf_config_set_fair(gt, VFID(1), num_vfs); result = result ?: err; } From 288b775a1cd4c569ec3ffba2f4d0b13b117e8be4 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 10 Apr 2026 15:50:28 -0700 Subject: [PATCH 061/120] drm/xe/tuning: Stop applying CCCHKNREG1 tuning from Xe3p onward Whereas the tuning guide gave guidance on adjusting various CCCHKNREG1 on past platforms, starting from Xe3p the guidance is "Leave register at HW default settings." Set a version range upper bound of "34.99" so that the current programming will stop being applied on any Xe3p platforms that have graphics version 35. Bspec: 72161 Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20260410-xe3p_tuning-v1-1-e206a62ee38f@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_tuning.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_tuning.c b/drivers/gpu/drm/xe/xe_tuning.c index f8de6a4bf189..ea48e2a60fcd 100644 --- a/drivers/gpu/drm/xe/xe_tuning.c +++ b/drivers/gpu/drm/xe/xe_tuning.c @@ -43,7 +43,7 @@ static const struct xe_rtp_entry_sr gt_tunings[] = { REG_FIELD_PREP(L3_PWM_TIMER_INIT_VAL_MASK, 0x7f))) }, { XE_RTP_NAME("Tuning: Compression Overfetch"), - XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, XE_RTP_END_VERSION_UNDEFINED), + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 3499), FUNC(xe_rtp_match_has_flat_ccs)), XE_RTP_ACTIONS(CLR(CCCHKNREG1, ENCOMPPERFFIX), SET(CCCHKNREG1, L3CMPCTRL)) From 0b1676eafdd1ba5a5436bdca0d2a25ce56699783 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 10 Apr 2026 15:50:29 -0700 Subject: [PATCH 062/120] drm/xe/tuning: Use proper register offset for GAMSTLB_CTRL From Xe2 onward (i.e., all platforms officially supported by the Xe driver), the GAMSTLB_CTRL register is located at offset 0x477C and represented by the macro "GAMSTLB_CTRL" in code. However the register formerly resided at offset 0xCF4C on Xe1-era platforms, and we also have macro XEHP_GAMSTLB_CTRL that represents this old offset in the unofficial/developer-only Xe1 code. When tuning for the register was added for Xe3p_LPG, the old Xe1-era macro was accidentally used instead of the proper macro for Xe2 and beyond, causing the tuning to not be applied properly. Use the proper definition so that the correct offset is written to. Bspec: 59298 Fixes: 377c89bfaa5d ("drm/xe/xe3p_lpg: Set STLB bank hash mode to 4KB") Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20260410-xe3p_tuning-v1-2-e206a62ee38f@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_tuning.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_tuning.c b/drivers/gpu/drm/xe/xe_tuning.c index ea48e2a60fcd..6fb8887d1482 100644 --- a/drivers/gpu/drm/xe/xe_tuning.c +++ b/drivers/gpu/drm/xe/xe_tuning.c @@ -97,7 +97,7 @@ static const struct xe_rtp_entry_sr gt_tunings[] = { { XE_RTP_NAME("Tuning: Set STLB Bank Hash Mode to 4KB"), XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3510, XE_RTP_END_VERSION_UNDEFINED), IS_INTEGRATED), - XE_RTP_ACTIONS(FIELD_SET(XEHP_GAMSTLB_CTRL, BANK_HASH_MODE, + XE_RTP_ACTIONS(FIELD_SET(GAMSTLB_CTRL, BANK_HASH_MODE, BANK_HASH_4KB_MODE)) }, }; From cd84bfbba7feb4c1e72356f14de026dfda1a9e2a Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 10 Apr 2026 15:50:30 -0700 Subject: [PATCH 063/120] drm/xe: Mark ROW_CHICKEN5 as a masked register ROW_CHICKEN5 is a masked register (i.e., to adjust the value of any of the lower 16 bits, the corresponding bit in the upper 16 bits must also be set). Add the XE_REG_OPTION_MASKED to its definition; failure to do so will cause workaround updates of this register to not apply properly. Bspec: 56853 Fixes: 835cd6cbb0d0 ("drm/xe/xe3p_lpg: Add initial workarounds for graphics version 35.10") Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20260410-xe3p_tuning-v1-3-e206a62ee38f@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/regs/xe_gt_regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h index aa267c2f6162..a4472b7acb18 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -584,7 +584,7 @@ #define DISABLE_128B_EVICTION_COMMAND_UDW REG_BIT(36 - 32) #define LSCFE_SAME_ADDRESS_ATOMICS_COALESCING_DISABLE REG_BIT(35 - 32) -#define ROW_CHICKEN5 XE_REG_MCR(0xe7f0) +#define ROW_CHICKEN5 XE_REG_MCR(0xe7f0, XE_REG_OPTION_MASKED) #define CPSS_AWARE_DIS REG_BIT(3) #define SARB_CHICKEN1 XE_REG_MCR(0xe90c) From 1a2a722ff96749734a5585dfe7f0bea7719caa8b Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Wed, 8 Apr 2026 15:27:44 -0700 Subject: [PATCH 064/120] drm/xe/debugfs: Correct printing of register whitelist ranges The register-save-restore debugfs prints whitelist entries as offset ranges. E.g., REG[0x39319c-0x39319f]: allow read access for a single dword-sized register. However the GENMASK value used to set the lower bits to '1' for the upper bound of the whitelist range incorrectly included one more bit than it should have, causing the whitelist ranges to sometimes appear twice as large as they really were. For example, REG[0x6210-0x6217]: allow rw access was also intended to be a single dword-sized register whitelist (with a range 0x6210-0x6213) but was printed incorrectly as a qword-sized range because one too many bits was flipped on. Similar 'off by one' logic was applied when printing 4-dword register ranges and 64-dword register ranges as well. Correct the GENMASK logic to print these ranges in debugfs correctly. No impact outside of correcting the misleading debugfs output. Fixes: d855d2246ea6 ("drm/xe: Print whitelist while applying") Reviewed-by: Stuart Summers Link: https://patch.msgid.link/20260408-regsr_wl_range-v1-1-e9a28c8b4264@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_reg_whitelist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_reg_whitelist.c b/drivers/gpu/drm/xe/xe_reg_whitelist.c index 80577e4b7437..8cc313182968 100644 --- a/drivers/gpu/drm/xe/xe_reg_whitelist.c +++ b/drivers/gpu/drm/xe/xe_reg_whitelist.c @@ -226,7 +226,7 @@ void xe_reg_whitelist_print_entry(struct drm_printer *p, unsigned int indent, } range_start = reg & REG_GENMASK(25, range_bit); - range_end = range_start | REG_GENMASK(range_bit, 0); + range_end = range_start | REG_GENMASK(range_bit - 1, 0); switch (val & RING_FORCE_TO_NONPRIV_ACCESS_MASK) { case RING_FORCE_TO_NONPRIV_ACCESS_RW: From 1ce3229f8f269a245ff3b8c65ffae36b4d6afb93 Mon Sep 17 00:00:00 2001 From: Satyanarayana K V P Date: Wed, 8 Apr 2026 11:01:47 +0000 Subject: [PATCH 065/120] drm/xe: Add memory pool with shadow support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a memory pool to allocate sub-ranges from a BO-backed pool using drm_mm. Signed-off-by: Satyanarayana K V P Cc: Matthew Brost Cc: Thomas Hellström Cc: Maarten Lankhorst Cc: Michal Wajdeczko Reviewed-by: Matthew Brost Signed-off-by: Matthew Brost Link: https://patch.msgid.link/20260408110145.1639937-5-satyanarayana.k.v.p@intel.com --- drivers/gpu/drm/xe/Makefile | 1 + drivers/gpu/drm/xe/xe_mem_pool.c | 403 +++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_mem_pool.h | 35 +++ drivers/gpu/drm/xe/xe_mem_pool_types.h | 21 ++ 4 files changed, 460 insertions(+) create mode 100644 drivers/gpu/drm/xe/xe_mem_pool.c create mode 100644 drivers/gpu/drm/xe/xe_mem_pool.h create mode 100644 drivers/gpu/drm/xe/xe_mem_pool_types.h diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 9dacb0579a7d..8e31b14239ec 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -88,6 +88,7 @@ xe-y += xe_bb.o \ xe_irq.o \ xe_late_bind_fw.o \ xe_lrc.o \ + xe_mem_pool.o \ xe_migrate.o \ xe_mmio.o \ xe_mmio_gem.o \ diff --git a/drivers/gpu/drm/xe/xe_mem_pool.c b/drivers/gpu/drm/xe/xe_mem_pool.c new file mode 100644 index 000000000000..d5e24d6aa88d --- /dev/null +++ b/drivers/gpu/drm/xe/xe_mem_pool.c @@ -0,0 +1,403 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2026 Intel Corporation + */ + +#include + +#include + +#include "instructions/xe_mi_commands.h" +#include "xe_bo.h" +#include "xe_device_types.h" +#include "xe_map.h" +#include "xe_mem_pool.h" +#include "xe_mem_pool_types.h" +#include "xe_tile_printk.h" + +/** + * struct xe_mem_pool - DRM MM pool for sub-allocating memory from a BO on an + * XE tile. + * + * The XE memory pool is a DRM MM manager that provides sub-allocation of memory + * from a backing buffer object (BO) on a specific XE tile. It is designed to + * manage memory for GPU workloads, allowing for efficient allocation and + * deallocation of memory regions within the BO. + * + * The memory pool maintains a primary BO that is pinned in the GGTT and mapped + * into the CPU address space for direct access. Optionally, it can also maintain + * a shadow BO that can be used for atomic updates to the primary BO's contents. + * + * The API provided by the memory pool allows clients to allocate and free memory + * regions, retrieve GPU and CPU addresses, and synchronize data between the + * primary and shadow BOs as needed. + */ +struct xe_mem_pool { + /** @base: Range allocator over [0, @size) in bytes */ + struct drm_mm base; + /** @bo: Active pool BO (GGTT-pinned, CPU-mapped). */ + struct xe_bo *bo; + /** @shadow: Shadow BO for atomic command updates. */ + struct xe_bo *shadow; + /** @swap_guard: Timeline guard updating @bo and @shadow */ + struct mutex swap_guard; + /** @cpu_addr: CPU virtual address of the active BO. */ + void *cpu_addr; + /** @is_iomem: Indicates if the BO mapping is I/O memory. */ + bool is_iomem; +}; + +static struct xe_mem_pool *node_to_pool(struct xe_mem_pool_node *node) +{ + return container_of(node->sa_node.mm, struct xe_mem_pool, base); +} + +static struct xe_tile *pool_to_tile(struct xe_mem_pool *pool) +{ + return pool->bo->tile; +} + +static void fini_pool_action(struct drm_device *drm, void *arg) +{ + struct xe_mem_pool *pool = arg; + + if (pool->is_iomem) + kvfree(pool->cpu_addr); + + drm_mm_takedown(&pool->base); +} + +static int pool_shadow_init(struct xe_mem_pool *pool) +{ + struct xe_tile *tile = pool->bo->tile; + struct xe_device *xe = tile_to_xe(tile); + struct xe_bo *shadow; + int ret; + + xe_assert(xe, !pool->shadow); + + ret = drmm_mutex_init(&xe->drm, &pool->swap_guard); + if (ret) + return ret; + + if (IS_ENABLED(CONFIG_PROVE_LOCKING)) { + fs_reclaim_acquire(GFP_KERNEL); + might_lock(&pool->swap_guard); + fs_reclaim_release(GFP_KERNEL); + } + shadow = xe_managed_bo_create_pin_map(xe, tile, + xe_bo_size(pool->bo), + XE_BO_FLAG_VRAM_IF_DGFX(tile) | + XE_BO_FLAG_GGTT | + XE_BO_FLAG_GGTT_INVALIDATE | + XE_BO_FLAG_PINNED_NORESTORE); + if (IS_ERR(shadow)) + return PTR_ERR(shadow); + + pool->shadow = shadow; + + return 0; +} + +/** + * xe_mem_pool_init() - Initialize memory pool. + * @tile: the &xe_tile where allocate. + * @size: number of bytes to allocate. + * @guard: the size of the guard region at the end of the BO that is not + * sub-allocated, in bytes. + * @flags: flags to use to create shadow pool. + * + * Initializes a memory pool for sub-allocating memory from a backing BO on the + * specified XE tile. The backing BO is pinned in the GGTT and mapped into + * the CPU address space for direct access. Optionally, a shadow BO can also be + * initialized for atomic updates to the primary BO's contents. + * + * Returns: a pointer to the &xe_mem_pool, or an error pointer on failure. + */ +struct xe_mem_pool *xe_mem_pool_init(struct xe_tile *tile, u32 size, + u32 guard, int flags) +{ + struct xe_device *xe = tile_to_xe(tile); + struct xe_mem_pool *pool; + struct xe_bo *bo; + u32 managed_size; + int ret; + + xe_tile_assert(tile, size > guard); + managed_size = size - guard; + + pool = drmm_kzalloc(&xe->drm, sizeof(*pool), GFP_KERNEL); + if (!pool) + return ERR_PTR(-ENOMEM); + + bo = xe_managed_bo_create_pin_map(xe, tile, size, + XE_BO_FLAG_VRAM_IF_DGFX(tile) | + XE_BO_FLAG_GGTT | + XE_BO_FLAG_GGTT_INVALIDATE | + XE_BO_FLAG_PINNED_NORESTORE); + if (IS_ERR(bo)) { + xe_tile_err(tile, "Failed to prepare %uKiB BO for mem pool (%pe)\n", + size / SZ_1K, bo); + return ERR_CAST(bo); + } + pool->bo = bo; + pool->is_iomem = bo->vmap.is_iomem; + + if (pool->is_iomem) { + pool->cpu_addr = kvzalloc(size, GFP_KERNEL); + if (!pool->cpu_addr) + return ERR_PTR(-ENOMEM); + } else { + pool->cpu_addr = bo->vmap.vaddr; + } + + if (flags & XE_MEM_POOL_BO_FLAG_INIT_SHADOW_COPY) { + ret = pool_shadow_init(pool); + + if (ret) + goto out_err; + } + + drm_mm_init(&pool->base, 0, managed_size); + ret = drmm_add_action_or_reset(&xe->drm, fini_pool_action, pool); + if (ret) + return ERR_PTR(ret); + + return pool; + +out_err: + if (flags & XE_MEM_POOL_BO_FLAG_INIT_SHADOW_COPY) + xe_tile_err(tile, + "Failed to initialize shadow BO for mem pool (%d)\n", ret); + if (bo->vmap.is_iomem) + kvfree(pool->cpu_addr); + return ERR_PTR(ret); +} + +/** + * xe_mem_pool_sync() - Copy the entire contents of the main pool to shadow pool. + * @pool: the memory pool containing the primary and shadow BOs. + * + * Copies the entire contents of the primary pool to the shadow pool. This must + * be done after xe_mem_pool_init() with the XE_MEM_POOL_BO_FLAG_INIT_SHADOW_COPY + * flag to ensure that the shadow pool has the same initial contents as the primary + * pool. After this initial synchronization, clients can choose to synchronize the + * shadow pool with the primary pool on a node basis using + * xe_mem_pool_sync_shadow_locked() as needed. + * + * Return: None. + */ +void xe_mem_pool_sync(struct xe_mem_pool *pool) +{ + struct xe_tile *tile = pool_to_tile(pool); + struct xe_device *xe = tile_to_xe(tile); + + xe_tile_assert(tile, pool->shadow); + + xe_map_memcpy_to(xe, &pool->shadow->vmap, 0, + pool->cpu_addr, xe_bo_size(pool->bo)); +} + +/** + * xe_mem_pool_swap_shadow_locked() - Swap the primary BO with the shadow BO. + * @pool: the memory pool containing the primary and shadow BOs. + * + * Swaps the primary buffer object with the shadow buffer object in the mem + * pool. This allows for atomic updates to the contents of the primary BO + * by first writing to the shadow BO and then swapping it with the primary BO. + * Swap_guard must be held to ensure synchronization with any concurrent swap + * operations. + * + * Return: None. + */ +void xe_mem_pool_swap_shadow_locked(struct xe_mem_pool *pool) +{ + struct xe_tile *tile = pool_to_tile(pool); + + xe_tile_assert(tile, pool->shadow); + lockdep_assert_held(&pool->swap_guard); + + swap(pool->bo, pool->shadow); + if (!pool->bo->vmap.is_iomem) + pool->cpu_addr = pool->bo->vmap.vaddr; +} + +/** + * xe_mem_pool_sync_shadow_locked() - Copy node from primary pool to shadow pool. + * @node: the node allocated in the memory pool. + * + * Copies the specified batch buffer from the primary pool to the shadow pool. + * Swap_guard must be held to ensure synchronization with any concurrent swap + * operations. + * + * Return: None. + */ +void xe_mem_pool_sync_shadow_locked(struct xe_mem_pool_node *node) +{ + struct xe_mem_pool *pool = node_to_pool(node); + struct xe_tile *tile = pool_to_tile(pool); + struct xe_device *xe = tile_to_xe(tile); + struct drm_mm_node *sa_node = &node->sa_node; + + xe_tile_assert(tile, pool->shadow); + lockdep_assert_held(&pool->swap_guard); + + xe_map_memcpy_to(xe, &pool->shadow->vmap, + sa_node->start, + pool->cpu_addr + sa_node->start, + sa_node->size); +} + +/** + * xe_mem_pool_gpu_addr() - Retrieve GPU address of memory pool. + * @pool: the memory pool + * + * Returns: GGTT address of the memory pool. + */ +u64 xe_mem_pool_gpu_addr(struct xe_mem_pool *pool) +{ + return xe_bo_ggtt_addr(pool->bo); +} + +/** + * xe_mem_pool_cpu_addr() - Retrieve CPU address of manager pool. + * @pool: the memory pool + * + * Returns: CPU virtual address of memory pool. + */ +void *xe_mem_pool_cpu_addr(struct xe_mem_pool *pool) +{ + return pool->cpu_addr; +} + +/** + * xe_mem_pool_bo_swap_guard() - Retrieve the mutex used to guard swap + * operations on a memory pool. + * @pool: the memory pool + * + * Returns: Swap guard mutex or NULL if shadow pool is not created. + */ +struct mutex *xe_mem_pool_bo_swap_guard(struct xe_mem_pool *pool) +{ + if (!pool->shadow) + return NULL; + + return &pool->swap_guard; +} + +/** + * xe_mem_pool_bo_flush_write() - Copy the data from the sub-allocation + * to the GPU memory. + * @node: the node allocated in the memory pool to flush. + */ +void xe_mem_pool_bo_flush_write(struct xe_mem_pool_node *node) +{ + struct xe_mem_pool *pool = node_to_pool(node); + struct xe_tile *tile = pool_to_tile(pool); + struct xe_device *xe = tile_to_xe(tile); + struct drm_mm_node *sa_node = &node->sa_node; + + if (!pool->bo->vmap.is_iomem) + return; + + xe_map_memcpy_to(xe, &pool->bo->vmap, sa_node->start, + pool->cpu_addr + sa_node->start, + sa_node->size); +} + +/** + * xe_mem_pool_bo_sync_read() - Copy the data from GPU memory to the + * sub-allocation. + * @node: the node allocated in the memory pool to read back. + */ +void xe_mem_pool_bo_sync_read(struct xe_mem_pool_node *node) +{ + struct xe_mem_pool *pool = node_to_pool(node); + struct xe_tile *tile = pool_to_tile(pool); + struct xe_device *xe = tile_to_xe(tile); + struct drm_mm_node *sa_node = &node->sa_node; + + if (!pool->bo->vmap.is_iomem) + return; + + xe_map_memcpy_from(xe, pool->cpu_addr + sa_node->start, + &pool->bo->vmap, sa_node->start, sa_node->size); +} + +/** + * xe_mem_pool_alloc_node() - Allocate a new node for use with xe_mem_pool. + * + * Returns: node structure or an ERR_PTR(-ENOMEM). + */ +struct xe_mem_pool_node *xe_mem_pool_alloc_node(void) +{ + struct xe_mem_pool_node *node = kzalloc_obj(*node); + + if (!node) + return ERR_PTR(-ENOMEM); + + return node; +} + +/** + * xe_mem_pool_insert_node() - Insert a node into the memory pool. + * @pool: the memory pool to insert into + * @node: the node to insert + * @size: the size of the node to be allocated in bytes. + * + * Inserts a node into the specified memory pool using drm_mm for + * allocation. + * + * Returns: 0 on success or a negative error code on failure. + */ +int xe_mem_pool_insert_node(struct xe_mem_pool *pool, + struct xe_mem_pool_node *node, u32 size) +{ + if (!pool) + return -EINVAL; + + return drm_mm_insert_node(&pool->base, &node->sa_node, size); +} + +/** + * xe_mem_pool_free_node() - Free a node allocated from the memory pool. + * @node: the node to free + * + * Returns: None. + */ +void xe_mem_pool_free_node(struct xe_mem_pool_node *node) +{ + if (!node) + return; + + drm_mm_remove_node(&node->sa_node); + kfree(node); +} + +/** + * xe_mem_pool_node_cpu_addr() - Retrieve CPU address of the node. + * @node: the node allocated in the memory pool + * + * Returns: CPU virtual address of the node. + */ +void *xe_mem_pool_node_cpu_addr(struct xe_mem_pool_node *node) +{ + struct xe_mem_pool *pool = node_to_pool(node); + + return xe_mem_pool_cpu_addr(pool) + node->sa_node.start; +} + +/** + * xe_mem_pool_dump() - Dump the state of the DRM MM manager for debugging. + * @pool: the memory pool info be dumped. + * @p: The DRM printer to use for output. + * + * Only the drm managed region is dumped, not the state of the BOs or any other + * pool information. + * + * Returns: None. + */ +void xe_mem_pool_dump(struct xe_mem_pool *pool, struct drm_printer *p) +{ + drm_mm_print(&pool->base, p); +} diff --git a/drivers/gpu/drm/xe/xe_mem_pool.h b/drivers/gpu/drm/xe/xe_mem_pool.h new file mode 100644 index 000000000000..89cd2555fe91 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_mem_pool.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ +#ifndef _XE_MEM_POOL_H_ +#define _XE_MEM_POOL_H_ + +#include +#include + +#include +#include "xe_mem_pool_types.h" + +struct drm_printer; +struct xe_mem_pool; +struct xe_tile; + +struct xe_mem_pool *xe_mem_pool_init(struct xe_tile *tile, u32 size, + u32 guard, int flags); +void xe_mem_pool_sync(struct xe_mem_pool *pool); +void xe_mem_pool_swap_shadow_locked(struct xe_mem_pool *pool); +void xe_mem_pool_sync_shadow_locked(struct xe_mem_pool_node *node); +u64 xe_mem_pool_gpu_addr(struct xe_mem_pool *pool); +void *xe_mem_pool_cpu_addr(struct xe_mem_pool *pool); +struct mutex *xe_mem_pool_bo_swap_guard(struct xe_mem_pool *pool); +void xe_mem_pool_bo_flush_write(struct xe_mem_pool_node *node); +void xe_mem_pool_bo_sync_read(struct xe_mem_pool_node *node); +struct xe_mem_pool_node *xe_mem_pool_alloc_node(void); +int xe_mem_pool_insert_node(struct xe_mem_pool *pool, + struct xe_mem_pool_node *node, u32 size); +void xe_mem_pool_free_node(struct xe_mem_pool_node *node); +void *xe_mem_pool_node_cpu_addr(struct xe_mem_pool_node *node); +void xe_mem_pool_dump(struct xe_mem_pool *pool, struct drm_printer *p); + +#endif diff --git a/drivers/gpu/drm/xe/xe_mem_pool_types.h b/drivers/gpu/drm/xe/xe_mem_pool_types.h new file mode 100644 index 000000000000..d5e926c93351 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_mem_pool_types.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_MEM_POOL_TYPES_H_ +#define _XE_MEM_POOL_TYPES_H_ + +#include + +#define XE_MEM_POOL_BO_FLAG_INIT_SHADOW_COPY BIT(0) + +/** + * struct xe_mem_pool_node - Sub-range allocations from mem pool. + */ +struct xe_mem_pool_node { + /** @sa_node: drm_mm_node for this allocation. */ + struct drm_mm_node sa_node; +}; + +#endif From 6c84b493012aeb05dec29c709377bf0e17ac6815 Mon Sep 17 00:00:00 2001 From: Satyanarayana K V P Date: Wed, 8 Apr 2026 11:01:48 +0000 Subject: [PATCH 066/120] drm/xe/vf: Use drm mm instead of drm sa for CCS read/write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The suballocator algorithm tracks a hole cursor at the last allocation and tries to allocate after it. This is optimized for fence-ordered progress, where older allocations are expected to become reusable first. In fence-enabled mode, that ordering assumption holds. In fence-disabled mode, allocations may be freed in arbitrary order, so limiting allocation to the current hole window can miss valid free space and fail allocations despite sufficient total space. Use DRM memory manager instead of sub-allocator to get rid of this issue as CCS read/write operations do not use fences. Fixes: 864690cf4dd6 ("drm/xe/vf: Attach and detach CCS copy commands with BO") Signed-off-by: Satyanarayana K V P Cc: Matthew Brost Cc: Thomas Hellström Cc: Maarten Lankhorst Cc: Michal Wajdeczko Reviewed-by: Matthew Brost Signed-off-by: Matthew Brost Link: https://patch.msgid.link/20260408110145.1639937-6-satyanarayana.k.v.p@intel.com --- drivers/gpu/drm/xe/xe_bo_types.h | 3 +- drivers/gpu/drm/xe/xe_migrate.c | 56 ++++++++++++---------- drivers/gpu/drm/xe/xe_sriov_vf_ccs.c | 54 +++++++++++---------- drivers/gpu/drm/xe/xe_sriov_vf_ccs_types.h | 5 +- 4 files changed, 63 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_bo_types.h b/drivers/gpu/drm/xe/xe_bo_types.h index ff8317bfc1ae..9d19940b8fc0 100644 --- a/drivers/gpu/drm/xe/xe_bo_types.h +++ b/drivers/gpu/drm/xe/xe_bo_types.h @@ -18,6 +18,7 @@ #include "xe_ggtt_types.h" struct xe_device; +struct xe_mem_pool_node; struct xe_vm; #define XE_BO_MAX_PLACEMENTS 3 @@ -88,7 +89,7 @@ struct xe_bo { bool ccs_cleared; /** @bb_ccs: BB instructions of CCS read/write. Valid only for VF */ - struct xe_bb *bb_ccs[XE_SRIOV_VF_CCS_CTX_COUNT]; + struct xe_mem_pool_node *bb_ccs[XE_SRIOV_VF_CCS_CTX_COUNT]; /** * @cpu_caching: CPU caching mode. Currently only used for userspace diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c index fc918b4fba54..5fdc89ed5256 100644 --- a/drivers/gpu/drm/xe/xe_migrate.c +++ b/drivers/gpu/drm/xe/xe_migrate.c @@ -29,6 +29,7 @@ #include "xe_hw_engine.h" #include "xe_lrc.h" #include "xe_map.h" +#include "xe_mem_pool.h" #include "xe_mocs.h" #include "xe_printk.h" #include "xe_pt.h" @@ -1166,11 +1167,12 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, u32 batch_size, batch_size_allocated; struct xe_device *xe = gt_to_xe(gt); struct xe_res_cursor src_it, ccs_it; + struct xe_mem_pool *bb_pool; struct xe_sriov_vf_ccs_ctx *ctx; - struct xe_sa_manager *bb_pool; u64 size = xe_bo_size(src_bo); - struct xe_bb *bb = NULL; + struct xe_mem_pool_node *bb; u64 src_L0, src_L0_ofs; + struct xe_bb xe_bb_tmp; u32 src_L0_pt; int err; @@ -1208,18 +1210,18 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, size -= src_L0; } - bb = xe_bb_alloc(gt); + bb = xe_mem_pool_alloc_node(); if (IS_ERR(bb)) return PTR_ERR(bb); bb_pool = ctx->mem.ccs_bb_pool; - scoped_guard(mutex, xe_sa_bo_swap_guard(bb_pool)) { - xe_sa_bo_swap_shadow(bb_pool); + scoped_guard(mutex, xe_mem_pool_bo_swap_guard(bb_pool)) { + xe_mem_pool_swap_shadow_locked(bb_pool); - err = xe_bb_init(bb, bb_pool, batch_size); + err = xe_mem_pool_insert_node(bb_pool, bb, batch_size * sizeof(u32)); if (err) { xe_gt_err(gt, "BB allocation failed.\n"); - xe_bb_free(bb, NULL); + kfree(bb); return err; } @@ -1227,6 +1229,7 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, size = xe_bo_size(src_bo); batch_size = 0; + xe_bb_tmp = (struct xe_bb){ .cs = xe_mem_pool_node_cpu_addr(bb), .len = 0 }; /* * Emit PTE and copy commands here. * The CCS copy command can only support limited size. If the size to be @@ -1255,24 +1258,27 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, xe_assert(xe, IS_ALIGNED(ccs_it.start, PAGE_SIZE)); batch_size += EMIT_COPY_CCS_DW; - emit_pte(m, bb, src_L0_pt, false, true, &src_it, src_L0, src); + emit_pte(m, &xe_bb_tmp, src_L0_pt, false, true, &src_it, src_L0, src); - emit_pte(m, bb, ccs_pt, false, false, &ccs_it, ccs_size, src); + emit_pte(m, &xe_bb_tmp, ccs_pt, false, false, &ccs_it, ccs_size, src); - bb->len = emit_flush_invalidate(bb->cs, bb->len, flush_flags); - flush_flags = xe_migrate_ccs_copy(m, bb, src_L0_ofs, src_is_pltt, + xe_bb_tmp.len = emit_flush_invalidate(xe_bb_tmp.cs, xe_bb_tmp.len, + flush_flags); + flush_flags = xe_migrate_ccs_copy(m, &xe_bb_tmp, src_L0_ofs, src_is_pltt, src_L0_ofs, dst_is_pltt, src_L0, ccs_ofs, true); - bb->len = emit_flush_invalidate(bb->cs, bb->len, flush_flags); + xe_bb_tmp.len = emit_flush_invalidate(xe_bb_tmp.cs, xe_bb_tmp.len, + flush_flags); size -= src_L0; } - xe_assert(xe, (batch_size_allocated == bb->len)); + xe_assert(xe, (batch_size_allocated == xe_bb_tmp.len)); + xe_assert(xe, bb->sa_node.size == xe_bb_tmp.len * sizeof(u32)); src_bo->bb_ccs[read_write] = bb; xe_sriov_vf_ccs_rw_update_bb_addr(ctx); - xe_sa_bo_sync_shadow(bb->bo); + xe_mem_pool_sync_shadow_locked(bb); } return 0; @@ -1297,10 +1303,10 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo, enum xe_sriov_vf_ccs_rw_ctxs read_write) { - struct xe_bb *bb = src_bo->bb_ccs[read_write]; + struct xe_mem_pool_node *bb = src_bo->bb_ccs[read_write]; struct xe_device *xe = xe_bo_device(src_bo); + struct xe_mem_pool *bb_pool; struct xe_sriov_vf_ccs_ctx *ctx; - struct xe_sa_manager *bb_pool; u32 *cs; xe_assert(xe, IS_SRIOV_VF(xe)); @@ -1308,17 +1314,17 @@ void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo, ctx = &xe->sriov.vf.ccs.contexts[read_write]; bb_pool = ctx->mem.ccs_bb_pool; - guard(mutex) (xe_sa_bo_swap_guard(bb_pool)); - xe_sa_bo_swap_shadow(bb_pool); + scoped_guard(mutex, xe_mem_pool_bo_swap_guard(bb_pool)) { + xe_mem_pool_swap_shadow_locked(bb_pool); - cs = xe_sa_bo_cpu_addr(bb->bo); - memset(cs, MI_NOOP, bb->len * sizeof(u32)); - xe_sriov_vf_ccs_rw_update_bb_addr(ctx); + cs = xe_mem_pool_node_cpu_addr(bb); + memset(cs, MI_NOOP, bb->sa_node.size); + xe_sriov_vf_ccs_rw_update_bb_addr(ctx); - xe_sa_bo_sync_shadow(bb->bo); - - xe_bb_free(bb, NULL); - src_bo->bb_ccs[read_write] = NULL; + xe_mem_pool_sync_shadow_locked(bb); + xe_mem_pool_free_node(bb); + src_bo->bb_ccs[read_write] = NULL; + } } /** diff --git a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c index db023fb66a27..09b99fb2608b 100644 --- a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c +++ b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c @@ -14,9 +14,9 @@ #include "xe_guc.h" #include "xe_guc_submit.h" #include "xe_lrc.h" +#include "xe_mem_pool.h" #include "xe_migrate.h" #include "xe_pm.h" -#include "xe_sa.h" #include "xe_sriov_printk.h" #include "xe_sriov_vf.h" #include "xe_sriov_vf_ccs.h" @@ -141,43 +141,47 @@ static u64 get_ccs_bb_pool_size(struct xe_device *xe) static int alloc_bb_pool(struct xe_tile *tile, struct xe_sriov_vf_ccs_ctx *ctx) { + struct xe_mem_pool *pool; struct xe_device *xe = tile_to_xe(tile); - struct xe_sa_manager *sa_manager; + u32 *pool_cpu_addr, *last_dw_addr; u64 bb_pool_size; - int offset, err; + int err; bb_pool_size = get_ccs_bb_pool_size(xe); xe_sriov_info(xe, "Allocating %s CCS BB pool size = %lldMB\n", ctx->ctx_id ? "Restore" : "Save", bb_pool_size / SZ_1M); - sa_manager = __xe_sa_bo_manager_init(tile, bb_pool_size, SZ_4K, SZ_16, - XE_SA_BO_MANAGER_FLAG_SHADOW); - - if (IS_ERR(sa_manager)) { - xe_sriov_err(xe, "Suballocator init failed with error: %pe\n", - sa_manager); - err = PTR_ERR(sa_manager); + pool = xe_mem_pool_init(tile, bb_pool_size, sizeof(u32), + XE_MEM_POOL_BO_FLAG_INIT_SHADOW_COPY); + if (IS_ERR(pool)) { + xe_sriov_err(xe, "xe_mem_pool_init failed with error: %pe\n", + pool); + err = PTR_ERR(pool); return err; } - offset = 0; - xe_map_memset(xe, &sa_manager->bo->vmap, offset, MI_NOOP, - bb_pool_size); - xe_map_memset(xe, &sa_manager->shadow->vmap, offset, MI_NOOP, - bb_pool_size); + pool_cpu_addr = xe_mem_pool_cpu_addr(pool); + memset(pool_cpu_addr, 0, bb_pool_size); - offset = bb_pool_size - sizeof(u32); - xe_map_wr(xe, &sa_manager->bo->vmap, offset, u32, MI_BATCH_BUFFER_END); - xe_map_wr(xe, &sa_manager->shadow->vmap, offset, u32, MI_BATCH_BUFFER_END); + last_dw_addr = pool_cpu_addr + (bb_pool_size / sizeof(u32)) - 1; + *last_dw_addr = MI_BATCH_BUFFER_END; - ctx->mem.ccs_bb_pool = sa_manager; + /** + * Sync the main copy and shadow copy so that the shadow copy is + * replica of main copy. We sync only BBs after init part. So, we + * need to make sure the main pool and shadow copy are in sync after + * this point. This is needed as GuC may read the BB commands from + * shadow copy. + */ + xe_mem_pool_sync(pool); + ctx->mem.ccs_bb_pool = pool; return 0; } static void ccs_rw_update_ring(struct xe_sriov_vf_ccs_ctx *ctx) { - u64 addr = xe_sa_manager_gpu_addr(ctx->mem.ccs_bb_pool); + u64 addr = xe_mem_pool_gpu_addr(ctx->mem.ccs_bb_pool); struct xe_lrc *lrc = xe_exec_queue_lrc(ctx->mig_q); u32 dw[10], i = 0; @@ -388,7 +392,7 @@ int xe_sriov_vf_ccs_init(struct xe_device *xe) #define XE_SRIOV_VF_CCS_RW_BB_ADDR_OFFSET (2 * sizeof(u32)) void xe_sriov_vf_ccs_rw_update_bb_addr(struct xe_sriov_vf_ccs_ctx *ctx) { - u64 addr = xe_sa_manager_gpu_addr(ctx->mem.ccs_bb_pool); + u64 addr = xe_mem_pool_gpu_addr(ctx->mem.ccs_bb_pool); struct xe_lrc *lrc = xe_exec_queue_lrc(ctx->mig_q); struct xe_device *xe = gt_to_xe(ctx->mig_q->gt); @@ -412,8 +416,8 @@ int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo) struct xe_device *xe = xe_bo_device(bo); enum xe_sriov_vf_ccs_rw_ctxs ctx_id; struct xe_sriov_vf_ccs_ctx *ctx; + struct xe_mem_pool_node *bb; struct xe_tile *tile; - struct xe_bb *bb; int err = 0; xe_assert(xe, IS_VF_CCS_READY(xe)); @@ -445,7 +449,7 @@ int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo) { struct xe_device *xe = xe_bo_device(bo); enum xe_sriov_vf_ccs_rw_ctxs ctx_id; - struct xe_bb *bb; + struct xe_mem_pool_node *bb; xe_assert(xe, IS_VF_CCS_READY(xe)); @@ -471,8 +475,8 @@ int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo) */ void xe_sriov_vf_ccs_print(struct xe_device *xe, struct drm_printer *p) { - struct xe_sa_manager *bb_pool; enum xe_sriov_vf_ccs_rw_ctxs ctx_id; + struct xe_mem_pool *bb_pool; if (!IS_VF_CCS_READY(xe)) return; @@ -485,7 +489,7 @@ void xe_sriov_vf_ccs_print(struct xe_device *xe, struct drm_printer *p) drm_printf(p, "ccs %s bb suballoc info\n", ctx_id ? "write" : "read"); drm_printf(p, "-------------------------\n"); - drm_suballoc_dump_debug_info(&bb_pool->base, p, xe_sa_manager_gpu_addr(bb_pool)); + xe_mem_pool_dump(bb_pool, p); drm_puts(p, "\n"); } } diff --git a/drivers/gpu/drm/xe/xe_sriov_vf_ccs_types.h b/drivers/gpu/drm/xe/xe_sriov_vf_ccs_types.h index 22c499943d2a..6fc8f97ef3f4 100644 --- a/drivers/gpu/drm/xe/xe_sriov_vf_ccs_types.h +++ b/drivers/gpu/drm/xe/xe_sriov_vf_ccs_types.h @@ -17,9 +17,6 @@ enum xe_sriov_vf_ccs_rw_ctxs { XE_SRIOV_VF_CCS_CTX_COUNT }; -struct xe_migrate; -struct xe_sa_manager; - /** * struct xe_sriov_vf_ccs_ctx - VF CCS migration context data. */ @@ -33,7 +30,7 @@ struct xe_sriov_vf_ccs_ctx { /** @mem: memory data */ struct { /** @mem.ccs_bb_pool: Pool from which batch buffers are allocated. */ - struct xe_sa_manager *ccs_bb_pool; + struct xe_mem_pool *ccs_bb_pool; } mem; }; From d88c4bac8c2accbf84a6994a28ee43fee8157703 Mon Sep 17 00:00:00 2001 From: Satyanarayana K V P Date: Thu, 9 Apr 2026 15:44:25 +0000 Subject: [PATCH 067/120] drm/xe/pf: Restrict device query responses in admin-only PF mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a PF is configured in admin-only mode, it is intended for management only and must not expose workload-facing capabilities to userspace. Limit the exposed ioctl set in admin-only PF mode to XE_DEVICE_QUERY and XE_OBSERVATION, and suppress capability-bearing query payloads so that the userspace cannot discover execution-related device details in this mode. Signed-off-by: Satyanarayana K V P Cc: Michal Wajdeczko Cc: Rodrigo Vivi Cc: Piotr Piórkowski Cc: Matthew Brost Cc: Thomas Hellström Cc: Michał Winiarski Cc: Dunajski Bartosz Cc: Ashutosh Dixit Cc: dri-devel@lists.freedesktop.org Acked-by: Rodrigo Vivi Acked-by: Ashutosh Dixit Reviewed-by: Michal Wajdeczko Signed-off-by: Michal Wajdeczko Link: https://patch.msgid.link/20260409154423.2499340-5-satyanarayana.k.v.p@intel.com --- drivers/gpu/drm/xe/xe_device.c | 57 ++++++++++++++++++++++++++++--- drivers/gpu/drm/xe/xe_device.h | 9 +++++ drivers/gpu/drm/xe/xe_hw_engine.c | 3 ++ drivers/gpu/drm/xe/xe_query.c | 7 ++++ 4 files changed, 72 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index cbce1d0ffe48..ceddda10f78f 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -25,6 +25,7 @@ #include "regs/xe_regs.h" #include "xe_bo.h" #include "xe_bo_evict.h" +#include "xe_configfs.h" #include "xe_debugfs.h" #include "xe_defaults.h" #include "xe_devcoredump.h" @@ -390,7 +391,7 @@ bool xe_is_xe_file(const struct file *file) return file->f_op == &xe_driver_fops; } -static struct drm_driver driver = { +static struct drm_driver regular_driver = { .driver_features = DRIVER_GEM | DRIVER_RENDER | DRIVER_SYNCOBJ | @@ -415,6 +416,39 @@ static struct drm_driver driver = { .patchlevel = DRIVER_PATCHLEVEL, }; +#ifdef CONFIG_PCI_IOV +static const struct drm_ioctl_desc xe_ioctls_admin_only[] = { + DRM_IOCTL_DEF_DRV(XE_DEVICE_QUERY, xe_query_ioctl, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl, DRM_RENDER_ALLOW), +}; + +static struct drm_driver admin_only_driver = { + .driver_features = + DRIVER_GEM | DRIVER_RENDER | DRIVER_GEM_GPUVA, + .open = xe_file_open, + .postclose = xe_file_close, + .ioctls = xe_ioctls_admin_only, + .num_ioctls = ARRAY_SIZE(xe_ioctls_admin_only), + .fops = &xe_driver_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, +}; + +/** + * xe_device_is_admin_only() - Check whether device is admin only or not. + * @xe: the &xe_device to check + * + * Return: true if the device is admin only, false otherwise. + */ +bool xe_device_is_admin_only(const struct xe_device *xe) +{ + return xe->drm.driver == &admin_only_driver; +} +#endif + static void xe_device_destroy(struct drm_device *dev, void *dummy) { struct xe_device *xe = to_xe_device(dev); @@ -439,16 +473,26 @@ static void xe_device_destroy(struct drm_device *dev, void *dummy) struct xe_device *xe_device_create(struct pci_dev *pdev, const struct pci_device_id *ent) { + struct drm_driver *driver = ®ular_driver; struct xe_device *xe; int err; - xe_display_driver_set_hooks(&driver); +#ifdef CONFIG_PCI_IOV + /* + * Since XE device is not initialized yet, read from configfs + * directly to decide whether we are in admin-only PF mode or not. + */ + if (xe_configfs_admin_only_pf(pdev)) + driver = &admin_only_driver; +#endif - err = aperture_remove_conflicting_pci_devices(pdev, driver.name); + xe_display_driver_set_hooks(driver); + + err = aperture_remove_conflicting_pci_devices(pdev, driver->name); if (err) return ERR_PTR(err); - xe = devm_drm_dev_alloc(&pdev->dev, &driver, struct xe_device, drm); + xe = devm_drm_dev_alloc(&pdev->dev, driver, struct xe_device, drm); if (IS_ERR(xe)) return xe; @@ -708,6 +752,11 @@ int xe_device_probe_early(struct xe_device *xe) xe_sriov_probe_early(xe); + if (xe_device_is_admin_only(xe) && !IS_SRIOV_PF(xe)) { + xe_err(xe, "Can't run Admin-only mode without SR-IOV PF mode!\n"); + return -ENODEV; + } + if (IS_SRIOV_VF(xe)) vf_update_device_info(xe); diff --git a/drivers/gpu/drm/xe/xe_device.h b/drivers/gpu/drm/xe/xe_device.h index e4b9de8d8e95..555c191f7510 100644 --- a/drivers/gpu/drm/xe/xe_device.h +++ b/drivers/gpu/drm/xe/xe_device.h @@ -211,6 +211,15 @@ bool xe_is_xe_file(const struct file *file); struct xe_vm *xe_device_asid_to_vm(struct xe_device *xe, u32 asid); +#ifdef CONFIG_PCI_IOV +bool xe_device_is_admin_only(const struct xe_device *xe); +#else +static inline bool xe_device_is_admin_only(const struct xe_device *xe) +{ + return false; +} +#endif + /* * Occasionally it is seen that the G2H worker starts running after a delay of more than * a second even after being queued and activated by the Linux workqueue subsystem. This diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index 6dd05fac6595..2f9c1c063f16 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -1026,6 +1026,9 @@ bool xe_hw_engine_is_reserved(struct xe_hw_engine *hwe) struct xe_gt *gt = hwe->gt; struct xe_device *xe = gt_to_xe(gt); + if (xe_device_is_admin_only(xe)) + return true; + if (hwe->class == XE_ENGINE_CLASS_OTHER) return true; diff --git a/drivers/gpu/drm/xe/xe_query.c b/drivers/gpu/drm/xe/xe_query.c index d84d6a422c45..8c7d54498f38 100644 --- a/drivers/gpu/drm/xe/xe_query.c +++ b/drivers/gpu/drm/xe/xe_query.c @@ -231,6 +231,9 @@ static size_t calc_mem_regions_size(struct xe_device *xe) u32 num_managers = 1; int i; + if (xe_device_is_admin_only(xe)) + return sizeof(struct drm_xe_query_mem_regions); + for (i = XE_PL_VRAM0; i <= XE_PL_VRAM1; ++i) if (ttm_manager_type(&xe->ttm, i)) num_managers++; @@ -259,6 +262,9 @@ static int query_mem_regions(struct xe_device *xe, if (XE_IOCTL_DBG(xe, !mem_regions)) return -ENOMEM; + if (xe_device_is_admin_only(xe)) + goto user_copy; + man = ttm_manager_type(&xe->ttm, XE_PL_TT); mem_regions->mem_regions[0].mem_class = DRM_XE_MEM_REGION_CLASS_SYSMEM; /* @@ -297,6 +303,7 @@ static int query_mem_regions(struct xe_device *xe, } } +user_copy: if (!copy_to_user(query_ptr, mem_regions, size)) ret = 0; else From 3e3fbb5ee3092015db2dc9843a605896b2cca97b Mon Sep 17 00:00:00 2001 From: Satyanarayana K V P Date: Mon, 13 Apr 2026 09:56:38 +0000 Subject: [PATCH 068/120] drm/xe/pf: Derive admin-only PF mode from xe_device state Stop tracking admin-only PF mode in a separate `xe->sriov.pf.admin_only` field and use `xe_device_is_admin_only(xe)` as the single source of admin mode. Signed-off-by: Satyanarayana K V P Cc: Michal Wajdeczko Reviewed-by: Michal Wajdeczko Signed-off-by: Michal Wajdeczko Link: https://patch.msgid.link/20260413095637.2871287-2-satyanarayana.k.v.p@intel.com --- .../xe/tests/xe_gt_sriov_pf_config_kunit.c | 21 +++++++++++++++++-- drivers/gpu/drm/xe/xe_device.c | 2 ++ drivers/gpu/drm/xe/xe_sriov_pf.c | 6 ------ drivers/gpu/drm/xe/xe_sriov_pf_helpers.h | 3 ++- drivers/gpu/drm/xe/xe_sriov_pf_types.h | 3 --- 5 files changed, 23 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_config_kunit.c b/drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_config_kunit.c index efa8963ec248..e6eaa94d4d30 100644 --- a/drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_config_kunit.c +++ b/drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_config_kunit.c @@ -13,11 +13,28 @@ #define TEST_MAX_VFS 63 #define TEST_VRAM 0x7a800000ull /* random size that works on 32-bit */ +static bool xe_device_is_admin_only_stub_enable(const struct xe_device *xe) +{ + return true; +} + +static bool xe_device_is_admin_only_stub_disable(const struct xe_device *xe) +{ + return false; +} + static void pf_set_admin_mode(struct xe_device *xe, bool enable) { - /* should match logic of xe_sriov_pf_admin_only() */ - xe->sriov.pf.admin_only = enable; + typeof(xe_device_is_admin_only) *stub = enable ? + xe_device_is_admin_only_stub_enable : + xe_device_is_admin_only_stub_disable; + + kunit_activate_static_stub(kunit_get_current_test(), + xe_device_is_admin_only, + *stub); + KUNIT_EXPECT_EQ(kunit_get_current_test(), enable, xe_sriov_pf_admin_only(xe)); + KUNIT_EXPECT_EQ(kunit_get_current_test(), enable, xe_device_is_admin_only(xe)); } static void pf_set_usable_vram(struct xe_device *xe, u64 usable) diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index ceddda10f78f..4b45b617a039 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "display/xe_display.h" @@ -445,6 +446,7 @@ static struct drm_driver admin_only_driver = { */ bool xe_device_is_admin_only(const struct xe_device *xe) { + KUNIT_STATIC_STUB_REDIRECT(xe_device_is_admin_only, xe); return xe->drm.driver == &admin_only_driver; } #endif diff --git a/drivers/gpu/drm/xe/xe_sriov_pf.c b/drivers/gpu/drm/xe/xe_sriov_pf.c index 47a6e0fd66e0..33bd754d138f 100644 --- a/drivers/gpu/drm/xe/xe_sriov_pf.c +++ b/drivers/gpu/drm/xe/xe_sriov_pf.c @@ -20,11 +20,6 @@ #include "xe_sriov_pf_sysfs.h" #include "xe_sriov_printk.h" -static bool wanted_admin_only(struct xe_device *xe) -{ - return xe_configfs_admin_only_pf(to_pci_dev(xe->drm.dev)); -} - static unsigned int wanted_max_vfs(struct xe_device *xe) { return xe_configfs_get_max_vfs(to_pci_dev(xe->drm.dev)); @@ -79,7 +74,6 @@ bool xe_sriov_pf_readiness(struct xe_device *xe) pf_reduce_totalvfs(xe, newlimit); - xe->sriov.pf.admin_only = wanted_admin_only(xe); xe->sriov.pf.device_total_vfs = totalvfs; xe->sriov.pf.driver_max_vfs = newlimit; diff --git a/drivers/gpu/drm/xe/xe_sriov_pf_helpers.h b/drivers/gpu/drm/xe/xe_sriov_pf_helpers.h index 0fcc6cec4afc..19f6f8331c8d 100644 --- a/drivers/gpu/drm/xe/xe_sriov_pf_helpers.h +++ b/drivers/gpu/drm/xe/xe_sriov_pf_helpers.h @@ -7,6 +7,7 @@ #define _XE_SRIOV_PF_HELPERS_H_ #include "xe_assert.h" +#include "xe_device.h" #include "xe_device_types.h" #include "xe_sriov.h" #include "xe_sriov_types.h" @@ -57,7 +58,7 @@ static inline unsigned int xe_sriov_pf_num_vfs(const struct xe_device *xe) static inline bool xe_sriov_pf_admin_only(const struct xe_device *xe) { xe_assert(xe, IS_SRIOV_PF(xe)); - return xe->sriov.pf.admin_only; + return xe_device_is_admin_only(xe); } static inline struct mutex *xe_sriov_pf_master_mutex(struct xe_device *xe) diff --git a/drivers/gpu/drm/xe/xe_sriov_pf_types.h b/drivers/gpu/drm/xe/xe_sriov_pf_types.h index 080cf10512f4..b0253e1ae5da 100644 --- a/drivers/gpu/drm/xe/xe_sriov_pf_types.h +++ b/drivers/gpu/drm/xe/xe_sriov_pf_types.h @@ -36,9 +36,6 @@ struct xe_sriov_metadata { * @XE_SRIOV_MODE_PF mode. */ struct xe_device_pf { - /** @admin_only: PF functionality focused on VFs management only. */ - bool admin_only; - /** @device_total_vfs: Maximum number of VFs supported by the device. */ u16 device_total_vfs; From 96078a1c68bf97f17fd1d08c3f58f5c5cc9ccd65 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Thu, 9 Apr 2026 00:34:49 +0000 Subject: [PATCH 069/120] drm/xe: Fix potential NULL deref in xe_exec_queue_tlb_inval_last_fence_put_unlocked xe_exec_queue_tlb_inval_last_fence_put_unlocked() uses q->vm->xe as the first argument to xe_assert(). This function is called unconditionally from xe_exec_queue_destroy() for all queues, including kernel queues that have q->vm == NULL (e.g., queues created during GT init in xe_gt_record_default_lrcs() with vm=NULL). While current compilers optimize away the q->vm->xe dereference (even in CONFIG_DRM_XE_DEBUG=y builds, the compiler pushes the dereference into the WARN branch that is only taken when the assert condition is false), the code is semantically incorrect and constitutes undefined behavior in the C abstract machine for the NULL pointer case. Use gt_to_xe(q->gt) instead, which is always valid for any exec queue. This is consistent with how xe_exec_queue_destroy() itself obtains the xe_device pointer in its own xe_assert at the top of the function. Fixes: b2d7ec41f2a3 ("drm/xe: Attach last fence to TLB invalidation job queues") Assisted-by: Claude:claude-opus-4.6 Reviewed-by: Matthew Brost Link: https://patch.msgid.link/20260409003449.3405767-1-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_exec_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c index b287d0e0e60a..8de8ec784a03 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.c +++ b/drivers/gpu/drm/xe/xe_exec_queue.c @@ -1760,7 +1760,7 @@ void xe_exec_queue_tlb_inval_last_fence_put(struct xe_exec_queue *q, void xe_exec_queue_tlb_inval_last_fence_put_unlocked(struct xe_exec_queue *q, unsigned int type) { - xe_assert(q->vm->xe, type == XE_EXEC_QUEUE_TLB_INVAL_MEDIA_GT || + xe_assert(gt_to_xe(q->gt), type == XE_EXEC_QUEUE_TLB_INVAL_MEDIA_GT || type == XE_EXEC_QUEUE_TLB_INVAL_PRIMARY_GT); dma_fence_put(q->tlb_inval[type].last_fence); From 601c2aa087b6f21014300a3f107a08ee4dde7bdf Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Wed, 8 Apr 2026 17:52:52 +0000 Subject: [PATCH 070/120] drm/xe/bo: Fix bo leak on unaligned size validation in xe_bo_init_locked() When type is ttm_bo_type_device and aligned_size != size, the function returns an error without freeing a caller-provided bo, violating the documented contract that bo is freed on failure. Add xe_bo_free(bo) before returning the error. Fixes: 4e03b584143e ("drm/xe/uapi: Reject bo creation of unaligned size") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4.6 Reviewed-by: Matthew Brost Link: https://patch.msgid.link/20260408175255.3402838-2-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_bo.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index daac53168dba..c2f4f9090fb0 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -2329,8 +2329,10 @@ struct xe_bo *xe_bo_init_locked(struct xe_device *xe, struct xe_bo *bo, alignment = SZ_4K >> PAGE_SHIFT; } - if (type == ttm_bo_type_device && aligned_size != size) + if (type == ttm_bo_type_device && aligned_size != size) { + xe_bo_free(bo); return ERR_PTR(-EINVAL); + } if (!bo) { bo = xe_bo_alloc(); From 3fbd6cf43cac7b60757f3ce3d95195d3843a902c Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Wed, 8 Apr 2026 17:52:53 +0000 Subject: [PATCH 071/120] drm/xe/bo: Fix bo leak on GGTT flag validation in xe_bo_init_locked() When XE_BO_FLAG_GGTT_ALL is set without XE_BO_FLAG_GGTT, the function returns an error without freeing a caller-provided bo, violating the documented contract that bo is freed on failure. Add xe_bo_free(bo) before returning the error. Fixes: 5a3b0df25d6a ("drm/xe: Allow bo mapping on multiple ggtts") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4.6 Reviewed-by: Matthew Brost Link: https://patch.msgid.link/20260408175255.3402838-3-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_bo.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index c2f4f9090fb0..5ce60d161e09 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -2309,8 +2309,10 @@ struct xe_bo *xe_bo_init_locked(struct xe_device *xe, struct xe_bo *bo, } /* XE_BO_FLAG_GGTTx requires XE_BO_FLAG_GGTT also be set */ - if ((flags & XE_BO_FLAG_GGTT_ALL) && !(flags & XE_BO_FLAG_GGTT)) + if ((flags & XE_BO_FLAG_GGTT_ALL) && !(flags & XE_BO_FLAG_GGTT)) { + xe_bo_free(bo); return ERR_PTR(-EINVAL); + } if (flags & (XE_BO_FLAG_VRAM_MASK | XE_BO_FLAG_STOLEN) && !(flags & XE_BO_FLAG_IGNORE_MIN_PAGE_SIZE) && From 78a6c5f899f22338bbf48b44fb8950409c5a69b9 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Wed, 8 Apr 2026 17:52:54 +0000 Subject: [PATCH 072/120] drm/xe: Fix bo leak in xe_dma_buf_init_obj() on allocation failure When drm_gpuvm_resv_object_alloc() fails, the pre-allocated storage bo is not freed. Add xe_bo_free(storage) before returning the error. xe_dma_buf_init_obj() calls xe_bo_init_locked(), which frees the bo on error. Therefore, xe_dma_buf_init_obj() must also free the bo on its own error paths. Otherwise, since xe_gem_prime_import() cannot distinguish whether the failure originated from xe_dma_buf_init_obj() or from xe_bo_init_locked(), it cannot safely decide whether the bo should be freed. Add comments documenting the ownership semantics: on success, ownership of storage is transferred to the returned drm_gem_object; on failure, storage is freed before returning. v2: Add comments to explain the free logic. Fixes: eb289a5f6cc6 ("drm/xe: Convert xe_dma_buf.c for exhaustive eviction") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4.6 Reviewed-by: Matthew Brost Link: https://patch.msgid.link/20260408175255.3402838-4-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_dma_buf.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_dma_buf.c b/drivers/gpu/drm/xe/xe_dma_buf.c index 7f9602b3363d..c0937c090d33 100644 --- a/drivers/gpu/drm/xe/xe_dma_buf.c +++ b/drivers/gpu/drm/xe/xe_dma_buf.c @@ -258,6 +258,13 @@ struct dma_buf *xe_gem_prime_export(struct drm_gem_object *obj, int flags) return ERR_PTR(ret); } +/* + * Takes ownership of @storage: on success it is transferred to the returned + * drm_gem_object; on failure it is freed before returning the error. + * This matches the contract of xe_bo_init_locked() which frees @storage on + * its error paths, so callers need not (and must not) free @storage after + * this call. + */ static struct drm_gem_object * xe_dma_buf_init_obj(struct drm_device *dev, struct xe_bo *storage, struct dma_buf *dma_buf) @@ -271,8 +278,10 @@ xe_dma_buf_init_obj(struct drm_device *dev, struct xe_bo *storage, int ret = 0; dummy_obj = drm_gpuvm_resv_object_alloc(&xe->drm); - if (!dummy_obj) + if (!dummy_obj) { + xe_bo_free(storage); return ERR_PTR(-ENOMEM); + } dummy_obj->resv = resv; xe_validation_guard(&ctx, &xe->val, &exec, (struct xe_val_flags) {}, ret) { @@ -281,6 +290,7 @@ xe_dma_buf_init_obj(struct drm_device *dev, struct xe_bo *storage, if (ret) break; + /* xe_bo_init_locked() frees storage on error */ bo = xe_bo_init_locked(xe, storage, NULL, resv, NULL, dma_buf->size, 0, /* Will require 1way or 2way for vm_bind */ ttm_bo_type_sg, XE_BO_FLAG_SYSTEM, &exec); From a828eb185aac41800df8eae4b60501ccc0dbbe51 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Wed, 8 Apr 2026 17:52:55 +0000 Subject: [PATCH 073/120] drm/xe: Fix dma-buf attachment leak in xe_gem_prime_import() When xe_dma_buf_init_obj() fails, the attachment from dma_buf_dynamic_attach() is not detached. Add dma_buf_detach() before returning the error. Note: we cannot use goto out_err here because xe_dma_buf_init_obj() already frees bo on failure, and out_err would double-free it. Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4.6 Reviewed-by: Mattheq Brost Link: https://patch.msgid.link/20260408175255.3402838-5-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_dma_buf.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_dma_buf.c b/drivers/gpu/drm/xe/xe_dma_buf.c index c0937c090d33..b9828da15897 100644 --- a/drivers/gpu/drm/xe/xe_dma_buf.c +++ b/drivers/gpu/drm/xe/xe_dma_buf.c @@ -378,12 +378,15 @@ struct drm_gem_object *xe_gem_prime_import(struct drm_device *dev, goto out_err; } - /* Errors here will take care of freeing the bo. */ + /* + * xe_dma_buf_init_obj() takes ownership of bo on both success + * and failure, so we must not touch bo after this call. + */ obj = xe_dma_buf_init_obj(dev, bo, dma_buf); - if (IS_ERR(obj)) + if (IS_ERR(obj)) { + dma_buf_detach(dma_buf, attach); return obj; - - + } get_dma_buf(dma_buf); obj->import_attach = attach; return obj; From 37c831f401746a45d510b312b0ed7a77b1e06ec8 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Wed, 8 Apr 2026 02:06:47 +0000 Subject: [PATCH 074/120] drm/xe: Fix error cleanup in xe_exec_queue_create_ioctl() Two error handling issues exist in xe_exec_queue_create_ioctl(): 1. When xe_hw_engine_group_add_exec_queue() fails, the error path jumps to put_exec_queue which skips xe_exec_queue_kill(). If the VM is in preempt fence mode, xe_vm_add_compute_exec_queue() has already added the queue to the VM's compute exec queue list. Skipping the kill leaves the queue on that list, leading to a dangling pointer after the queue is freed. 2. When xa_alloc() fails after xe_hw_engine_group_add_exec_queue() has succeeded, the error path does not call xe_hw_engine_group_del_exec_queue() to remove the queue from the hw engine group list. The queue is then freed while still linked into the hw engine group, causing a use-after-free. Fix both by: - Changing the xe_hw_engine_group_add_exec_queue() failure path to jump to kill_exec_queue so that xe_exec_queue_kill() properly removes the queue from the VM's compute list. - Adding a del_hw_engine_group label before kill_exec_queue for the xa_alloc() failure path, which removes the queue from the hw engine group before proceeding with the rest of the cleanup. Fixes: 7970cb36966c ("'drm/xe/hw_engine_group: Register hw engine group's exec queues") Cc: Francois Dugast Cc: Matthew Brost Cc: Niranjana Vishwanathapura Assisted-by: Claude:claude-opus-4.6 Reviewed-by: Matthew Brost Link: https://patch.msgid.link/20260408020647.3397933-1-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_exec_queue.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c index 8de8ec784a03..071b8c41df43 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue.c +++ b/drivers/gpu/drm/xe/xe_exec_queue.c @@ -1405,7 +1405,7 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data, if (q->vm && q->hwe->hw_engine_group) { err = xe_hw_engine_group_add_exec_queue(q->hwe->hw_engine_group, q); if (err) - goto put_exec_queue; + goto kill_exec_queue; } } @@ -1416,12 +1416,15 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data, /* user id alloc must always be last in ioctl to prevent UAF */ err = xa_alloc(&xef->exec_queue.xa, &id, q, xa_limit_32b, GFP_KERNEL); if (err) - goto kill_exec_queue; + goto del_hw_engine_group; args->exec_queue_id = id; return 0; +del_hw_engine_group: + if (q->vm && q->hwe && q->hwe->hw_engine_group) + xe_hw_engine_group_del_exec_queue(q->hwe->hw_engine_group, q); kill_exec_queue: xe_exec_queue_kill(q); delete_queue_group: From 36acdfbc2cad67f550021725d6550bb0d4973217 Mon Sep 17 00:00:00 2001 From: Clint Taylor Date: Mon, 13 Apr 2026 13:08:25 -0700 Subject: [PATCH 075/120] drm/xe/xe3p: add gt tuning TileY 2x2 walk pattern Apply engine tuning for TileY 2x2 walk pattern, starting with IP Xe3p_LPG. v2: move to xe tunings (MattR) Bspec: 72161, 73720 Signed-off-by: Clint Taylor Link: https://patch.msgid.link/20260413200825.4054940-1-clinton.a.taylor@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/regs/xe_gt_regs.h | 3 +++ drivers/gpu/drm/xe/xe_tuning.c | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h index a4472b7acb18..87a99efa4765 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -536,6 +536,9 @@ #define SLM_WMTP_RESTORE REG_BIT(11) #define RES_CHK_SPR_DIS REG_BIT(6) +#define TDL_TSL_CHICKEN2 XE_REG_MCR(0xe4cc, XE_REG_OPTION_MASKED) +#define TILEY_LOCALID REG_BIT(2) + #define ROW_CHICKEN XE_REG_MCR(0xe4f0, XE_REG_OPTION_MASKED) #define UGM_BACKUP_MODE REG_BIT(13) #define MDQ_ARBITRATION_MODE REG_BIT(12) diff --git a/drivers/gpu/drm/xe/xe_tuning.c b/drivers/gpu/drm/xe/xe_tuning.c index 6fb8887d1482..ce39b77a084a 100644 --- a/drivers/gpu/drm/xe/xe_tuning.c +++ b/drivers/gpu/drm/xe/xe_tuning.c @@ -124,6 +124,11 @@ static const struct xe_rtp_entry_sr engine_tunings[] = { GHWSP_CSB_REPORT_DIS, XE_RTP_ACTION_FLAG(ENGINE_BASE))) }, + { XE_RTP_NAME("Tuning: TileY 2x2 Walk"), + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3510, XE_RTP_END_VERSION_UNDEFINED), + FUNC(xe_rtp_match_first_render_or_compute)), + XE_RTP_ACTIONS(SET(TDL_TSL_CHICKEN2, TILEY_LOCALID)) + }, }; static const struct xe_rtp_entry_sr lrc_tunings[] = { From ad422cae958fcfbc231aabc8ad8fbcdda0f2e019 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Mon, 13 Apr 2026 16:07:24 -0700 Subject: [PATCH 076/120] drm/xe: Suppress reset log for killed queues When an app exits abruptly (for example due to the user hitting ctrl+c), any of its queues that are still active on the HW are immediately killed. As part of this process, the driver tells the GuC to preempt the queues off the HW and to reset them if they don't preempt. This can cause a reset log to be printed to dmesg, which can be confusing to users as resets are commonly tied to errors, while any resets performed in this case are just done to speed up the cleanup. Also, those reset messages are not useful for debug, because we don't care what happens to a queue once its app has exited. The only case where a queue might be killed before the app that owns it has exited is if the queue uses PXP and a PXP termination occurs. In such scenario a log might be useful, but rather than a reset log it is better to have a communication that the queue is being killed. Therefore, we can silence the reset log for all killed queues and add a simple debug log to record when a PXP queue is killed to cover that case. Signed-off-by: Daniele Ceraolo Spurio Cc: Matthew Brost Reviewed-by: Matthew Brost Link: https://patch.msgid.link/20260413230724.714884-2-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/xe/xe_guc_submit.c | 7 ++++--- drivers/gpu/drm/xe/xe_pxp.c | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 10556156eaad..b1222b42174c 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -2968,9 +2968,10 @@ int xe_guc_exec_queue_reset_handler(struct xe_guc *guc, u32 *msg, u32 len) if (unlikely(!q)) return -EPROTO; - xe_gt_info(gt, "Engine reset: engine_class=%s, logical_mask: 0x%x, guc_id=%d, state=0x%0x", - xe_hw_engine_class_to_str(q->class), q->logical_mask, guc_id, - atomic_read(&q->guc->state)); + if (!exec_queue_killed(q)) + xe_gt_info(gt, "Engine reset: engine_class=%s, logical_mask: 0x%x, guc_id=%d, state=0x%0x", + xe_hw_engine_class_to_str(q->class), q->logical_mask, guc_id, + atomic_read(&q->guc->state)); trace_xe_exec_queue_reset(q); diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index 7244090b0782..968b7e70b3f9 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -13,10 +13,12 @@ #include "xe_device_types.h" #include "xe_exec_queue.h" #include "xe_force_wake.h" +#include "xe_guc_exec_queue_types.h" #include "xe_guc_submit.h" #include "xe_gsc_proxy.h" #include "xe_gt_types.h" #include "xe_huc.h" +#include "xe_hw_engine.h" #include "xe_mmio.h" #include "xe_pm.h" #include "xe_pxp_submit.h" @@ -740,6 +742,10 @@ static void pxp_invalidate_queues(struct xe_pxp *pxp) spin_unlock_irq(&pxp->queues.lock); list_for_each_entry_safe(q, tmp, &to_clean, pxp.link) { + drm_dbg(&pxp->xe->drm, + "Killing queue due to PXP termination: eclass=%s, guc_id=%d\n", + xe_hw_engine_class_to_str(q->class), q->guc->id); + xe_exec_queue_kill(q); /* From ef838419059c2b579e0153335065a2f6f48f10a5 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 14 Apr 2026 22:54:30 +0000 Subject: [PATCH 077/120] drm/xe: Fix stale and mismatched kernel-doc member tags in header files Fix kernel-doc member tags that do not match the actual struct member names, which would cause warnings with scripts/kernel-doc or produce incorrect documentation: - xe_bo_types.h: @atomic_access -> @attr.atomic_access - xe_device_types.h: @mem.sys_mgr -> @mem.shrinker, @pinned.external -> @pinned.late.external, @vram_usefault.list -> @mem_access.vram_userfault.list, @usm.asid -> @usm.asid_to_vm, @usm.pagemap_shrinker -> @usm.dpagemap_shrinker, @vm.xe -> @vm.xa - xe_exec_queue_types.h: @last_fence -> @tlb_inval.last_fence - xe_gt_sriov_pf_types.h: Remove stale @migration doc for non-existent member - xe_gt_types.h: @info->engine_mask -> @info.engine_mask, @multi_queue_engine_class_mask -> @info.multi_queue_engine_class_mask - xe_guc_ct_types.h: @ctbs.send -> @ctbs.h2g, @ctbs.recv -> @ctbs.g2h - xe_guc_submit_types.h: @valid -> @multi_queue.valid - xe_hw_engine_types.h: @sched_props.set_job_timeout -> @sched_props.job_timeout_ms - xe_oa_types.h: duplicate @format -> @bo - xe_vm_types.h: @read_only -> @invalidate_on_bind, add missing @vma_flags doc Assisted-by: GitHub Copilot:claude-sonnet-4.6 Reviewed-by: Brian Nguyen Link: https://patch.msgid.link/20260414225457.3687449-2-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_bo_types.h | 2 +- drivers/gpu/drm/xe/xe_device_types.h | 12 ++++++------ drivers/gpu/drm/xe/xe_exec_queue_types.h | 2 +- drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h | 1 - drivers/gpu/drm/xe/xe_gt_types.h | 4 ++-- drivers/gpu/drm/xe/xe_guc_ct_types.h | 4 ++-- drivers/gpu/drm/xe/xe_guc_submit_types.h | 2 +- drivers/gpu/drm/xe/xe_hw_engine_types.h | 2 +- drivers/gpu/drm/xe/xe_oa_types.h | 2 +- drivers/gpu/drm/xe/xe_vm_types.h | 3 ++- 10 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_bo_types.h b/drivers/gpu/drm/xe/xe_bo_types.h index 9d19940b8fc0..9c199badd9b2 100644 --- a/drivers/gpu/drm/xe/xe_bo_types.h +++ b/drivers/gpu/drm/xe/xe_bo_types.h @@ -67,7 +67,7 @@ struct xe_bo { /** @attr: User controlled attributes for bo */ struct { /** - * @atomic_access: type of atomic access bo needs + * @attr.atomic_access: type of atomic access bo needs * protected by bo dma-resv lock */ u32 atomic_access; diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 150c76b2acaf..2ebe33a0dc07 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -276,7 +276,7 @@ struct xe_device { struct xe_vram_region *vram; /** @mem.sys_mgr: system TTM manager */ struct ttm_resource_manager sys_mgr; - /** @mem.sys_mgr: system memory shrinker. */ + /** @mem.shrinker: system memory shrinker. */ struct xe_shrinker *shrinker; } mem; @@ -298,7 +298,7 @@ struct xe_device { /** @usm: unified memory state */ struct { - /** @usm.asid: convert a ASID to VM */ + /** @usm.asid_to_vm: convert an ASID to VM */ struct xarray asid_to_vm; /** @usm.next_asid: next ASID, used to cyclical alloc asids */ u32 next_asid; @@ -315,7 +315,7 @@ struct xe_device { /** @usm.pf_queue: Page fault queues */ struct xe_pagefault_queue pf_queue[XE_PAGEFAULT_QUEUE_COUNT]; #if IS_ENABLED(CONFIG_DRM_XE_PAGEMAP) - /** @usm.pagemap_shrinker: Shrinker for unused pagemaps */ + /** @usm.dpagemap_shrinker: Shrinker for unused pagemaps */ struct drm_pagemap_shrinker *dpagemap_shrinker; #endif } usm; @@ -337,7 +337,7 @@ struct xe_device { struct list_head kernel_bo_present; /** @pinned.late.evicted: pinned BO that have been evicted */ struct list_head evicted; - /** @pinned.external: pinned external and dma-buf. */ + /** @pinned.late.external: pinned external and dma-buf. */ struct list_head external; } late; } pinned; @@ -372,7 +372,7 @@ struct xe_device { struct { /** * @mem_access.vram_userfault.lock: Protects access to - * @vram_usefault.list Using mutex instead of spinlock + * @mem_access.vram_userfault.list Using mutex instead of spinlock * as lock is applied to entire list operation which * may sleep */ @@ -584,7 +584,7 @@ struct xe_file { /** @vm: VM state for file */ struct { - /** @vm.xe: xarray to store VMs */ + /** @vm.xa: xarray to store VMs */ struct xarray xa; /** * @vm.lock: Protects VM lookup + reference and removal from diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h index 8ce78e0b1d50..2f5ccf294675 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h @@ -214,7 +214,7 @@ struct xe_exec_queue { */ struct xe_dep_scheduler *dep_scheduler; /** - * @last_fence: last fence for tlb invalidation, protected by + * @tlb_inval.last_fence: last fence for tlb invalidation, protected by * vm->lock in write mode */ struct dma_fence *last_fence; diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h index 667b8310478d..6296483c44ec 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h @@ -49,7 +49,6 @@ struct xe_gt_sriov_pf_workers { * @service: service data. * @control: control data. * @policy: policy data. - * @migration: migration data. * @spare: PF-only provisioning configuration. * @vfs: metadata for all VFs. */ diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h index 8b55cf25a75f..7351aadd238e 100644 --- a/drivers/gpu/drm/xe/xe_gt_types.h +++ b/drivers/gpu/drm/xe/xe_gt_types.h @@ -136,7 +136,7 @@ struct xe_gt { /** @info.gmdid: raw GMD_ID value from hardware */ u32 gmdid; /** - * @multi_queue_engine_class_mask: Bitmask of engine classes with + * @info.multi_queue_engine_class_mask: Bitmask of engine classes with * multi queue support enabled. */ u16 multi_queue_engine_class_mask; @@ -355,7 +355,7 @@ struct xe_gt { /** @user_engines: engines present in GT and available to userspace */ struct { /** - * @user_engines.mask: like @info->engine_mask, but take in + * @user_engines.mask: like @info.engine_mask, but take in * consideration only engines available to userspace */ u64 mask; diff --git a/drivers/gpu/drm/xe/xe_guc_ct_types.h b/drivers/gpu/drm/xe/xe_guc_ct_types.h index 5da1ce5dc372..c81996f8915a 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct_types.h +++ b/drivers/gpu/drm/xe/xe_guc_ct_types.h @@ -134,9 +134,9 @@ struct xe_guc_ct { spinlock_t fast_lock; /** @ctbs: buffers for sending and receiving commands */ struct { - /** @ctbs.send: Host to GuC (H2G, send) channel */ + /** @ctbs.h2g: Host to GuC (H2G, send) channel */ struct guc_ctb h2g; - /** @ctbs.recv: GuC to Host (G2H, receive) channel */ + /** @ctbs.g2h: GuC to Host (G2H, receive) channel */ struct guc_ctb g2h; } ctbs; /** @g2h_outstanding: number of outstanding G2H */ diff --git a/drivers/gpu/drm/xe/xe_guc_submit_types.h b/drivers/gpu/drm/xe/xe_guc_submit_types.h index 5ccc5f959bb3..7824f61b1290 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit_types.h +++ b/drivers/gpu/drm/xe/xe_guc_submit_types.h @@ -138,7 +138,7 @@ struct xe_guc_submit_exec_queue_snapshot { u32 primary; /** @multi_queue.pos: Position of the exec queue within the multi queue group */ u8 pos; - /** @valid: The exec queue is part of a multi queue group */ + /** @multi_queue.valid: The exec queue is part of a multi queue group */ bool valid; } multi_queue; }; diff --git a/drivers/gpu/drm/xe/xe_hw_engine_types.h b/drivers/gpu/drm/xe/xe_hw_engine_types.h index e4191a7a2c31..0f87128c6529 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine_types.h +++ b/drivers/gpu/drm/xe/xe_hw_engine_types.h @@ -79,7 +79,7 @@ struct xe_hw_engine_class_intf { * @defaults: default scheduling properties */ struct { - /** @sched_props.set_job_timeout: Set job timeout in ms for engine */ + /** @sched_props.job_timeout_ms: Set job timeout in ms for engine */ u32 job_timeout_ms; /** @sched_props.job_timeout_min: Min job timeout in ms for engine */ u32 job_timeout_min; diff --git a/drivers/gpu/drm/xe/xe_oa_types.h b/drivers/gpu/drm/xe/xe_oa_types.h index b03ffd513483..acd78bc14822 100644 --- a/drivers/gpu/drm/xe/xe_oa_types.h +++ b/drivers/gpu/drm/xe/xe_oa_types.h @@ -159,7 +159,7 @@ struct xe_oa_buffer { /** @format: data format */ const struct xe_oa_format *format; - /** @format: xe_bo backing the OA buffer */ + /** @bo: xe_bo backing the OA buffer */ struct xe_bo *bo; /** @vaddr: mapped vaddr of the OA buffer */ diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h index a94827d7fbec..635ed29b9a69 100644 --- a/drivers/gpu/drm/xe/xe_vm_types.h +++ b/drivers/gpu/drm/xe/xe_vm_types.h @@ -412,10 +412,11 @@ struct xe_vm { struct xe_vma_op_map { /** @vma: VMA to map */ struct xe_vma *vma; + /** @vma_flags: VMA flags for this operation */ unsigned int vma_flags; /** @immediate: Immediate bind */ bool immediate; - /** @read_only: Read only */ + /** @invalidate_on_bind: Invalidate on bind */ bool invalidate_on_bind; /** @request_decompress: schedule decompression for GPU map */ bool request_decompress; From 4e12b3b53b5239619f55ab04537c3e854dd1c140 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 14 Apr 2026 22:54:31 +0000 Subject: [PATCH 078/120] drm/xe: Add missing '@' prefix to kernel-doc member tags Add the required '@' prefix to member documentation tags that were missing it. Without the prefix, kernel-doc does not associate the comment with the struct member. - xe_guc_ct_types.h: snapshot_ct -> @snapshot_ct, snapshot_log -> @snapshot_log - xe_pagefault_types.h: consumer.reserved -> @consumer.reserved - xe_pt_types.h: addr -> @addr Assisted-by: GitHub Copilot:claude-sonnet-4.6 Reviewed-by: Brian Nguyen Link: https://patch.msgid.link/20260414225457.3687449-3-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_guc_ct_types.h | 4 ++-- drivers/gpu/drm/xe/xe_pagefault_types.h | 2 +- drivers/gpu/drm/xe/xe_pt_types.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_ct_types.h b/drivers/gpu/drm/xe/xe_guc_ct_types.h index c81996f8915a..f88e588af0d3 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct_types.h +++ b/drivers/gpu/drm/xe/xe_guc_ct_types.h @@ -102,9 +102,9 @@ struct xe_dead_ct { bool reported; /** @worker: worker thread to get out of interrupt context before dumping */ struct work_struct worker; - /** snapshot_ct: copy of CT state and CTB content at point of error */ + /** @snapshot_ct: copy of CT state and CTB content at point of error */ struct xe_guc_ct_snapshot *snapshot_ct; - /** snapshot_log: copy of GuC log at point of error */ + /** @snapshot_log: copy of GuC log at point of error */ struct xe_guc_log_snapshot *snapshot_log; }; diff --git a/drivers/gpu/drm/xe/xe_pagefault_types.h b/drivers/gpu/drm/xe/xe_pagefault_types.h index b3289219b1be..aa3cfae01b9c 100644 --- a/drivers/gpu/drm/xe/xe_pagefault_types.h +++ b/drivers/gpu/drm/xe/xe_pagefault_types.h @@ -86,7 +86,7 @@ struct xe_pagefault { u8 engine_class; /** @consumer.engine_instance: engine instance */ u8 engine_instance; - /** consumer.reserved: reserved bits for future expansion */ + /** @consumer.reserved: reserved bits for future expansion */ u64 reserved; } consumer; /** diff --git a/drivers/gpu/drm/xe/xe_pt_types.h b/drivers/gpu/drm/xe/xe_pt_types.h index 84b51d3762a4..a7d1bb708b69 100644 --- a/drivers/gpu/drm/xe/xe_pt_types.h +++ b/drivers/gpu/drm/xe/xe_pt_types.h @@ -34,7 +34,7 @@ struct xe_pt { bool rebind; bool is_compact; #if IS_ENABLED(CONFIG_DRM_XE_DEBUG_VM) - /** addr: Virtual address start address of the PT. */ + /** @addr: Virtual address start address of the PT. */ u64 addr; #endif }; From 7f46eefbf5dbe309cd7a876db69f758d0b8b9784 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 14 Apr 2026 22:54:32 +0000 Subject: [PATCH 079/120] drm/xe: Fix kernel-doc comment syntax issues in header files Fix doc comment formatting that does not conform to kernel-doc syntax rules: - xe_guc_relay_types.h: Add missing space after '/**' in member doc comment (/**@lock -> /** @lock) - xe_oa_types.h: Fix struct documentation to use proper kernel-doc format (/** @xe_oa_buffer: -> /** struct xe_oa_buffer -) - xe_pagefault_types.h: Use dash instead of colon as separator in struct doc (struct xe_pagefault_queue: -> struct xe_pagefault_queue -) - xe_pt_walk.h: Use dash instead of colon as separator in function docs (xe_pt_num_entries: -> xe_pt_num_entries -, xe_pt_offset: -> xe_pt_offset -) Assisted-by: GitHub Copilot:claude-sonnet-4.6 Reviewed-by: Brian Nguyen Link: https://patch.msgid.link/20260414225457.3687449-4-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_guc_relay_types.h | 2 +- drivers/gpu/drm/xe/xe_oa_types.h | 4 +++- drivers/gpu/drm/xe/xe_pagefault_types.h | 2 +- drivers/gpu/drm/xe/xe_pt_walk.h | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_relay_types.h b/drivers/gpu/drm/xe/xe_guc_relay_types.h index 20eee10856b2..b99a6686416b 100644 --- a/drivers/gpu/drm/xe/xe_guc_relay_types.h +++ b/drivers/gpu/drm/xe/xe_guc_relay_types.h @@ -15,7 +15,7 @@ * struct xe_guc_relay - Data used by the VF-PF Relay Communication over GuC. */ struct xe_guc_relay { - /**@lock: protects all internal data. */ + /** @lock: protects all internal data. */ spinlock_t lock; /** @worker: dispatches incoming action messages. */ diff --git a/drivers/gpu/drm/xe/xe_oa_types.h b/drivers/gpu/drm/xe/xe_oa_types.h index acd78bc14822..0c48c1e0c2c6 100644 --- a/drivers/gpu/drm/xe/xe_oa_types.h +++ b/drivers/gpu/drm/xe/xe_oa_types.h @@ -154,7 +154,9 @@ struct xe_oa { u16 oa_unit_ids; }; -/** @xe_oa_buffer: State of the stream OA buffer */ +/** + * struct xe_oa_buffer - State of the stream OA buffer + */ struct xe_oa_buffer { /** @format: data format */ const struct xe_oa_format *format; diff --git a/drivers/gpu/drm/xe/xe_pagefault_types.h b/drivers/gpu/drm/xe/xe_pagefault_types.h index aa3cfae01b9c..c4ee625b93dd 100644 --- a/drivers/gpu/drm/xe/xe_pagefault_types.h +++ b/drivers/gpu/drm/xe/xe_pagefault_types.h @@ -112,7 +112,7 @@ struct xe_pagefault { }; /** - * struct xe_pagefault_queue: Xe pagefault queue (consumer) + * struct xe_pagefault_queue - Xe pagefault queue (consumer) * * Used to capture all device page faults for deferred processing. Size this * queue to absorb the device’s worst-case number of outstanding faults. diff --git a/drivers/gpu/drm/xe/xe_pt_walk.h b/drivers/gpu/drm/xe/xe_pt_walk.h index 07c8f409f236..dcedfc9a28df 100644 --- a/drivers/gpu/drm/xe/xe_pt_walk.h +++ b/drivers/gpu/drm/xe/xe_pt_walk.h @@ -111,7 +111,7 @@ static inline bool xe_pt_covers(u64 addr, u64 end, unsigned int level, } /** - * xe_pt_num_entries: Number of page-table entries of a given range at this + * xe_pt_num_entries - Number of page-table entries of a given range at this * level * @addr: Start address. * @end: End address. @@ -132,7 +132,7 @@ xe_pt_num_entries(u64 addr, u64 end, unsigned int level, } /** - * xe_pt_offset: Offset of the page-table entry for a given address. + * xe_pt_offset - Offset of the page-table entry for a given address. * @addr: The address. * @level: Page table level. * @walk: Walk info. From ec7cae58994c294470add15c5894ce521a1c0e35 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Tue, 14 Apr 2026 22:54:33 +0000 Subject: [PATCH 080/120] drm/xe: Fix type and parameter name mismatches in kernel-doc references Fix kernel-doc references that point to wrong type or parameter names: - xe_guc_capture_types.h: register_data_type -> capture_register_data_type to match actual enum name - xe_oa_types.h: enum @drm_xe_oa_format_type -> enum drm_xe_oa_format_type (spurious '@' before type name) - xe_pt_walk.h: @sizes -> @shifts to match actual struct member, @start -> @addr to match actual parameter name, page.table. -> page table. (typo) Assisted-by: GitHub Copilot:claude-sonnet-4.6 Reviewed-by: Brian Nguyen Link: https://patch.msgid.link/20260414225457.3687449-5-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_guc_capture_types.h | 2 +- drivers/gpu/drm/xe/xe_oa_types.h | 2 +- drivers/gpu/drm/xe/xe_pt_walk.h | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_capture_types.h b/drivers/gpu/drm/xe/xe_guc_capture_types.h index af7e21777b06..058a3f2eadce 100644 --- a/drivers/gpu/drm/xe/xe_guc_capture_types.h +++ b/drivers/gpu/drm/xe/xe_guc_capture_types.h @@ -32,7 +32,7 @@ struct __guc_mmio_reg_descr { /** * @data_type: data type of the register * Could be 32 bit, low or hi dword of a 64 bit, see enum - * register_data_type + * capture_register_data_type */ enum capture_register_data_type data_type; /** @flags: Flags for the register */ diff --git a/drivers/gpu/drm/xe/xe_oa_types.h b/drivers/gpu/drm/xe/xe_oa_types.h index 0c48c1e0c2c6..8906c3084b5f 100644 --- a/drivers/gpu/drm/xe/xe_oa_types.h +++ b/drivers/gpu/drm/xe/xe_oa_types.h @@ -67,7 +67,7 @@ struct xe_oa_format { u32 counter_select; /** @size: record size as written by HW (multiple of 64 byte cachelines) */ int size; - /** @type: of enum @drm_xe_oa_format_type */ + /** @type: of enum drm_xe_oa_format_type */ int type; /** @header: 32 or 64 bit report headers */ enum xe_oa_report_header header; diff --git a/drivers/gpu/drm/xe/xe_pt_walk.h b/drivers/gpu/drm/xe/xe_pt_walk.h index dcedfc9a28df..e91995fa703b 100644 --- a/drivers/gpu/drm/xe/xe_pt_walk.h +++ b/drivers/gpu/drm/xe/xe_pt_walk.h @@ -34,7 +34,7 @@ struct xe_pt_walk { * changed during the walk. */ const u64 *shifts; - /** @max_level: Highest populated level in @sizes */ + /** @max_level: Highest populated level in @shifts */ unsigned int max_level; /** * @shared_pt_mode: Whether to skip all entries that are private @@ -49,7 +49,7 @@ struct xe_pt_walk { /** * typedef xe_pt_entry_fn - gpu page-table-walk callback-function - * @parent: The parent page.table. + * @parent: The parent page table. * @offset: The offset (number of entries) into the page table. * @level: The level of @parent. * @addr: The virtual address. @@ -118,7 +118,7 @@ static inline bool xe_pt_covers(u64 addr, u64 end, unsigned int level, * @level: Page table level. * @walk: Walk info. * - * Return: The number of page table entries at this level between @start and + * Return: The number of page table entries at this level between @addr and * @end. */ static inline pgoff_t From c027f1a19180ea4e5aa29bab4e0871a21bb96c05 Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Thu, 26 Mar 2026 21:46:28 +0530 Subject: [PATCH 081/120] drm/xe/xe3p_lpg: Add Wa_18044193044 Add engine workaround Wa_18044193044 for graphics version 35.10 stepping A0..B0. Signed-off-by: Varun Gupta Reviewed-by: Tejas Upadhyay Link: https://patch.msgid.link/20260326161628.3566067-1-varun.gupta@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/regs/xe_gt_regs.h | 1 + drivers/gpu/drm/xe/xe_wa.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h index 87a99efa4765..16c87ce3f614 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -564,6 +564,7 @@ #define DIS_ATOMIC_CHAINING_TYPED_WRITES REG_BIT(3) #define TDL_CHICKEN XE_REG_MCR(0xe5f4, XE_REG_OPTION_MASKED) +#define BIT_APQ_OPT_DIS REG_BIT(14) #define QID_WAIT_FOR_THREAD_NOT_RUN_DISABLE REG_BIT(12) #define EUSTALL_PERF_SAMPLING_DISABLE REG_BIT(5) diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c index 2ec70be78bf9..49f5e3e4c7cc 100644 --- a/drivers/gpu/drm/xe/xe_wa.c +++ b/drivers/gpu/drm/xe/xe_wa.c @@ -609,6 +609,11 @@ static const struct xe_rtp_entry_sr engine_was[] = { FUNC(xe_rtp_match_first_render_or_compute)), XE_RTP_ACTIONS(SET(ROW_CHICKEN3, DIS_EU_GRF_POISON_TO_LSC)) }, + { XE_RTP_NAME("18044193044"), + XE_RTP_RULES(GRAPHICS_VERSION(3510), GRAPHICS_STEP(A0, B0), + FUNC(xe_rtp_match_first_render_or_compute)), + XE_RTP_ACTIONS(SET(TDL_CHICKEN, BIT_APQ_OPT_DIS)) + }, }; static const struct xe_rtp_entry_sr lrc_was[] = { From 35aff528f7297e949e5e19c9cd7fd748cf1cf21c Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Wed, 15 Apr 2026 22:54:28 +0000 Subject: [PATCH 082/120] drm/xe/eustall: Fix drm_dev_put called before stream disable in close In xe_eu_stall_stream_close(), drm_dev_put() is called before the stream is disabled and its resources are freed. If this drops the last reference, the device structures could be freed while the subsequent cleanup code still accesses them, leading to a use-after-free. Fix this by moving drm_dev_put() after all device accesses are complete. This matches the ordering in xe_oa_release(). Fixes: 9a0b11d4cf3b ("drm/xe/eustall: Add support to init, enable and disable EU stall sampling") Cc: Harish Chegondi Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Shuicheng Lin Reviewed-by: Harish Chegondi Link: https://patch.msgid.link/20260415225428.3399934-1-shuicheng.lin@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_eu_stall.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_eu_stall.c b/drivers/gpu/drm/xe/xe_eu_stall.c index c34408cfd292..dddcdd0bb7a3 100644 --- a/drivers/gpu/drm/xe/xe_eu_stall.c +++ b/drivers/gpu/drm/xe/xe_eu_stall.c @@ -869,14 +869,14 @@ static int xe_eu_stall_stream_close(struct inode *inode, struct file *file) struct xe_eu_stall_data_stream *stream = file->private_data; struct xe_gt *gt = stream->gt; - drm_dev_put(>->tile->xe->drm); - mutex_lock(>->eu_stall->stream_lock); xe_eu_stall_disable_locked(stream); xe_eu_stall_data_buf_destroy(stream); xe_eu_stall_stream_free(stream); mutex_unlock(>->eu_stall->stream_lock); + drm_dev_put(>->tile->xe->drm); + return 0; } From 0479934ec74f8f4e03ee654eb2e19074297e069f Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 16 Apr 2026 15:18:31 +0200 Subject: [PATCH 083/120] drm/xe/pf: Fix VF's scheduling priority reporting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When preparing number of impacted VFs parameter for the reporting helper function, we wrongly ended with adding +1 (representing PF) twice, since local variable total_vfs was already adjusted. This resulted in printing a message that was referring to an invalid VF: [] xe ... [drm] PF: Enabled 2 of 24 VFs [] xe ... [drm] PF: Tile0: GT0: PF..VF25 provisioned with 0(low) scheduling priority Fix variable initialization and adjust the loop accordingly. Fixes: fbbf73a81b84 ("drm/xe/pf: Force new VFs prorities only once") Signed-off-by: Michal Wajdeczko Reviewed-by: Piotr Piórkowski Link: https://patch.msgid.link/20260416131831.7302-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index e112aa148dab..2c9b85b84b1b 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -2626,14 +2626,14 @@ u32 xe_gt_sriov_pf_config_get_sched_priority(struct xe_gt *gt, unsigned int vfid */ void xe_gt_sriov_pf_config_force_sched_priority_locked(struct xe_gt *gt, u32 priority) { - unsigned int total_vfs = 1 + xe_gt_sriov_pf_get_totalvfs(gt); + unsigned int total_vfs = xe_gt_sriov_pf_get_totalvfs(gt); struct xe_gt_sriov_config *config; unsigned int n; xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); - for (n = 0; n < total_vfs; n++) { + for (n = 0; n <= total_vfs; n++) { config = pf_pick_vf_config(gt, VFID(n)); config->sched_priority = priority; } From ae314535c24aaacb847bae04514085a56bfc925c Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 16 Apr 2026 14:17:09 -0700 Subject: [PATCH 084/120] drm/xe: Drop skip_mtcfg descriptor flag The skip_mtcfg descriptor flag is unused and expected to remain that way. Drop it. Single-tile platforms are already identified by a zero/unset value for max_remote_tiles and don't need/use this flag to avoid trying to read out multi-tile configuration. PVC is currently the only multi-tile platform, and PVC uses MTCFG so this flag is not set. The current expectation is that if/when future multi-tile platforms show up, they will also use the MTCFG register in the same manner as PVC, meaning that they won't have any need to set 'skip_mtcfg' either. Even if a future platform does change how multi-tile configuration gets probed (e.g., using some different register), simply doing an early return from xe_info_probe_tile_count() would probably not be the correct logic to handle that anyway. Bspec: 53146 Reviewed-by: Xin Wang Link: https://patch.msgid.link/20260416-no-skip-mtcfg-v1-1-c8ea26d81530@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_device_types.h | 2 -- drivers/gpu/drm/xe/xe_pci.c | 4 ---- drivers/gpu/drm/xe/xe_pci_types.h | 1 - 3 files changed, 7 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 2ebe33a0dc07..e9e11bb1c65f 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -218,8 +218,6 @@ struct xe_device { u8 probe_display:1; /** @info.skip_guc_pc: Skip GuC based PM feature init */ u8 skip_guc_pc:1; - /** @info.skip_mtcfg: skip Multi-Tile configuration from MTCFG register */ - u8 skip_mtcfg:1; /** @info.skip_pcode: skip access to PCODE uC */ u8 skip_pcode:1; /** @info.needs_shared_vf_gt_wq: needs shared GT WQ on VF */ diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index b1b89d09e42b..41435f84aeb2 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -767,7 +767,6 @@ static int xe_info_init_early(struct xe_device *xe, desc->has_sriov; xe->info.has_sysctrl = desc->has_sysctrl; xe->info.skip_guc_pc = desc->skip_guc_pc; - xe->info.skip_mtcfg = desc->skip_mtcfg; xe->info.skip_pcode = desc->skip_pcode; xe->info.needs_scratch = desc->needs_scratch; xe->info.needs_shared_vf_gt_wq = desc->needs_shared_vf_gt_wq; @@ -809,9 +808,6 @@ static void xe_info_probe_tile_count(struct xe_device *xe) if (xe->info.tile_count == 1) return; - if (xe->info.skip_mtcfg) - return; - mmio = xe_root_tile_mmio(xe); /* diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h index 08386c5eca27..5b85e2c24b7b 100644 --- a/drivers/gpu/drm/xe/xe_pci_types.h +++ b/drivers/gpu/drm/xe/xe_pci_types.h @@ -60,7 +60,6 @@ struct xe_device_desc { u8 has_sysctrl:1; u8 needs_scratch:1; u8 skip_guc_pc:1; - u8 skip_mtcfg:1; u8 skip_pcode:1; u8 needs_shared_vf_gt_wq:1; }; From ffc2f7fd1c2b39ef50dd92556232deec653fc466 Mon Sep 17 00:00:00 2001 From: Karthik Poosa Date: Mon, 23 Mar 2026 17:28:36 +0530 Subject: [PATCH 085/120] drm/xe/hwmon: Read accepted power limit for CRI Update xe_hwmon_pcode_read_power_limit() and xe_hwmon_pcode_rmw_power_limit() to read the accepted power limit for discrete platforms post CRI. For platforms before CRI only the last written pcode value was available. From CRI onwards, pcode exposes a new param2 value 2 that allows reading the accepted power limit by the hardware. v2: - Read resolved power limit in xe_hwmon_pcode_rmw_power_limit() as well. (Badal) - Rephrase commit message. (Badal) - Add prepare_power_limit_param2() to prepare param2 for mailbox power limit read. Signed-off-by: Karthik Poosa Reviewed-by: Badal Nilawar Link: https://patch.msgid.link/20260323115836.3737300-1-karthik.poosa@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_hwmon.c | 21 ++++++++++++++------- drivers/gpu/drm/xe/xe_pcode_api.h | 3 ++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index 0fd4d4f1014a..0f92aa3fe8e8 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -180,6 +180,18 @@ struct xe_hwmon { struct xe_hwmon_thermal_info temp; }; +static inline int prepare_power_limit_param2(const struct xe_hwmon *hwmon) +{ + if (hwmon->boot_power_limit_read) { + if (hwmon->xe->info.platform >= XE_CRESCENTISLAND) + return READ_PL_ACCEPTED; + else + return READ_PL_FROM_PCODE; + } else { + return READ_PL_FROM_FW; + } +} + static int xe_hwmon_pcode_read_power_limit(const struct xe_hwmon *hwmon, u32 attr, int channel, u32 *uval) { @@ -191,9 +203,7 @@ static int xe_hwmon_pcode_read_power_limit(const struct xe_hwmon *hwmon, u32 att (channel == CHANNEL_CARD) ? READ_PSYSGPU_POWER_LIMIT : READ_PACKAGE_POWER_LIMIT, - hwmon->boot_power_limit_read ? - READ_PL_FROM_PCODE : READ_PL_FROM_FW), - &val0, &val1); + prepare_power_limit_param2(hwmon)), &val0, &val1); if (ret) { drm_dbg(&hwmon->xe->drm, "read failed ch %d val0 0x%08x, val1 0x%08x, ret %d\n", @@ -226,10 +236,7 @@ static int xe_hwmon_pcode_rmw_power_limit(const struct xe_hwmon *hwmon, u32 attr (channel == CHANNEL_CARD) ? READ_PSYSGPU_POWER_LIMIT : READ_PACKAGE_POWER_LIMIT, - hwmon->boot_power_limit_read ? - READ_PL_FROM_PCODE : READ_PL_FROM_FW), - &val0, &val1); - + prepare_power_limit_param2(hwmon)), &val0, &val1); if (ret) drm_dbg(&hwmon->xe->drm, "read failed ch %d val0 0x%08x, val1 0x%08x, ret %d\n", channel, val0, val1, ret); diff --git a/drivers/gpu/drm/xe/xe_pcode_api.h b/drivers/gpu/drm/xe/xe_pcode_api.h index b619030b9e17..94575c476e3d 100644 --- a/drivers/gpu/drm/xe/xe_pcode_api.h +++ b/drivers/gpu/drm/xe/xe_pcode_api.h @@ -50,8 +50,9 @@ #define WRITE_PSYSGPU_POWER_LIMIT 0x7 #define READ_PACKAGE_POWER_LIMIT 0x8 #define WRITE_PACKAGE_POWER_LIMIT 0x9 -#define READ_PL_FROM_FW 0x1 #define READ_PL_FROM_PCODE 0x0 +#define READ_PL_FROM_FW 0x1 +#define READ_PL_ACCEPTED 0x2 #define PCODE_THERMAL_INFO 0x25 #define READ_THERMAL_LIMITS 0x0 From c973f7a672d07b9c297c27011bab299bc61732ba Mon Sep 17 00:00:00 2001 From: Karthik Poosa Date: Fri, 17 Apr 2026 09:44:56 +0530 Subject: [PATCH 086/120] drm/xe/hwmon: Enable energy attributes for CRI Enable HWMON energy attributes for CRI, which are available through MMIO registers. Although these attributes can also be accessed via PMT, MMIO is preferred as it avoids dependency on ocode firmware load in late binding scenario. v2: Rephrase commit message. (Anshuman) Signed-off-by: Karthik Poosa Reviewed-by: Soham Purkait Link: https://patch.msgid.link/20260417041456.818668-1-karthik.poosa@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/regs/xe_pcode_regs.h | 3 +++ drivers/gpu/drm/xe/xe_hwmon.c | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/regs/xe_pcode_regs.h b/drivers/gpu/drm/xe/regs/xe_pcode_regs.h index 4b3c46eb858f..c63b409d7a82 100644 --- a/drivers/gpu/drm/xe/regs/xe_pcode_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_pcode_regs.h @@ -27,4 +27,7 @@ #define TEMP_SIGN_MASK REG_BIT(31) #define BMG_PACKAGE_TEMPERATURE XE_REG(0x138434) +#define CRI_PACKAGE_ENERGY_STATUS XE_REG(0x138120) +#define CRI_PLATFORM_ENERGY_STATUS XE_REG(0x138458) + #endif /* _XE_PCODE_REGS_H_ */ diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index 0f92aa3fe8e8..2e95989b78ca 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -303,7 +303,12 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg return GT_PERF_STATUS; break; case REG_PKG_ENERGY_STATUS: - if (xe->info.platform == XE_PVC && channel == CHANNEL_PKG) { + if (xe->info.platform == XE_CRESCENTISLAND) { + if (channel == CHANNEL_CARD) + return CRI_PLATFORM_ENERGY_STATUS; + else if (channel == CHANNEL_PKG) + return CRI_PACKAGE_ENERGY_STATUS; + } else if (xe->info.platform == XE_PVC && channel == CHANNEL_PKG) { return PVC_GT0_PLATFORM_ENERGY_STATUS; } else if ((xe->info.platform == XE_DG2) && (channel == CHANNEL_PKG)) { return PCU_CR_PACKAGE_ENERGY_STATUS; From 8de86d0a843c32ca9d36864bdb92f0376a830bce Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Fri, 17 Apr 2026 16:33:08 +0000 Subject: [PATCH 087/120] drm/xe/gsc: Fix BO leak on error in query_compatibility_version() When xe_gsc_read_out_header() fails, query_compatibility_version() returns directly instead of jumping to the out_bo label. This skips the xe_bo_unpin_map_no_vm() call, leaving the BO pinned and mapped with no remaining reference to free it. Fix by using goto out_bo so the error path properly cleans up the BO, consistent with the other error handling in the same function. Fixes: 0881cbe04077 ("drm/xe/gsc: Query GSC compatibility version") Cc: Daniele Ceraolo Spurio Reviewed-by: Daniele Ceraolo Spurio Link: https://patch.msgid.link/20260417163308.3416147-1-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_gsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c index e5c234f3d795..0d13e357fb43 100644 --- a/drivers/gpu/drm/xe/xe_gsc.c +++ b/drivers/gpu/drm/xe/xe_gsc.c @@ -166,7 +166,7 @@ static int query_compatibility_version(struct xe_gsc *gsc) &rd_offset); if (err) { xe_gt_err(gt, "HuC: invalid GSC reply for version query (err=%d)\n", err); - return err; + goto out_bo; } compat->major = version_query_rd(xe, &bo->vmap, rd_offset, proj_major); From 5627392001802a98ed6cf8cf79a303abd00d1c0f Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 20 Apr 2026 14:16:03 +0100 Subject: [PATCH 088/120] drm/xe/xelp: Fix Wa_18022495364 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Command parser relative MMIO addressing needs to be enabled when writing to the register. Signed-off-by: Tvrtko Ursulin Fixes: ca33cd271ef9 ("drm/xe/xelp: Add Wa_18022495364") Cc: Matt Roper Cc: Matthew Brost Cc: Thomas Hellström Cc: Rodrigo Vivi Reviewed-by: Matt Roper Link: https://patch.msgid.link/20260420131603.70357-1-tvrtko.ursulin@igalia.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_lrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index 9d12a0d2f0b5..c725cde4508d 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -1214,7 +1214,7 @@ static ssize_t setup_invalidate_state_cache_wa(struct xe_lrc *lrc, if (xe_gt_WARN_ON(lrc->gt, max_len < 3)) return -ENOSPC; - *cmd++ = MI_LOAD_REGISTER_IMM | MI_LRI_NUM_REGS(1); + *cmd++ = MI_LOAD_REGISTER_IMM | MI_LRI_LRM_CS_MMIO | MI_LRI_NUM_REGS(1); *cmd++ = CS_DEBUG_MODE2(0).addr; *cmd++ = REG_MASKED_FIELD_ENABLE(INSTRUCTION_STATE_CACHE_INVALIDATE); From 5f01da06878f48d0ee7919a0af6b2b7217c4ae61 Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Wed, 15 Apr 2026 21:55:24 -0700 Subject: [PATCH 089/120] drm/xe: Standardize pat_index to u16 type Ensure all pat_index definitions consistently use u16 type across the XE driver. This addresses two remaining instances where pat_index was incorrectly typed: - xe_vm_snapshot structure used int for pat_index field - xe_device pat.idx array used u32 instead of u16 This cleanup improves type consistency and ensures proper alignment with the PAT subsystem design. Signed-off-by: Xin Wang Reviewed-by: Matthew Auld Link: https://patch.msgid.link/20260416045526.536497-2-x.wang@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_device_types.h | 2 +- drivers/gpu/drm/xe/xe_vm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index e9e11bb1c65f..89437de3001a 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -401,7 +401,7 @@ struct xe_device { const struct xe_pat_table_entry *pat_primary_pta; /** @pat.pat_media_pta: media GT PAT entry for page table accesses */ const struct xe_pat_table_entry *pat_media_pta; - u32 idx[__XE_CACHE_LEVEL_COUNT]; + u16 idx[__XE_CACHE_LEVEL_COUNT]; } pat; /** @d3cold: Encapsulate d3cold related stuff */ diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 2408b547ca3d..f97c7af2f17c 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -4407,7 +4407,7 @@ struct xe_vm_snapshot { #define XE_VM_SNAP_FLAG_IS_NULL BIT(2) unsigned long flags; int uapi_mem_region; - int pat_index; + u16 pat_index; int cpu_caching; struct xe_bo *bo; void *data; From 369738a43a62c6ee46033ed1a26ed7d08c0e4b68 Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Wed, 15 Apr 2026 21:55:25 -0700 Subject: [PATCH 090/120] drm/xe/pat: Default XE_CACHE_NONE_COMPRESSION to invalid Initialize XE_CACHE_NONE_COMPRESSION PAT index to XE_PAT_INVALID_IDX by default, same as XE_CACHE_WB_COMPRESSION. Platforms that support this cache mode will override it in xe_pat_init_early(). This ensures that accidental use on unsupported platforms can be detected. A subsequent patch introduces a helper to assert on invalid PAT index access at all call sites. Suggested-by: Matthew Auld Cc: Matt Roper Reviewed-by: Matthew Auld Signed-off-by: Xin Wang Link: https://patch.msgid.link/20260416045526.536497-3-x.wang@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_pat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/xe/xe_pat.c b/drivers/gpu/drm/xe/xe_pat.c index 75aaae7b003d..fad5b5a5ed4a 100644 --- a/drivers/gpu/drm/xe/xe_pat.c +++ b/drivers/gpu/drm/xe/xe_pat.c @@ -559,6 +559,7 @@ static const struct xe_pat_ops xe3p_xpc_pat_ops = { void xe_pat_init_early(struct xe_device *xe) { xe->pat.idx[XE_CACHE_WB_COMPRESSION] = XE_PAT_INVALID_IDX; + xe->pat.idx[XE_CACHE_NONE_COMPRESSION] = XE_PAT_INVALID_IDX; if (GRAPHICS_VERx100(xe) == 3511) { xe->pat.ops = &xe3p_xpc_pat_ops; xe->pat.table = xe3p_xpc_pat_table; From dc9ccf14dc2ad44e3df4928015923735f0101bfd Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Wed, 15 Apr 2026 21:55:26 -0700 Subject: [PATCH 091/120] drm/xe/pat: Introduce xe_cache_pat_idx() macro helper Wrap pat.idx[] reads with xe_cache_pat_idx() so invalid PAT index use is caught by xe_assert() in debug builds. Suggested-by: Matthew Auld Reviewed-by: Matthew Auld Signed-off-by: Xin Wang Link: https://patch.msgid.link/20260416045526.536497-4-x.wang@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/display/xe_fb_pin.c | 11 ++++++----- drivers/gpu/drm/xe/tests/xe_migrate.c | 3 ++- drivers/gpu/drm/xe/xe_ggtt.c | 7 ++++--- drivers/gpu/drm/xe/xe_migrate.c | 15 ++++++++------- drivers/gpu/drm/xe/xe_pat.h | 8 ++++++++ drivers/gpu/drm/xe/xe_pt.c | 3 ++- drivers/gpu/drm/xe/xe_vm.c | 6 +++--- 7 files changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index e45a1e7a4670..d670a3cf1b84 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -14,6 +14,7 @@ #include "xe_device.h" #include "xe_display_vma.h" #include "xe_ggtt.h" +#include "xe_pat.h" #include "xe_pm.h" #include "xe_vram_types.h" @@ -24,7 +25,7 @@ write_dpt_rotated(struct xe_bo *bo, struct iosys_map *map, u32 *dpt_ofs, u32 bo_ struct xe_device *xe = xe_bo_device(bo); struct xe_ggtt *ggtt = xe_device_get_root_tile(xe)->mem.ggtt; u32 column, row; - u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe->pat.idx[XE_CACHE_NONE]); + u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe_cache_pat_idx(xe, XE_CACHE_NONE)); /* TODO: Maybe rewrite so we can traverse the bo addresses sequentially, * by writing dpt/ggtt in a different order? @@ -64,7 +65,7 @@ write_dpt_remapped_linear(struct xe_bo *bo, struct iosys_map *map, struct xe_device *xe = xe_bo_device(bo); struct xe_ggtt *ggtt = xe_device_get_root_tile(xe)->mem.ggtt; const u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, - xe->pat.idx[XE_CACHE_NONE]); + xe_cache_pat_idx(xe, XE_CACHE_NONE)); unsigned int offset = plane->offset * XE_PAGE_SIZE; unsigned int size = plane->size; @@ -87,7 +88,7 @@ write_dpt_remapped_tiled(struct xe_bo *bo, struct iosys_map *map, struct xe_device *xe = xe_bo_device(bo); struct xe_ggtt *ggtt = xe_device_get_root_tile(xe)->mem.ggtt; const u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, - xe->pat.idx[XE_CACHE_NONE]); + xe_cache_pat_idx(xe, XE_CACHE_NONE)); unsigned int offset, column, row; for (row = 0; row < plane->height; row++) { @@ -190,7 +191,7 @@ static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb, return PTR_ERR(dpt); if (view->type == I915_GTT_VIEW_NORMAL) { - u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe->pat.idx[XE_CACHE_NONE]); + u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe_cache_pat_idx(xe, XE_CACHE_NONE)); u32 x; for (x = 0; x < size / XE_PAGE_SIZE; x++) { @@ -306,7 +307,7 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, /* display uses tiles instead of bytes here, so convert it back.. */ size = intel_rotation_info_size(&view->rotated) * XE_PAGE_SIZE; - pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe->pat.idx[XE_CACHE_NONE]); + pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe_cache_pat_idx(xe, XE_CACHE_NONE)); vma->node = xe_ggtt_insert_node_transform(ggtt, bo, pte, ALIGN(size, align), align, view->type == I915_GTT_VIEW_NORMAL ? diff --git a/drivers/gpu/drm/xe/tests/xe_migrate.c b/drivers/gpu/drm/xe/tests/xe_migrate.c index 34e2f0f4631f..50a97705e0ac 100644 --- a/drivers/gpu/drm/xe/tests/xe_migrate.c +++ b/drivers/gpu/drm/xe/tests/xe_migrate.c @@ -9,6 +9,7 @@ #include "tests/xe_kunit_helpers.h" #include "tests/xe_pci_test.h" +#include "xe_pat.h" #include "xe_pci.h" #include "xe_pm.h" @@ -246,7 +247,7 @@ static void xe_migrate_sanity_test(struct xe_migrate *m, struct kunit *test, /* First part of the test, are we updating our pagetable bo with a new entry? */ xe_map_wr(xe, &bo->vmap, XE_PAGE_SIZE * (NUM_KERNEL_PDE - 1), u64, 0xdeaddeadbeefbeef); - expected = m->q->vm->pt_ops->pte_encode_bo(pt, 0, xe->pat.idx[XE_CACHE_WB], 0); + expected = m->q->vm->pt_ops->pte_encode_bo(pt, 0, xe_cache_pat_idx(xe, XE_CACHE_WB), 0); if (m->q->vm->flags & XE_VM_FLAG_64K) expected |= XE_PTE_PS64; if (xe_bo_is_vram(pt)) diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index 3552fa3cac4b..a351c578b170 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -24,6 +24,7 @@ #include "xe_gt_types.h" #include "xe_map.h" #include "xe_mmio.h" +#include "xe_pat.h" #include "xe_pm.h" #include "xe_res_cursor.h" #include "xe_sriov.h" @@ -258,7 +259,7 @@ static u64 xe_ggtt_get_pte(struct xe_ggtt *ggtt, u64 addr) static void xe_ggtt_clear(struct xe_ggtt *ggtt, u64 start, u64 size) { - u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[XE_CACHE_WB]; + u16 pat_index = xe_cache_pat_idx(tile_to_xe(ggtt->tile), XE_CACHE_WB); u64 end = start + size - 1; u64 scratch_pte; @@ -723,7 +724,7 @@ static void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, void xe_ggtt_map_bo_unlocked(struct xe_ggtt *ggtt, struct xe_bo *bo) { u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : XE_CACHE_WB; - u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode]; + u16 pat_index = xe_cache_pat_idx(tile_to_xe(ggtt->tile), cache_mode); u64 pte; mutex_lock(&ggtt->lock); @@ -840,7 +841,7 @@ static int __xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo, bo->ggtt_node[tile_id] = NULL; } else { u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : XE_CACHE_WB; - u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode]; + u16 pat_index = xe_cache_pat_idx(tile_to_xe(ggtt->tile), cache_mode); u64 pte = ggtt->pt_ops->pte_encode_flags(bo, pat_index); xe_ggtt_map_bo(ggtt, bo->ggtt_node[tile_id], bo, pte); diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c index 5fdc89ed5256..a87fbc1e9fb1 100644 --- a/drivers/gpu/drm/xe/xe_migrate.c +++ b/drivers/gpu/drm/xe/xe_migrate.c @@ -31,6 +31,7 @@ #include "xe_map.h" #include "xe_mem_pool.h" #include "xe_mocs.h" +#include "xe_pat.h" #include "xe_printk.h" #include "xe_pt.h" #include "xe_res_cursor.h" @@ -217,7 +218,7 @@ static void xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m, struct xe_vm *vm, u32 *ofs) { struct xe_device *xe = tile_to_xe(tile); - u16 pat_index = xe->pat.idx[XE_CACHE_WB]; + u16 pat_index = xe_cache_pat_idx(xe, XE_CACHE_WB); u8 id = tile->id; u32 num_entries = NUM_PT_SLOTS, num_level = vm->pt_root[id]->level; #define VRAM_IDENTITY_MAP_COUNT 2 @@ -337,7 +338,7 @@ static void xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m, * if flat ccs is enabled. */ if (GRAPHICS_VER(xe) >= 20 && xe_device_has_flat_ccs(xe)) { - u16 comp_pat_index = xe->pat.idx[XE_CACHE_NONE_COMPRESSION]; + u16 comp_pat_index = xe_cache_pat_idx(xe, XE_CACHE_NONE_COMPRESSION); u64 vram_offset = IDENTITY_OFFSET + DIV_ROUND_UP_ULL(actual_phy_size, SZ_1G); u64 pt31_ofs = xe_bo_size(bo) - XE_PAGE_SIZE; @@ -637,10 +638,10 @@ static void emit_pte(struct xe_migrate *m, /* Indirect access needs compression enabled uncached PAT index */ if (GRAPHICS_VERx100(xe) >= 2000) - pat_index = is_comp_pte ? xe->pat.idx[XE_CACHE_NONE_COMPRESSION] : - xe->pat.idx[XE_CACHE_WB]; + pat_index = is_comp_pte ? xe_cache_pat_idx(xe, XE_CACHE_NONE_COMPRESSION) : + xe_cache_pat_idx(xe, XE_CACHE_WB); else - pat_index = xe->pat.idx[XE_CACHE_WB]; + pat_index = xe_cache_pat_idx(xe, XE_CACHE_WB); ptes = DIV_ROUND_UP(size, XE_PAGE_SIZE); @@ -1876,7 +1877,7 @@ __xe_migrate_update_pgtables(struct xe_migrate *m, /* For sysmem PTE's, need to map them in our hole.. */ if (!IS_DGFX(xe)) { - u16 pat_index = xe->pat.idx[XE_CACHE_WB]; + u16 pat_index = xe_cache_pat_idx(xe, XE_CACHE_WB); u32 ptes, ofs; ppgtt_ofs = NUM_KERNEL_PDE - 1; @@ -2098,7 +2099,7 @@ static void build_pt_update_batch_sram(struct xe_migrate *m, struct drm_pagemap_addr *sram_addr, u32 size, int level) { - u16 pat_index = tile_to_xe(m->tile)->pat.idx[XE_CACHE_WB]; + u16 pat_index = xe_cache_pat_idx(tile_to_xe(m->tile), XE_CACHE_WB); u64 gpu_page_size = 0x1ull << xe_pt_shift(level); u32 ptes; int i = 0; diff --git a/drivers/gpu/drm/xe/xe_pat.h b/drivers/gpu/drm/xe/xe_pat.h index a1e287c08f57..7060f66e1d63 100644 --- a/drivers/gpu/drm/xe/xe_pat.h +++ b/drivers/gpu/drm/xe/xe_pat.h @@ -82,4 +82,12 @@ bool xe_pat_index_get_comp_en(struct xe_device *xe, u16 pat_index); */ u16 xe_pat_index_get_l3_policy(struct xe_device *xe, u16 pat_index); +#define xe_cache_pat_idx(xe, cache_mode) ({ \ + const struct xe_device *__xedev = (xe); \ + enum xe_cache_level __mode = (cache_mode); \ + xe_assert(__xedev, __mode < __XE_CACHE_LEVEL_COUNT); \ + xe_assert(__xedev, __xedev->pat.idx[__mode] != XE_PAT_INVALID_IDX); \ + __xedev->pat.idx[__mode]; \ +}) + #endif diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index 8e5f4f0dea3f..2669ff5ee747 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -14,6 +14,7 @@ #include "xe_gt_stats.h" #include "xe_migrate.h" #include "xe_page_reclaim.h" +#include "xe_pat.h" #include "xe_pt_types.h" #include "xe_pt_walk.h" #include "xe_res_cursor.h" @@ -62,7 +63,7 @@ static u64 __xe_pt_empty_pte(struct xe_tile *tile, struct xe_vm *vm, unsigned int level) { struct xe_device *xe = tile_to_xe(tile); - u16 pat_index = xe->pat.idx[XE_CACHE_WB]; + u16 pat_index = xe_cache_pat_idx(xe, XE_CACHE_WB); u8 id = tile->id; if (!xe_vm_has_scratch(vm)) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index f97c7af2f17c..5f4220125c76 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -1399,9 +1399,9 @@ static u16 pde_pat_index(struct xe_bo *bo) * something which is always safe). */ if (!xe_bo_is_vram(bo) && bo->ttm.ttm->caching == ttm_cached) - pat_index = xe->pat.idx[XE_CACHE_WB]; + pat_index = xe_cache_pat_idx(xe, XE_CACHE_WB); else - pat_index = xe->pat.idx[XE_CACHE_NONE]; + pat_index = xe_cache_pat_idx(xe, XE_CACHE_NONE); xe_assert(xe, pat_index <= 3); @@ -4204,7 +4204,7 @@ struct dma_fence *xe_vm_bind_kernel_bo(struct xe_vm *vm, struct xe_bo *bo, ops = vm_bind_ioctl_ops_create(vm, &vops, bo, 0, addr, xe_bo_size(bo), DRM_XE_VM_BIND_OP_MAP, 0, 0, - vm->xe->pat.idx[cache_lvl]); + xe_cache_pat_idx(vm->xe, cache_lvl)); if (IS_ERR(ops)) { err = PTR_ERR(ops); goto release_vm_lock; From 12ef528d78adc8ea4e7e3db594f3bcac327e79fa Mon Sep 17 00:00:00 2001 From: Zhanjun Dong Date: Thu, 26 Mar 2026 14:10:17 -0400 Subject: [PATCH 092/120] drm/xe: Fix null pointer dereference in devcoredump cleanup In xe_devcoredump_snapshot_free(), ss->gt may be NULL when the snapshot was never fully populated (e.g., when cleanup is triggered without a prior capture). Guard the xe_guc_capture_put_matched_nodes() call with IS_ERR_OR_NULL() to prevent a null dereference. In xe_devcoredump_free(), the deferred work is only queued when a coredump is captured, so guard cancel_work_sync() with a check on coredump->captured. Signed-off-by: Zhanjun Dong Reviewed-by: Vinay Belgaumkar Signed-off-by: Vinay Belgaumkar Link: https://patch.msgid.link/20260326181017.2060209-1-zhanjun.dong@intel.com --- drivers/gpu/drm/xe/xe_devcoredump.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c index 558a1a9841a0..ec206f512795 100644 --- a/drivers/gpu/drm/xe/xe_devcoredump.c +++ b/drivers/gpu/drm/xe/xe_devcoredump.c @@ -149,7 +149,8 @@ static void xe_devcoredump_snapshot_free(struct xe_devcoredump_snapshot *ss) xe_guc_ct_snapshot_free(ss->guc.ct); ss->guc.ct = NULL; - xe_guc_capture_put_matched_nodes(&ss->gt->uc.guc); + if (!IS_ERR_OR_NULL(ss->gt)) + xe_guc_capture_put_matched_nodes(&ss->gt->uc.guc); ss->matched_node = NULL; xe_guc_exec_queue_snapshot_free(ss->ge); @@ -254,7 +255,8 @@ static void xe_devcoredump_free(void *data) if (!data || !coredump_to_xe(coredump)) return; - cancel_work_sync(&coredump->snapshot.work); + if (coredump->captured) + cancel_work_sync(&coredump->snapshot.work); mutex_lock(&coredump->lock); From ee18d39a087792d7c11e6e87b546aff435a3cc58 Mon Sep 17 00:00:00 2001 From: Riana Tauro Date: Thu, 9 Apr 2026 13:03:19 +0530 Subject: [PATCH 093/120] drm/drm_ras: Add clear-error-counter netlink command to drm_ras Introduce a new 'clear-error-counter' drm_ras command to reset the counter value for a specific error counter of a given node. The command is a 'do' netlink request with 'node-id' and 'error-id' as parameters with no response payload. Usage: $ sudo ynl --family drm_ras --do clear-error-counter --json \ '{"node-id":1, "error-id":1}' None Cc: Jakub Kicinski Cc: Zack McKevitt Cc: Lijo Lazar Cc: Hawking Zhang Cc: David S. Miller Cc: Paolo Abeni Cc: Eric Dumazet Signed-off-by: Riana Tauro Reviewed-by: Jakub Kicinski Reviewed-by: Raag Jadav Link: https://patch.msgid.link/20260409073318.2909379-5-riana.tauro@intel.com Signed-off-by: Rodrigo Vivi Acked-by: Maxime Ripard --- Documentation/gpu/drm-ras.rst | 8 +++++ Documentation/netlink/specs/drm_ras.yaml | 13 ++++++- drivers/gpu/drm/drm_ras.c | 43 +++++++++++++++++++++++- drivers/gpu/drm/drm_ras_nl.c | 13 +++++++ drivers/gpu/drm/drm_ras_nl.h | 2 ++ include/drm/drm_ras.h | 11 ++++++ include/uapi/drm/drm_ras.h | 1 + 7 files changed, 89 insertions(+), 2 deletions(-) diff --git a/Documentation/gpu/drm-ras.rst b/Documentation/gpu/drm-ras.rst index 70b246a78fc8..4636e68f5678 100644 --- a/Documentation/gpu/drm-ras.rst +++ b/Documentation/gpu/drm-ras.rst @@ -52,6 +52,8 @@ User space tools can: as a parameter. * Query specific error counter values with the ``get-error-counter`` command, using both ``node-id`` and ``error-id`` as parameters. +* Clear specific error counters with the ``clear-error-counter`` command, using both + ``node-id`` and ``error-id`` as parameters. YAML-based Interface -------------------- @@ -101,3 +103,9 @@ Example: Query an error counter for a given node sudo ynl --family drm_ras --do get-error-counter --json '{"node-id":0, "error-id":1}' {'error-id': 1, 'error-name': 'error_name1', 'error-value': 0} +Example: Clear an error counter for a given node + +.. code-block:: bash + + sudo ynl --family drm_ras --do clear-error-counter --json '{"node-id":0, "error-id":1}' + None diff --git a/Documentation/netlink/specs/drm_ras.yaml b/Documentation/netlink/specs/drm_ras.yaml index 79af25dac3c5..e113056f8c01 100644 --- a/Documentation/netlink/specs/drm_ras.yaml +++ b/Documentation/netlink/specs/drm_ras.yaml @@ -99,7 +99,7 @@ operations: flags: [admin-perm] do: request: - attributes: + attributes: &id-attrs - node-id - error-id reply: @@ -113,3 +113,14 @@ operations: - node-id reply: attributes: *errorinfo + - + name: clear-error-counter + doc: >- + Clear error counter for a given node. + The request includes the error-id and node-id of the + counter to be cleared. + attribute-set: error-counter-attrs + flags: [admin-perm] + do: + request: + attributes: *id-attrs diff --git a/drivers/gpu/drm/drm_ras.c b/drivers/gpu/drm/drm_ras.c index b2fa5ab86d87..d6eab29a1394 100644 --- a/drivers/gpu/drm/drm_ras.c +++ b/drivers/gpu/drm/drm_ras.c @@ -26,7 +26,7 @@ * efficient lookup by ID. Nodes can be registered or unregistered * dynamically at runtime. * - * A Generic Netlink family `drm_ras` exposes two main operations to + * A Generic Netlink family `drm_ras` exposes the below operations to * userspace: * * 1. LIST_NODES: Dump all currently registered RAS nodes. @@ -37,6 +37,10 @@ * Returns all counters of a node if only Node ID is provided or specific * error counters. * + * 3. CLEAR_ERROR_COUNTER: Clear error counter of a given node. + * Userspace must provide Node ID, Error ID. + * Clears specific error counter of a node if supported. + * * Node registration: * * - drm_ras_node_register(): Registers a new node and assigns @@ -66,6 +70,8 @@ * operation, fetching all counters from a specific node. * - drm_ras_nl_get_error_counter_doit(): Implements the GET_ERROR_COUNTER doit * operation, fetching a counter value from a specific node. + * - drm_ras_nl_clear_error_counter_doit(): Implements the CLEAR_ERROR_COUNTER doit + * operation, clearing a counter value from a specific node. */ static DEFINE_XARRAY_ALLOC(drm_ras_xa); @@ -314,6 +320,41 @@ int drm_ras_nl_get_error_counter_doit(struct sk_buff *skb, return doit_reply_value(info, node_id, error_id); } +/** + * drm_ras_nl_clear_error_counter_doit() - Clear an error counter of a node + * @skb: Netlink message buffer + * @info: Generic Netlink info containing attributes of the request + * + * Extracts the node ID and error ID from the netlink attributes and + * clears the current value. + * + * Return: 0 on success, or negative errno on failure. + */ +int drm_ras_nl_clear_error_counter_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct drm_ras_node *node; + u32 node_id, error_id; + + if (!info->attrs || + GENL_REQ_ATTR_CHECK(info, DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID) || + GENL_REQ_ATTR_CHECK(info, DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID)) + return -EINVAL; + + node_id = nla_get_u32(info->attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID]); + error_id = nla_get_u32(info->attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID]); + + node = xa_load(&drm_ras_xa, node_id); + if (!node || !node->clear_error_counter) + return -ENOENT; + + if (error_id < node->error_counter_range.first || + error_id > node->error_counter_range.last) + return -EINVAL; + + return node->clear_error_counter(node, error_id); +} + /** * drm_ras_node_register() - Register a new RAS node * @node: Node structure to register diff --git a/drivers/gpu/drm/drm_ras_nl.c b/drivers/gpu/drm/drm_ras_nl.c index 16803d0c4a44..dea1c1b2494e 100644 --- a/drivers/gpu/drm/drm_ras_nl.c +++ b/drivers/gpu/drm/drm_ras_nl.c @@ -22,6 +22,12 @@ static const struct nla_policy drm_ras_get_error_counter_dump_nl_policy[DRM_RAS_ [DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID] = { .type = NLA_U32, }, }; +/* DRM_RAS_CMD_CLEAR_ERROR_COUNTER - do */ +static const struct nla_policy drm_ras_clear_error_counter_nl_policy[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID + 1] = { + [DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID] = { .type = NLA_U32, }, + [DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID] = { .type = NLA_U32, }, +}; + /* Ops table for drm_ras */ static const struct genl_split_ops drm_ras_nl_ops[] = { { @@ -43,6 +49,13 @@ static const struct genl_split_ops drm_ras_nl_ops[] = { .maxattr = DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, }, + { + .cmd = DRM_RAS_CMD_CLEAR_ERROR_COUNTER, + .doit = drm_ras_nl_clear_error_counter_doit, + .policy = drm_ras_clear_error_counter_nl_policy, + .maxattr = DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, }; struct genl_family drm_ras_nl_family __ro_after_init = { diff --git a/drivers/gpu/drm/drm_ras_nl.h b/drivers/gpu/drm/drm_ras_nl.h index 06ccd9342773..a398643572a5 100644 --- a/drivers/gpu/drm/drm_ras_nl.h +++ b/drivers/gpu/drm/drm_ras_nl.h @@ -18,6 +18,8 @@ int drm_ras_nl_get_error_counter_doit(struct sk_buff *skb, struct genl_info *info); int drm_ras_nl_get_error_counter_dumpit(struct sk_buff *skb, struct netlink_callback *cb); +int drm_ras_nl_clear_error_counter_doit(struct sk_buff *skb, + struct genl_info *info); extern struct genl_family drm_ras_nl_family; diff --git a/include/drm/drm_ras.h b/include/drm/drm_ras.h index 5d50209e51db..f2a787bc4f64 100644 --- a/include/drm/drm_ras.h +++ b/include/drm/drm_ras.h @@ -58,6 +58,17 @@ struct drm_ras_node { int (*query_error_counter)(struct drm_ras_node *node, u32 error_id, const char **name, u32 *val); + /** + * @clear_error_counter: + * + * This callback is used by drm_ras to clear a specific error counter. + * Driver should implement this callback to support clearing error counters + * of a node. + * + * Returns: 0 on success, negative error code on failure. + */ + int (*clear_error_counter)(struct drm_ras_node *node, u32 error_id); + /** @priv: Driver private data */ void *priv; }; diff --git a/include/uapi/drm/drm_ras.h b/include/uapi/drm/drm_ras.h index 5f40fa5b869d..218a3ee86805 100644 --- a/include/uapi/drm/drm_ras.h +++ b/include/uapi/drm/drm_ras.h @@ -41,6 +41,7 @@ enum { enum { DRM_RAS_CMD_LIST_NODES = 1, DRM_RAS_CMD_GET_ERROR_COUNTER, + DRM_RAS_CMD_CLEAR_ERROR_COUNTER, __DRM_RAS_CMD_MAX, DRM_RAS_CMD_MAX = (__DRM_RAS_CMD_MAX - 1) From e12be2535cca2e0b457175a0ee25d1c0d1fb909f Mon Sep 17 00:00:00 2001 From: Riana Tauro Date: Thu, 9 Apr 2026 13:03:20 +0530 Subject: [PATCH 094/120] drm/xe/xe_drm_ras: Add support for clear-error-counter in XE drm_ras Add support for clear-error-counter command in XE drm_ras This resets the counter value. Usage: $ sudo ynl --family drm_ras --do clear-error-counter --json \ '{"node-id":1, "error-id":1}' None Signed-off-by: Riana Tauro Reviewed-by: Raag Jadav Link: https://patch.msgid.link/20260409073318.2909379-6-riana.tauro@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_drm_ras.c | 35 +++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_drm_ras.c b/drivers/gpu/drm/xe/xe_drm_ras.c index e07dc23a155e..c21c8b428de6 100644 --- a/drivers/gpu/drm/xe/xe_drm_ras.c +++ b/drivers/gpu/drm/xe/xe_drm_ras.c @@ -27,6 +27,16 @@ static int hw_query_error_counter(struct xe_drm_ras_counter *info, return 0; } +static int hw_clear_error_counter(struct xe_drm_ras_counter *info, u32 error_id) +{ + if (!info || !info[error_id].name) + return -ENOENT; + + atomic_set(&info[error_id].counter, 0); + + return 0; +} + static int query_uncorrectable_error_counter(struct drm_ras_node *ep, u32 error_id, const char **name, u32 *val) { @@ -37,6 +47,15 @@ static int query_uncorrectable_error_counter(struct drm_ras_node *ep, u32 error_ return hw_query_error_counter(info, error_id, name, val); } +static int clear_uncorrectable_error_counter(struct drm_ras_node *node, u32 error_id) +{ + struct xe_device *xe = node->priv; + struct xe_drm_ras *ras = &xe->ras; + struct xe_drm_ras_counter *info = ras->info[DRM_XE_RAS_ERR_SEV_UNCORRECTABLE]; + + return hw_clear_error_counter(info, error_id); +} + static int query_correctable_error_counter(struct drm_ras_node *ep, u32 error_id, const char **name, u32 *val) { @@ -47,6 +66,15 @@ static int query_correctable_error_counter(struct drm_ras_node *ep, u32 error_id return hw_query_error_counter(info, error_id, name, val); } +static int clear_correctable_error_counter(struct drm_ras_node *node, u32 error_id) +{ + struct xe_device *xe = node->priv; + struct xe_drm_ras *ras = &xe->ras; + struct xe_drm_ras_counter *info = ras->info[DRM_XE_RAS_ERR_SEV_CORRECTABLE]; + + return hw_clear_error_counter(info, error_id); +} + static struct xe_drm_ras_counter *allocate_and_copy_counters(struct xe_device *xe) { struct xe_drm_ras_counter *counter; @@ -92,10 +120,13 @@ static int assign_node_params(struct xe_device *xe, struct drm_ras_node *node, if (IS_ERR(ras->info[severity])) return PTR_ERR(ras->info[severity]); - if (severity == DRM_XE_RAS_ERR_SEV_CORRECTABLE) + if (severity == DRM_XE_RAS_ERR_SEV_CORRECTABLE) { node->query_error_counter = query_correctable_error_counter; - else + node->clear_error_counter = clear_correctable_error_counter; + } else { node->query_error_counter = query_uncorrectable_error_counter; + node->clear_error_counter = clear_uncorrectable_error_counter; + } return 0; } From 016ccdb674b8c899940b3944952c96a6a490d10a Mon Sep 17 00:00:00 2001 From: Jia Yao Date: Fri, 17 Apr 2026 05:59:16 +0000 Subject: [PATCH 095/120] drm/xe/uapi: Reject coh_none PAT index for CPU cached memory in madvise MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add validation in xe_vm_madvise_ioctl() to reject PAT indices with XE_COH_NONE coherency mode when applied to CPU cached memory. Using coh_none with CPU cached buffers is a security issue. When the kernel clears pages before reallocation, the clear operation stays in CPU cache (dirty). GPU with coh_none can bypass CPU caches and read stale sensitive data directly from DRAM, potentially leaking data from previously freed pages of other processes. This aligns with the existing validation in vm_bind path (xe_vm_bind_ioctl_validate_bo). v2(Matthew brost) - Add fixes - Move one debug print to better place v3(Matthew Auld) - Should be drm/xe/uapi - More Cc v4(Shuicheng Lin) - Fix kmem leak issues by the way v5 - Remove kmem leak because it has been merged by another patch v6 - Remove the fix which is not related to current fix v7 - No change v8 - Rebase v9 - Limit the restrictions to iGPU v10 - No change Fixes: ada7486c5668 ("drm/xe: Implement madvise ioctl for xe") Cc: # v6.18+ Cc: Shuicheng Lin Cc: Mathew Alwin Cc: Michal Mrozek Cc: Matthew Brost Cc: Matthew Auld Signed-off-by: Jia Yao Reviewed-by: Matthew Auld Acked-by: Michal Mrozek Acked-by: José Roberto de Souza Signed-off-by: Matthew Auld Link: https://patch.msgid.link/20260417055917.2027459-2-jia.yao@intel.com --- drivers/gpu/drm/xe/xe_vm_madvise.c | 47 ++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c index 66f00d3f5c07..c78906dea82b 100644 --- a/drivers/gpu/drm/xe/xe_vm_madvise.c +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c @@ -621,6 +621,45 @@ static int xe_madvise_purgeable_retained_to_user(const struct xe_madvise_details return 0; } +static bool check_pat_args_are_sane(struct xe_device *xe, + struct xe_vmas_in_madvise_range *madvise_range, + u16 pat_index) +{ + u16 coh_mode = xe_pat_index_get_coh_mode(xe, pat_index); + int i; + + /* + * Using coh_none with CPU cached buffers is not allowed on iGPU. + * On iGPU the GPU shares the LLC with the CPU, so with coh_none + * the GPU bypasses CPU caches and reads directly from DRAM, + * potentially seeing stale sensitive data from previously freed + * pages. On dGPU this restriction does not apply, because the + * platform does not provide a non-coherent system memory access + * path that would violate the DMA coherency contract. + */ + if (coh_mode != XE_COH_NONE || IS_DGFX(xe)) + return true; + + for (i = 0; i < madvise_range->num_vmas; i++) { + struct xe_vma *vma = madvise_range->vmas[i]; + struct xe_bo *bo = xe_vma_bo(vma); + + if (bo) { + /* BO with WB caching + COH_NONE is not allowed */ + if (XE_IOCTL_DBG(xe, bo->cpu_caching == DRM_XE_GEM_CPU_CACHING_WB)) + return false; + /* Imported dma-buf without caching info, assume cached */ + if (XE_IOCTL_DBG(xe, !bo->cpu_caching)) + return false; + } else if (XE_IOCTL_DBG(xe, xe_vma_is_cpu_addr_mirror(vma) || + xe_vma_is_userptr(vma))) + /* System memory (userptr/SVM) is always CPU cached */ + return false; + } + + return true; +} + static bool check_bo_args_are_sane(struct xe_vm *vm, struct xe_vma **vmas, int num_vmas, u32 atomic_val) { @@ -750,6 +789,14 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil } } + if (args->type == DRM_XE_MEM_RANGE_ATTR_PAT) { + if (!check_pat_args_are_sane(xe, &madvise_range, + args->pat_index.val)) { + err = -EINVAL; + goto free_vmas; + } + } + if (madvise_range.has_bo_vmas) { if (args->type == DRM_XE_MEM_RANGE_ATTR_ATOMIC) { if (!check_bo_args_are_sane(vm, madvise_range.vmas, From 4d58d7535e826a3175527b6174502f0db319d7f6 Mon Sep 17 00:00:00 2001 From: Jia Yao Date: Fri, 17 Apr 2026 05:59:17 +0000 Subject: [PATCH 096/120] drm/xe/uapi: Reject coh_none PAT index for CPU_ADDR_MIRROR Add validation in xe_vm_bind_ioctl() to reject PAT indices with XE_COH_NONE coherency mode when used with DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR. CPU address mirror mappings use system memory that is CPU cached, which makes them incompatible with COH_NONE PAT indices. Allowing COH_NONE with CPU cached buffers is a security risk, as the GPU may bypass CPU caches and read stale sensitive data from DRAM. Although CPU_ADDR_MIRROR does not create an immediate mapping, the backing system memory is still CPU cached. Apply the same PAT coherency restrictions as DRM_XE_VM_BIND_OP_MAP_USERPTR. v2: - Correct fix tag v6: - No change v7: - Correct fix tag v8: - Rebase v9: - Limit the restrictions to iGPU v10: - Just add the iGPU logic but keep dGPU logic Fixes: b43e864af0d4 ("drm/xe/uapi: Add DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR") Cc: # v6.15+ Cc: Shuicheng Lin Cc: Mathew Alwin Cc: Michal Mrozek Cc: Matthew Brost Cc: Matthew Auld Signed-off-by: Jia Yao Reviewed-by: Matthew Auld Acked-by: Michal Mrozek Signed-off-by: Matthew Auld Link: https://patch.msgid.link/20260417055917.2027459-3-jia.yao@intel.com --- drivers/gpu/drm/xe/xe_vm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 5f4220125c76..c3836f6eab35 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -3658,6 +3658,8 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe, struct xe_vm *vm, op == DRM_XE_VM_BIND_OP_MAP_USERPTR) || XE_IOCTL_DBG(xe, coh_mode == XE_COH_NONE && op == DRM_XE_VM_BIND_OP_MAP_USERPTR) || + XE_IOCTL_DBG(xe, !IS_DGFX(xe) && coh_mode == XE_COH_NONE && + is_cpu_addr_mirror) || XE_IOCTL_DBG(xe, xe_device_is_l2_flush_optimized(xe) && (op == DRM_XE_VM_BIND_OP_MAP_USERPTR || is_cpu_addr_mirror) && From 29e33bb890c2f5a2623d938b677e2039ff3edc68 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 21 Apr 2026 14:18:34 -0700 Subject: [PATCH 097/120] drm/xe: Steer MCR for NODE/L3BANK according to L3 fusing on Xe2/Xe3 Although the bspec currently indicates that steered reads/writes to L3 register ranges are never terminated for physically present instances (regardless of fusing) on Xe2, it turns out this is information is incorrect. The hardware architects have also confirmed that the current documentation is wrong (or that possibly the wording was intended to be interpreted in a different way), but have not yet provided an official spec update. All of our driver's writes to registers in these ranges are done as multicast, so steering is not actually important to proper driver operation; the only impact of this documentation mistake is that on some fused-down SKUs where the first L3 bank is absent we're not able to properly read back the values that were written to those registers to confirm that the writes were applied correctly (e.g., when using the register-save-restore-check debugfs interface). Since we don't have an official spec update yet, let's assume that Xe2/Xe3 use the same fuse => steering logic as Xe3p. I.e., remove L3BANK and NODE register ranges from the "INSTANCE0" steering group and add handle them with dedicated handling according to the L3 fuses. From testing on various fused-down platforms this does appear to give proper steering and fix the failures reported by IGT's igt@xe_debugfs@check-gt-reg-sr test. Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/work_items/7706 Reviewed-by: Matt Atwood Link: https://patch.msgid.link/20260421-xe2_l3bank_steering-v1-1-613158a27383@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_gt_mcr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.c b/drivers/gpu/drm/xe/xe_gt_mcr.c index 7c6f039c880d..89e105cee09b 100644 --- a/drivers/gpu/drm/xe/xe_gt_mcr.c +++ b/drivers/gpu/drm/xe/xe_gt_mcr.c @@ -216,9 +216,7 @@ static const struct xe_mmio_range xe2lpg_sqidi_psmi_steering_table[] = { static const struct xe_mmio_range xe2lpg_instance0_steering_table[] = { { 0x004000, 0x004AFF }, /* GAM, rsvd, GAMWKR */ { 0x008700, 0x00887F }, /* SQIDI, MEMPIPE */ - { 0x00B000, 0x00B3FF }, /* NODE, L3BANK */ { 0x00C800, 0x00CFFF }, /* GAM */ - { 0x00D880, 0x00D8FF }, /* NODE */ { 0x00DD00, 0x00DDFF }, /* MEMPIPE */ { 0x00E900, 0x00E97F }, /* MEMPIPE */ { 0x00F000, 0x00FFFF }, /* GAM, GAMWKR */ @@ -267,7 +265,7 @@ static const struct xe_mmio_range xe3p_xpc_gam_grp1_steering_table[] = { {}, }; -static const struct xe_mmio_range xe3p_xpc_node_steering_table[] = { +static const struct xe_mmio_range xe2_node_steering_table[] = { { 0x00B000, 0x00B0FF }, { 0x00D880, 0x00D8FF }, {}, @@ -298,7 +296,7 @@ static void init_steering_l3bank(struct xe_gt *gt) struct xe_device *xe = gt_to_xe(gt); struct xe_mmio *mmio = >->mmio; - if (GRAPHICS_VER(xe) >= 35) { + if (GRAPHICS_VER(xe) >= 20) { unsigned int first_bank = xe_l3_bank_mask_ffs(gt->fuse_topo.l3_bank_mask); const int banks_per_node = 4; unsigned int node = first_bank / banks_per_node; @@ -536,7 +534,7 @@ void xe_gt_mcr_init_early(struct xe_gt *gt) gt->steering[GAM1].ranges = xe3p_xpc_gam_grp1_steering_table; gt->steering[INSTANCE0].ranges = xe3p_xpc_instance0_steering_table; gt->steering[L3BANK].ranges = xelpg_l3bank_steering_table; - gt->steering[NODE].ranges = xe3p_xpc_node_steering_table; + gt->steering[NODE].ranges = xe2_node_steering_table; } else if (GRAPHICS_VERx100(xe) >= 3510) { gt->steering[DSS].ranges = xe2lpg_dss_steering_table; gt->steering[INSTANCE0].ranges = xe3p_lpg_instance0_steering_table; @@ -544,6 +542,8 @@ void xe_gt_mcr_init_early(struct xe_gt *gt) gt->steering[DSS].ranges = xe2lpg_dss_steering_table; gt->steering[SQIDI_PSMI].ranges = xe2lpg_sqidi_psmi_steering_table; gt->steering[INSTANCE0].ranges = xe2lpg_instance0_steering_table; + gt->steering[L3BANK].ranges = xelpg_l3bank_steering_table; + gt->steering[NODE].ranges = xe2_node_steering_table; } else if (GRAPHICS_VERx100(xe) >= 1270) { gt->steering[INSTANCE0].ranges = xelpg_instance0_steering_table; gt->steering[L3BANK].ranges = xelpg_l3bank_steering_table; From 78b8d6d05ad0a58da0375bbfd744e58a61a69ac0 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 24 Apr 2026 13:48:11 -0700 Subject: [PATCH 098/120] drm/xe: Move CCS enablement to engine setup RTP Most register programming for engine setup happens via RTP tables in hw_engine_setup_default_state(). Move the programming of RCU_MODE[0] which enables the platform's CCS engine(s) there. This both makes the code more consistent (other RCU_MODE register programming is already happening in this RTP table) and improves debuggability (since RTP contents and checks of their correct programming are exposed via debugfs). It also helps consolidate the regular driver initialization paths with the vestigial and currently unused execlist (i.e., non-GuC) initialization. With the original programming, the RCU_MODE register (which is a single global register, not a per-engine register) was getting re-programmed with the same value during the initialization of each CCS engine. When moved to the RTP table, we use the xe_rtp_match_first_render_or_compute match function so that it will just be programmed once, while doing the initialization for the first RCS/CCS engine, which avoids the redundant and unnecessary repetition. We can also safely drop the explicit addition of RCU_MODE from the GuC ADS save-restore list now since all registers programmed via RTP tables are automatically added to the GuC's list. v2: - Only enable CCS engines on Xe_HP and later. Even though Xe_LP platforms technically have a CCS engine, it's never been enabled on i915 or Xe due to other issues on these old platforms. Reviewed-by: Shuicheng Lin Link: https://patch.msgid.link/20260424-engine-setup-v2-1-59cc620a25f1@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_execlist.c | 4 ---- drivers/gpu/drm/xe/xe_guc_ads.c | 1 - drivers/gpu/drm/xe/xe_hw_engine.c | 11 +++++------ 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_execlist.c b/drivers/gpu/drm/xe/xe_execlist.c index 755a2bff5d7b..9d158a448a99 100644 --- a/drivers/gpu/drm/xe/xe_execlist.c +++ b/drivers/gpu/drm/xe/xe_execlist.c @@ -59,10 +59,6 @@ static void __start_lrc(struct xe_hw_engine *hwe, struct xe_lrc *lrc, lrc_desc |= FIELD_PREP(SW_CTX_ID, ctx_id); } - if (hwe->class == XE_ENGINE_CLASS_COMPUTE) - xe_mmio_write32(mmio, RCU_MODE, - REG_MASKED_FIELD_ENABLE(RCU_MODE_CCS_ENABLE)); - xe_lrc_write_ctx_reg(lrc, CTX_RING_TAIL, lrc->ring.tail); lrc->ring.old_tail = lrc->ring.tail; diff --git a/drivers/gpu/drm/xe/xe_guc_ads.c b/drivers/gpu/drm/xe/xe_guc_ads.c index 92c6981fe220..d0497d9f43a2 100644 --- a/drivers/gpu/drm/xe/xe_guc_ads.c +++ b/drivers/gpu/drm/xe/xe_guc_ads.c @@ -748,7 +748,6 @@ static unsigned int guc_mmio_regset_write(struct xe_guc_ads *ads, { .reg = RING_MODE(hwe->mmio_base), }, { .reg = RING_HWS_PGA(hwe->mmio_base), }, { .reg = RING_IMR(hwe->mmio_base), }, - { .reg = RCU_MODE, .skip = hwe != hwe_rcs_reset_domain }, { .reg = CCS_MODE, .skip = hwe != hwe_rcs_reset_domain || !xe_gt_ccs_mode_enabled(hwe->gt) }, }; diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index 2f9c1c063f16..74f29025dd6c 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -325,14 +325,8 @@ u32 xe_hw_engine_mmio_read32(struct xe_hw_engine *hwe, struct xe_reg reg) void xe_hw_engine_enable_ring(struct xe_hw_engine *hwe) { - u32 ccs_mask = - xe_hw_engine_mask_per_class(hwe->gt, XE_ENGINE_CLASS_COMPUTE); u32 ring_mode = REG_MASKED_FIELD_ENABLE(GFX_DISABLE_LEGACY_MODE); - if (hwe->class == XE_ENGINE_CLASS_COMPUTE && ccs_mask) - xe_mmio_write32(&hwe->gt->mmio, RCU_MODE, - REG_MASKED_FIELD_ENABLE(RCU_MODE_CCS_ENABLE)); - xe_hw_engine_mmio_write32(hwe, RING_HWSTAM(0), ~0x0); xe_hw_engine_mmio_write32(hwe, RING_HWS_PGA(0), xe_bo_ggtt_addr(hwe->hwsp)); @@ -465,6 +459,11 @@ hw_engine_setup_default_state(struct xe_hw_engine *hwe) XE_RTP_ACTIONS(SET(CSFE_CHICKEN1(0), CS_PRIORITY_MEM_READ, XE_RTP_ACTION_FLAG(ENGINE_BASE))) }, + { XE_RTP_NAME("Enable CCS Engine(s)"), + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1255, XE_RTP_END_VERSION_UNDEFINED), + FUNC(xe_rtp_match_first_render_or_compute)), + XE_RTP_ACTIONS(SET(RCU_MODE, RCU_MODE_CCS_ENABLE)) + }, /* Use Fixed slice CCS mode */ { XE_RTP_NAME("RCU_MODE_FIXED_SLICE_CCS_MODE"), XE_RTP_RULES(FUNC(xe_hw_engine_match_fixed_cslice_mode)), From 176f302e313a7e9038f878719dd0865045b5b2b6 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 24 Apr 2026 13:48:12 -0700 Subject: [PATCH 099/120] drm/xe/rtp: Add "always true" match function All RTP table entries are required to have at least one rule. In cases where an entry should apply unconditionally across all platforms we've been using a graphics version range of 12.00 - forever since this covers all platforms supported by the driver. However if the primary GT is disabled via configfs (not actually possible today, but probably possible in the future) or if we have a future platform that lacks a primary GT and only supports media/display, this rule would cause important programming to fail to apply on the media GT. Add a simple match function that just always returns true unconditionally. This solves the worries above while also being more immediately human-readable. Reviewed-by: Shuicheng Lin Link: https://patch.msgid.link/20260424-engine-setup-v2-2-59cc620a25f1@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_hw_engine.c | 2 +- drivers/gpu/drm/xe/xe_rtp.c | 7 +++++++ drivers/gpu/drm/xe/xe_rtp.h | 12 ++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index 74f29025dd6c..c7d211178300 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -430,7 +430,7 @@ hw_engine_setup_default_state(struct xe_hw_engine *hwe) struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(hwe); const struct xe_rtp_entry_sr engine_entries[] = { { XE_RTP_NAME("RING_CMD_CCTL_default_MOCS"), - XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED)), + XE_RTP_RULES(FUNC(xe_rtp_match_always)), XE_RTP_ACTIONS(FIELD_SET(RING_CMD_CCTL(0), CMD_CCTL_WRITE_OVERRIDE_MASK | CMD_CCTL_READ_OVERRIDE_MASK, diff --git a/drivers/gpu/drm/xe/xe_rtp.c b/drivers/gpu/drm/xe/xe_rtp.c index 991f218f1cc3..728933a1c34f 100644 --- a/drivers/gpu/drm/xe/xe_rtp.c +++ b/drivers/gpu/drm/xe/xe_rtp.c @@ -352,6 +352,13 @@ void xe_rtp_process(struct xe_rtp_process_ctx *ctx, } EXPORT_SYMBOL_IF_KUNIT(xe_rtp_process); +bool xe_rtp_match_always(const struct xe_device *xe, + const struct xe_gt *gt, + const struct xe_hw_engine *hwe) +{ + return true; +} + bool xe_rtp_match_even_instance(const struct xe_device *xe, const struct xe_gt *gt, const struct xe_hw_engine *hwe) diff --git a/drivers/gpu/drm/xe/xe_rtp.h b/drivers/gpu/drm/xe/xe_rtp.h index 4537ff46a17f..d058a629cd3e 100644 --- a/drivers/gpu/drm/xe/xe_rtp.h +++ b/drivers/gpu/drm/xe/xe_rtp.h @@ -459,6 +459,18 @@ void xe_rtp_process(struct xe_rtp_process_ctx *ctx, /* Match functions to be used with XE_RTP_MATCH_FUNC */ +/** + * xe_rtp_match_always - Match RTP entry unconditionally + * @xe: Device structure + * @gt: GT structure + * @hwe: Engine instance + * + * Returns: true, regardless of inputs + */ +bool xe_rtp_match_always(const struct xe_device *xe, + const struct xe_gt *gt, + const struct xe_hw_engine *hwe); + /** * xe_rtp_match_even_instance - Match if engine instance is even * @xe: Device structure From cdf9781025b3ed18f15f6c061c070b8bdcc1716f Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 24 Apr 2026 13:48:13 -0700 Subject: [PATCH 100/120] drm/xe: Stop programming BLIT_CCTL on Xe2 and later platforms Xe1 platforms used the BLIT_CCTL register to specify the MOCS value that would be used for BCS engine instructions that did not have a way of specifying a MOCS index directly. From Xe2 onward, all BCS instructions now have explicit instruction fields for specifying a MOCS index and the BLIT_CCTL register is now a dummy register with no valid fields. Although continuing to write to it today has no effect, the register could repurposed in future platforms, so restrict the BLIT_CCTL RTP entry to only apply to Xe1 platforms. Bspec: 60280 Reviewed-by: Shuicheng Lin Link: https://patch.msgid.link/20260424-engine-setup-v2-3-59cc620a25f1@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_hw_engine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index c7d211178300..0419cd045090 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -384,7 +384,7 @@ xe_hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe) * BLIT_CCTL registers are needed to be programmed to un-cached. */ { XE_RTP_NAME("BLIT_CCTL_default_MOCS"), - XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED), + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, 1274), ENGINE_CLASS(COPY)), XE_RTP_ACTIONS(FIELD_SET(BLIT_CCTL(0), BLIT_CCTL_DST_MOCS_MASK | From a04d8267bf20c73de3368d8ff9fd8289c532f9c5 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 24 Apr 2026 13:48:14 -0700 Subject: [PATCH 101/120] drm/xe: Move HWSTAM programming to RTP The write to RING_HWSTAM to disable hardware status page writes on interrupt was unnecessarily open-coded in xe_hw_engine_enable_ring(); it's preferable to do such programming in the engine_entries[] RTP table since gets reflected/verified in debugfs, and will also automatically ensure that the register is properly saved/restored around engine resets. In this case the HWSTAM register wasn't explicitly added to the GuC ADS' save-restore list, so there was the potential for the value to be lost on engine resets. This doesn't seem to have happened in practice, so likely the GuC firmware is automatically saving/restoring this register on our behalf, but we shouldn't rely on this implicit behavior going forward. One other slight change with this patch is that HWSTAM will now be programmed on the vestigial execlist (non-GuC) initialization path. Since the register's default value is 0x0 and the documentation indicates that it's only legal to leave a single bit unmasked at a time, this likely would have been an illegal situation if the execlist code were actually usable. Reviewed-by: Shuicheng Lin Link: https://patch.msgid.link/20260424-engine-setup-v2-4-59cc620a25f1@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_hw_engine.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index 0419cd045090..ec47e17b4119 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -327,7 +327,6 @@ void xe_hw_engine_enable_ring(struct xe_hw_engine *hwe) { u32 ring_mode = REG_MASKED_FIELD_ENABLE(GFX_DISABLE_LEGACY_MODE); - xe_hw_engine_mmio_write32(hwe, RING_HWSTAM(0), ~0x0); xe_hw_engine_mmio_write32(hwe, RING_HWS_PGA(0), xe_bo_ggtt_addr(hwe->hwsp)); @@ -437,6 +436,11 @@ hw_engine_setup_default_state(struct xe_hw_engine *hwe) ring_cmd_cctl_val, XE_RTP_ACTION_FLAG(ENGINE_BASE))) }, + { XE_RTP_NAME("Disable HW status page updates for interrupts"), + XE_RTP_RULES(FUNC(xe_rtp_match_always)), + XE_RTP_ACTIONS(SET(RING_HWSTAM(0), ~0x0, + XE_RTP_ACTION_FLAG(ENGINE_BASE))) + }, /* * To allow the GSC engine to go idle on MTL we need to enable * idle messaging and set the hysteresis value (we use 0xA=5us From 7e568852d4126de9322e7c8d44fc1a4a060274ad Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 24 Apr 2026 13:48:15 -0700 Subject: [PATCH 102/120] drm/xe: Fix name and definition of GFX_MODE register The register located at $base+0x29c is referred to as GFX_MODE in the bspec. Although many other registers have RING_* prefixes for historical reasons, this register does not, so using a name that does not match the bspec just makes it harder to recognize/find. Also, GFX_MODE is a masked register (updating bits [15:0] requires that the corresponding bit(s) in [31:16] are also set), so add the XE_REG_OPTION_MASKED flag to the register definition; this will become important when we start programming this register via RTP tables in a future patch. Finally swap the order of the register's two bit definitions to match our regular coding style of descending order for register bits/fields. Bspec: 45928 Reviewed-by: Shuicheng Lin Link: https://patch.msgid.link/20260424-engine-setup-v2-5-59cc620a25f1@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/regs/xe_engine_regs.h | 4 ++-- drivers/gpu/drm/xe/xe_execlist.c | 2 +- drivers/gpu/drm/xe/xe_guc_ads.c | 2 +- drivers/gpu/drm/xe/xe_guc_capture.c | 2 +- drivers/gpu/drm/xe/xe_hw_engine.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/xe/regs/xe_engine_regs.h b/drivers/gpu/drm/xe/regs/xe_engine_regs.h index 1b4a7e9a703d..4d5cd1b6f50d 100644 --- a/drivers/gpu/drm/xe/regs/xe_engine_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_engine_regs.h @@ -165,9 +165,9 @@ #define CTX_CTRL_INHIBIT_SYN_CTX_SWITCH REG_BIT(3) #define CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT REG_BIT(0) -#define RING_MODE(base) XE_REG((base) + 0x29c) -#define GFX_DISABLE_LEGACY_MODE REG_BIT(3) +#define GFX_MODE(base) XE_REG((base) + 0x29c, XE_REG_OPTION_MASKED) #define GFX_MSIX_INTERRUPT_ENABLE REG_BIT(13) +#define GFX_DISABLE_LEGACY_MODE REG_BIT(3) #define RING_CSMQDEBUG(base) XE_REG((base) + 0x2b0) diff --git a/drivers/gpu/drm/xe/xe_execlist.c b/drivers/gpu/drm/xe/xe_execlist.c index 9d158a448a99..024744f77ab5 100644 --- a/drivers/gpu/drm/xe/xe_execlist.c +++ b/drivers/gpu/drm/xe/xe_execlist.c @@ -80,7 +80,7 @@ static void __start_lrc(struct xe_hw_engine *hwe, struct xe_lrc *lrc, if (xe_device_has_msix(gt_to_xe(hwe->gt))) ring_mode |= REG_MASKED_FIELD_ENABLE(GFX_MSIX_INTERRUPT_ENABLE); - xe_mmio_write32(mmio, RING_MODE(hwe->mmio_base), ring_mode); + xe_mmio_write32(mmio, GFX_MODE(hwe->mmio_base), ring_mode); xe_mmio_write32(mmio, RING_EXECLIST_SQ_CONTENTS_LO(hwe->mmio_base), lower_32_bits(lrc_desc)); diff --git a/drivers/gpu/drm/xe/xe_guc_ads.c b/drivers/gpu/drm/xe/xe_guc_ads.c index d0497d9f43a2..b403ee0b5e74 100644 --- a/drivers/gpu/drm/xe/xe_guc_ads.c +++ b/drivers/gpu/drm/xe/xe_guc_ads.c @@ -745,7 +745,7 @@ static unsigned int guc_mmio_regset_write(struct xe_guc_ads *ads, struct xe_reg reg; bool skip; } *e, extra_regs[] = { - { .reg = RING_MODE(hwe->mmio_base), }, + { .reg = GFX_MODE(hwe->mmio_base), }, { .reg = RING_HWS_PGA(hwe->mmio_base), }, { .reg = RING_IMR(hwe->mmio_base), }, { .reg = CCS_MODE, diff --git a/drivers/gpu/drm/xe/xe_guc_capture.c b/drivers/gpu/drm/xe/xe_guc_capture.c index 2f5816c78fba..bc49e40165a3 100644 --- a/drivers/gpu/drm/xe/xe_guc_capture.c +++ b/drivers/gpu/drm/xe/xe_guc_capture.c @@ -111,7 +111,7 @@ struct __guc_capture_parsed_output { { RING_TAIL(0), REG_32BIT, 0, 0, 0, "RING_TAIL"}, \ { RING_CTL(0), REG_32BIT, 0, 0, 0, "RING_CTL"}, \ { RING_MI_MODE(0), REG_32BIT, 0, 0, 0, "RING_MI_MODE"}, \ - { RING_MODE(0), REG_32BIT, 0, 0, 0, "RING_MODE"}, \ + { GFX_MODE(0), REG_32BIT, 0, 0, 0, "GFX_MODE"}, \ { RING_ESR(0), REG_32BIT, 0, 0, 0, "RING_ESR"}, \ { RING_EMR(0), REG_32BIT, 0, 0, 0, "RING_EMR"}, \ { RING_EIR(0), REG_32BIT, 0, 0, 0, "RING_EIR"}, \ diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index ec47e17b4119..60af395d031c 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -332,7 +332,7 @@ void xe_hw_engine_enable_ring(struct xe_hw_engine *hwe) if (xe_device_has_msix(gt_to_xe(hwe->gt))) ring_mode |= REG_MASKED_FIELD_ENABLE(GFX_MSIX_INTERRUPT_ENABLE); - xe_hw_engine_mmio_write32(hwe, RING_MODE(0), ring_mode); + xe_hw_engine_mmio_write32(hwe, GFX_MODE(0), ring_mode); xe_hw_engine_mmio_write32(hwe, RING_MI_MODE(0), REG_MASKED_FIELD_DISABLE(STOP_RING)); xe_hw_engine_mmio_read32(hwe, RING_MI_MODE(0)); From ee9b3c6c79ac643c02320b881a4c1fbaf1eb4da8 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 24 Apr 2026 13:48:16 -0700 Subject: [PATCH 103/120] drm/xe: Const-ify parameters to xe_device_has_* functions None of these functions modify the Xe device parameter, and marking it as const will avoid warnings when the callsite wants to pass a const pointer. Reviewed-by: Michal Wajdeczko Link: https://patch.msgid.link/20260424-engine-setup-v2-6-59cc620a25f1@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_device.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_device.h b/drivers/gpu/drm/xe/xe_device.h index 555c191f7510..355d69dc8f54 100644 --- a/drivers/gpu/drm/xe/xe_device.h +++ b/drivers/gpu/drm/xe/xe_device.h @@ -146,37 +146,37 @@ static inline struct xe_force_wake *gt_to_fw(struct xe_gt *gt) void xe_device_assert_mem_access(struct xe_device *xe); -static inline bool xe_device_has_flat_ccs(struct xe_device *xe) +static inline bool xe_device_has_flat_ccs(const struct xe_device *xe) { return xe->info.has_flat_ccs; } -static inline bool xe_device_has_sriov(struct xe_device *xe) +static inline bool xe_device_has_sriov(const struct xe_device *xe) { return xe->info.has_sriov; } -static inline bool xe_device_has_msix(struct xe_device *xe) +static inline bool xe_device_has_msix(const struct xe_device *xe) { return xe->irq.msix.nvec > 0; } -static inline bool xe_device_has_memirq(struct xe_device *xe) +static inline bool xe_device_has_memirq(const struct xe_device *xe) { return GRAPHICS_VERx100(xe) >= 1250; } -static inline bool xe_device_uses_memirq(struct xe_device *xe) +static inline bool xe_device_uses_memirq(const struct xe_device *xe) { return xe_device_has_memirq(xe) && (IS_SRIOV_VF(xe) || xe_device_has_msix(xe)); } -static inline bool xe_device_has_lmtt(struct xe_device *xe) +static inline bool xe_device_has_lmtt(const struct xe_device *xe) { return IS_DGFX(xe); } -static inline bool xe_device_has_mert(struct xe_device *xe) +static inline bool xe_device_has_mert(const struct xe_device *xe) { return xe->info.has_mert; } From 4c936a0a22d200a6828fd051d035f09abab2835e Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 24 Apr 2026 13:48:17 -0700 Subject: [PATCH 104/120] drm/xe: Move GFX_MODE programming to RTP The write GFX_MODE to disable engine "legacy mode" and to enable MSI-X support was unnecessarily open-coded in xe_hw_engine_enable_ring(); it's preferable to do such programming in the engine_entries[] RTP table since gets reflected/verified in debugfs, and will also automatically ensure that the register is properly saved/restored around engine resets. This also helps consolidate common logic that was duplicated between the main driver initialization path and the dead-code execlist initialization path. This also allows us to drop GFX_MODE from the list of extra registers to be added to the GuC ADS' save-restore list since all registers on the RTP table are added automatically. v2: - Actually use the xe_rtp_match_has_msix match function added. (Shuicheng) Cc: Shuicheng Lin Reviewed-by: Shuicheng Lin Link: https://patch.msgid.link/20260424-engine-setup-v2-7-59cc620a25f1@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_execlist.c | 5 ----- drivers/gpu/drm/xe/xe_guc_ads.c | 1 - drivers/gpu/drm/xe/xe_hw_engine.c | 16 ++++++++++------ drivers/gpu/drm/xe/xe_rtp.c | 8 ++++++++ drivers/gpu/drm/xe/xe_rtp.h | 12 ++++++++++++ 5 files changed, 30 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_execlist.c b/drivers/gpu/drm/xe/xe_execlist.c index 024744f77ab5..0fe4fb226ef4 100644 --- a/drivers/gpu/drm/xe/xe_execlist.c +++ b/drivers/gpu/drm/xe/xe_execlist.c @@ -47,7 +47,6 @@ static void __start_lrc(struct xe_hw_engine *hwe, struct xe_lrc *lrc, struct xe_mmio *mmio = >->mmio; struct xe_device *xe = gt_to_xe(gt); u64 lrc_desc; - u32 ring_mode = REG_MASKED_FIELD_ENABLE(GFX_DISABLE_LEGACY_MODE); lrc_desc = xe_lrc_descriptor(lrc); @@ -78,10 +77,6 @@ static void __start_lrc(struct xe_hw_engine *hwe, struct xe_lrc *lrc, xe_bo_ggtt_addr(hwe->hwsp)); xe_mmio_read32(mmio, RING_HWS_PGA(hwe->mmio_base)); - if (xe_device_has_msix(gt_to_xe(hwe->gt))) - ring_mode |= REG_MASKED_FIELD_ENABLE(GFX_MSIX_INTERRUPT_ENABLE); - xe_mmio_write32(mmio, GFX_MODE(hwe->mmio_base), ring_mode); - xe_mmio_write32(mmio, RING_EXECLIST_SQ_CONTENTS_LO(hwe->mmio_base), lower_32_bits(lrc_desc)); xe_mmio_write32(mmio, RING_EXECLIST_SQ_CONTENTS_HI(hwe->mmio_base), diff --git a/drivers/gpu/drm/xe/xe_guc_ads.c b/drivers/gpu/drm/xe/xe_guc_ads.c index b403ee0b5e74..ce651da6f318 100644 --- a/drivers/gpu/drm/xe/xe_guc_ads.c +++ b/drivers/gpu/drm/xe/xe_guc_ads.c @@ -745,7 +745,6 @@ static unsigned int guc_mmio_regset_write(struct xe_guc_ads *ads, struct xe_reg reg; bool skip; } *e, extra_regs[] = { - { .reg = GFX_MODE(hwe->mmio_base), }, { .reg = RING_HWS_PGA(hwe->mmio_base), }, { .reg = RING_IMR(hwe->mmio_base), }, { .reg = CCS_MODE, diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index 60af395d031c..b380d3cf6d3a 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -325,14 +325,8 @@ u32 xe_hw_engine_mmio_read32(struct xe_hw_engine *hwe, struct xe_reg reg) void xe_hw_engine_enable_ring(struct xe_hw_engine *hwe) { - u32 ring_mode = REG_MASKED_FIELD_ENABLE(GFX_DISABLE_LEGACY_MODE); - xe_hw_engine_mmio_write32(hwe, RING_HWS_PGA(0), xe_bo_ggtt_addr(hwe->hwsp)); - - if (xe_device_has_msix(gt_to_xe(hwe->gt))) - ring_mode |= REG_MASKED_FIELD_ENABLE(GFX_MSIX_INTERRUPT_ENABLE); - xe_hw_engine_mmio_write32(hwe, GFX_MODE(0), ring_mode); xe_hw_engine_mmio_write32(hwe, RING_MI_MODE(0), REG_MASKED_FIELD_DISABLE(STOP_RING)); xe_hw_engine_mmio_read32(hwe, RING_MI_MODE(0)); @@ -441,6 +435,11 @@ hw_engine_setup_default_state(struct xe_hw_engine *hwe) XE_RTP_ACTIONS(SET(RING_HWSTAM(0), ~0x0, XE_RTP_ACTION_FLAG(ENGINE_BASE))) }, + { XE_RTP_NAME("Disable engine 'legacy' mode"), + XE_RTP_RULES(FUNC(xe_rtp_match_always)), + XE_RTP_ACTIONS(SET(GFX_MODE(0), GFX_DISABLE_LEGACY_MODE, + XE_RTP_ACTION_FLAG(ENGINE_BASE))) + }, /* * To allow the GSC engine to go idle on MTL we need to enable * idle messaging and set the hysteresis value (we use 0xA=5us @@ -474,6 +473,11 @@ hw_engine_setup_default_state(struct xe_hw_engine *hwe) XE_RTP_ACTIONS(FIELD_SET(RCU_MODE, RCU_MODE_FIXED_SLICE_CCS_MODE, RCU_MODE_FIXED_SLICE_CCS_MODE)) }, + { XE_RTP_NAME("Enable MSI-X interrupt support"), + XE_RTP_RULES(FUNC(xe_rtp_match_has_msix)), + XE_RTP_ACTIONS(SET(GFX_MODE(0), GFX_MSIX_INTERRUPT_ENABLE, + XE_RTP_ACTION_FLAG(ENGINE_BASE))) + }, }; xe_rtp_process_to_sr(&ctx, engine_entries, ARRAY_SIZE(engine_entries), diff --git a/drivers/gpu/drm/xe/xe_rtp.c b/drivers/gpu/drm/xe/xe_rtp.c index 728933a1c34f..1a4dcbbbc176 100644 --- a/drivers/gpu/drm/xe/xe_rtp.c +++ b/drivers/gpu/drm/xe/xe_rtp.c @@ -10,6 +10,7 @@ #include #include "xe_configfs.h" +#include "xe_device.h" #include "xe_gt.h" #include "xe_gt_topology.h" #include "xe_reg_sr.h" @@ -404,3 +405,10 @@ bool xe_rtp_match_has_flat_ccs(const struct xe_device *xe, { return xe->info.has_flat_ccs; } + +bool xe_rtp_match_has_msix(const struct xe_device *xe, + const struct xe_gt *gt, + const struct xe_hw_engine *hwe) +{ + return xe_device_has_msix(xe); +} diff --git a/drivers/gpu/drm/xe/xe_rtp.h b/drivers/gpu/drm/xe/xe_rtp.h index d058a629cd3e..562082b18d7b 100644 --- a/drivers/gpu/drm/xe/xe_rtp.h +++ b/drivers/gpu/drm/xe/xe_rtp.h @@ -536,4 +536,16 @@ bool xe_rtp_match_has_flat_ccs(const struct xe_device *xe, const struct xe_gt *gt, const struct xe_hw_engine *hwe); +/** + * xe_rtp_match_has_msix - Match when platform has MSI-X + * @xe: Device structure + * @gt: GT structure + * @hwe: Engine instance + * + * Returns: true if platform has MSI-X interrupt support + */ +bool xe_rtp_match_has_msix(const struct xe_device *xe, + const struct xe_gt *gt, + const struct xe_hw_engine *hwe); + #endif From 461a6698d608cc96ae83a4631bd529f3c74e7d92 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 24 Apr 2026 13:48:18 -0700 Subject: [PATCH 105/120] drm/xe: Drop unnecessary STOP_RING clearing The STOP_RING bit in MI_MODE is already clear by default out of hardware reset and will only be '1' if the driver intentionally sets it after that. The logic of clearing this bit appears to originate from very early (pre-GuC, pre-execlist) code in i915 where we needed to stop the ring before performing a host-initiated engine reset; after the reset the STOP_RING bit needed to be cleared to allow execution to resume. None of that is relevant to Xe (or even modern i915) since STOP_RING isn't necessary for execlist-based engine resets (and even if it were, Xe doesn't initiate any engine resets; the GuC handles that now). Bspec: 60356, 60184 Reviewed-by: Shuicheng Lin Link: https://patch.msgid.link/20260424-engine-setup-v2-8-59cc620a25f1@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/regs/xe_engine_regs.h | 1 - drivers/gpu/drm/xe/xe_hw_engine.c | 3 --- drivers/gpu/drm/xe/xe_lrc.c | 20 -------------------- 3 files changed, 24 deletions(-) diff --git a/drivers/gpu/drm/xe/regs/xe_engine_regs.h b/drivers/gpu/drm/xe/regs/xe_engine_regs.h index 4d5cd1b6f50d..c4c879a9e555 100644 --- a/drivers/gpu/drm/xe/regs/xe_engine_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_engine_regs.h @@ -176,7 +176,6 @@ #define RING_TIMESTAMP_UDW(base) XE_REG((base) + 0x358 + 4) #define RING_VALID_MASK 0x00000001 #define RING_VALID 0x00000001 -#define STOP_RING REG_BIT(8) #define RING_CTX_TIMESTAMP(base) XE_REG((base) + 0x3a8) #define RING_CTX_TIMESTAMP_UDW(base) XE_REG((base) + 0x3ac) diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index b380d3cf6d3a..91e644067cc4 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -327,9 +327,6 @@ void xe_hw_engine_enable_ring(struct xe_hw_engine *hwe) { xe_hw_engine_mmio_write32(hwe, RING_HWS_PGA(0), xe_bo_ggtt_addr(hwe->hwsp)); - xe_hw_engine_mmio_write32(hwe, RING_MI_MODE(0), - REG_MASKED_FIELD_DISABLE(STOP_RING)); - xe_hw_engine_mmio_read32(hwe, RING_MI_MODE(0)); } static bool xe_hw_engine_match_fixed_cslice_mode(const struct xe_device *xe, diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index c725cde4508d..9db914584347 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -682,25 +682,6 @@ static void set_memory_based_intr(u32 *regs, struct xe_hw_engine *hwe) } } -static int lrc_ring_mi_mode(struct xe_hw_engine *hwe) -{ - struct xe_device *xe = gt_to_xe(hwe->gt); - - if (GRAPHICS_VERx100(xe) >= 1250) - return 0x70; - else - return 0x60; -} - -static void reset_stop_ring(u32 *regs, struct xe_hw_engine *hwe) -{ - int x; - - x = lrc_ring_mi_mode(hwe); - regs[x + 1] &= ~STOP_RING; - regs[x + 1] |= STOP_RING << 16; -} - static inline bool xe_lrc_has_indirect_ring_state(struct xe_lrc *lrc) { return lrc->flags & XE_LRC_FLAG_INDIRECT_RING_STATE; @@ -980,7 +961,6 @@ static void *empty_lrc_data(struct xe_hw_engine *hwe) set_offsets(regs, reg_offsets(gt_to_xe(gt), hwe->class), hwe); set_context_control(regs, hwe); set_memory_based_intr(regs, hwe); - reset_stop_ring(regs, hwe); if (xe_gt_has_indirect_ring_state(gt)) { regs = data + xe_gt_lrc_size(gt, hwe->class) - LRC_INDIRECT_RING_STATE_SIZE; From cd2f1b4462c05bfe7610edb8cde6f084c3a4d6d1 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 24 Apr 2026 13:48:19 -0700 Subject: [PATCH 106/120] drm/xe: Drop xe_hw_engine_mmio_write32() xe_hw_engine_mmio_write32() is only used in a single place and is easily replaced by a regular xe_mmio_write32() call. Register read/write interfaces are already complicated enough with MCR vs non-MCR handling, so we should avoid adding extra wrappers that just make it more confusing what to use. xe_hw_engine_mmio_write32() did have a forcewake assertion that we're dropping here, but that assertion wasn't entirely correct anyway. It was checking hwe->domain which is currently set to XE_FW_RENDER for the BCS engine, even though BCS engines reside in the GT domain. v2: - Drop prototype in header file as well. (Shuicheng) Cc: Shuicheng Lin Reviewed-by: Shuicheng Lin Link: https://patch.msgid.link/20260424-engine-setup-v2-9-59cc620a25f1@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_hw_engine.c | 25 ++----------------------- drivers/gpu/drm/xe/xe_hw_engine.h | 1 - 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index 91e644067cc4..b3da832a5414 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -282,27 +282,6 @@ static void hw_engine_fini(void *arg) hwe->gt = NULL; } -/** - * xe_hw_engine_mmio_write32() - Write engine register - * @hwe: engine - * @reg: register to write into - * @val: desired 32-bit value to write - * - * This function will write val into an engine specific register. - * Forcewake must be held by the caller. - * - */ -void xe_hw_engine_mmio_write32(struct xe_hw_engine *hwe, - struct xe_reg reg, u32 val) -{ - xe_gt_assert(hwe->gt, !(reg.addr & hwe->mmio_base)); - xe_force_wake_assert_held(gt_to_fw(hwe->gt), hwe->domain); - - reg.addr += hwe->mmio_base; - - xe_mmio_write32(&hwe->gt->mmio, reg, val); -} - /** * xe_hw_engine_mmio_read32() - Read engine register * @hwe: engine @@ -325,8 +304,8 @@ u32 xe_hw_engine_mmio_read32(struct xe_hw_engine *hwe, struct xe_reg reg) void xe_hw_engine_enable_ring(struct xe_hw_engine *hwe) { - xe_hw_engine_mmio_write32(hwe, RING_HWS_PGA(0), - xe_bo_ggtt_addr(hwe->hwsp)); + xe_mmio_write32(&hwe->gt->mmio, RING_HWS_PGA(hwe->mmio_base), + xe_bo_ggtt_addr(hwe->hwsp)); } static bool xe_hw_engine_match_fixed_cslice_mode(const struct xe_device *xe, diff --git a/drivers/gpu/drm/xe/xe_hw_engine.h b/drivers/gpu/drm/xe/xe_hw_engine.h index 6b5f9fa2a594..ee9218773b51 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.h +++ b/drivers/gpu/drm/xe/xe_hw_engine.h @@ -76,7 +76,6 @@ const char *xe_hw_engine_class_to_str(enum xe_engine_class class); u64 xe_hw_engine_read_timestamp(struct xe_hw_engine *hwe); enum xe_force_wake_domains xe_hw_engine_to_fw_domain(struct xe_hw_engine *hwe); -void xe_hw_engine_mmio_write32(struct xe_hw_engine *hwe, struct xe_reg reg, u32 val); u32 xe_hw_engine_mmio_read32(struct xe_hw_engine *hwe, struct xe_reg reg); #endif From 8954033df47864e255aa0c5a3fc10a60f73325af Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 24 Apr 2026 13:48:20 -0700 Subject: [PATCH 107/120] drm/xe: Mark BCS engines as belonging to the GT forcewake domain On all platforms supported by the Xe driver, BCS engines are part of the GT forcewake domain, not the RENDER domain. Fix the engine list definition to match the spec. This mistake didn't really cause any real problems because the forcewake domain here was only used in a couple assertions that aren't really necessary and included in the information dumped during error capture. Bspec: 66696, 66534, 67609, 71185, 74417, 75242, 78286 Reviewed-by: Shuicheng Lin Link: https://patch.msgid.link/20260424-engine-setup-v2-10-59cc620a25f1@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_hw_engine.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index b3da832a5414..0f0e08bcc182 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -67,7 +67,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .instance = 0, .irq_offset = ilog2(INTR_BCS(0)), - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = BLT_RING_BASE, }, [XE_HW_ENGINE_BCS1] = { @@ -75,7 +75,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .instance = 1, .irq_offset = ilog2(INTR_BCS(1)), - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = XEHPC_BCS1_RING_BASE, }, [XE_HW_ENGINE_BCS2] = { @@ -83,7 +83,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .instance = 2, .irq_offset = ilog2(INTR_BCS(2)), - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = XEHPC_BCS2_RING_BASE, }, [XE_HW_ENGINE_BCS3] = { @@ -91,7 +91,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .instance = 3, .irq_offset = ilog2(INTR_BCS(3)), - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = XEHPC_BCS3_RING_BASE, }, [XE_HW_ENGINE_BCS4] = { @@ -99,7 +99,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .instance = 4, .irq_offset = ilog2(INTR_BCS(4)), - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = XEHPC_BCS4_RING_BASE, }, [XE_HW_ENGINE_BCS5] = { @@ -107,7 +107,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .instance = 5, .irq_offset = ilog2(INTR_BCS(5)), - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = XEHPC_BCS5_RING_BASE, }, [XE_HW_ENGINE_BCS6] = { @@ -115,7 +115,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .instance = 6, .irq_offset = ilog2(INTR_BCS(6)), - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = XEHPC_BCS6_RING_BASE, }, [XE_HW_ENGINE_BCS7] = { @@ -123,7 +123,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .irq_offset = ilog2(INTR_BCS(7)), .instance = 7, - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = XEHPC_BCS7_RING_BASE, }, [XE_HW_ENGINE_BCS8] = { @@ -131,7 +131,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .instance = 8, .irq_offset = ilog2(INTR_BCS8), - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = XEHPC_BCS8_RING_BASE, }, From 60b040fcea21dc14b90a81eb33d508a69ce1e427 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Mon, 27 Apr 2026 14:59:26 +0530 Subject: [PATCH 108/120] drm/xe/guc_pc: Make xe_guc_pc_stop() void xe_guc_pc_stop() doesn't return any meaningful value. Refactor it into void function. Signed-off-by: Raag Jadav Reviewed-by: Rodrigo Vivi Link: https://patch.msgid.link/20260427092928.1181893-2-raag.jadav@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_guc.c | 9 ++------- drivers/gpu/drm/xe/xe_guc_pc.c | 8 +++----- drivers/gpu/drm/xe/xe_guc_pc.h | 2 +- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c index e762eada21db..e468b638271b 100644 --- a/drivers/gpu/drm/xe/xe_guc.c +++ b/drivers/gpu/drm/xe/xe_guc.c @@ -1701,13 +1701,8 @@ void xe_guc_reset_wait(struct xe_guc *guc) void xe_guc_stop_prepare(struct xe_guc *guc) { - if (!IS_SRIOV_VF(guc_to_xe(guc))) { - int err; - - err = xe_guc_pc_stop(&guc->pc); - xe_gt_WARN(guc_to_gt(guc), err, "Failed to stop GuC PC: %pe\n", - ERR_PTR(err)); - } + if (!IS_SRIOV_VF(guc_to_xe(guc))) + xe_guc_pc_stop(&guc->pc); } void xe_guc_stop(struct xe_guc *guc) diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c index 7ecd91ad6192..9530cddbd11d 100644 --- a/drivers/gpu/drm/xe/xe_guc_pc.c +++ b/drivers/gpu/drm/xe/xe_guc_pc.c @@ -1316,18 +1316,16 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) * xe_guc_pc_stop - Stop GuC's Power Conservation component * @pc: Xe_GuC_PC instance */ -int xe_guc_pc_stop(struct xe_guc_pc *pc) +void xe_guc_pc_stop(struct xe_guc_pc *pc) { struct xe_device *xe = pc_to_xe(pc); if (xe->info.skip_guc_pc) - return 0; + return; mutex_lock(&pc->freq_lock); pc->freq_ready = false; mutex_unlock(&pc->freq_lock); - - return 0; } /** @@ -1343,7 +1341,7 @@ static void xe_guc_pc_fini_hw(void *arg) return; CLASS(xe_force_wake, fw_ref)(gt_to_fw(pc_to_gt(pc)), XE_FW_GT); - XE_WARN_ON(xe_guc_pc_stop(pc)); + xe_guc_pc_stop(pc); /* Bind requested freq to mert_freq_cap before unload */ pc_set_cur_freq(pc, min(pc_max_freq_cap(pc), xe_guc_pc_get_rpe_freq(pc))); diff --git a/drivers/gpu/drm/xe/xe_guc_pc.h b/drivers/gpu/drm/xe/xe_guc_pc.h index 0678a4e787b3..1025a2b15f5f 100644 --- a/drivers/gpu/drm/xe/xe_guc_pc.h +++ b/drivers/gpu/drm/xe/xe_guc_pc.h @@ -13,7 +13,7 @@ struct drm_printer; int xe_guc_pc_init(struct xe_guc_pc *pc); int xe_guc_pc_start(struct xe_guc_pc *pc); -int xe_guc_pc_stop(struct xe_guc_pc *pc); +void xe_guc_pc_stop(struct xe_guc_pc *pc); void xe_guc_pc_print(struct xe_guc_pc *pc, struct drm_printer *p); int xe_guc_pc_action_set_param(struct xe_guc_pc *pc, u8 id, u32 value); int xe_guc_pc_action_unset_param(struct xe_guc_pc *pc, u8 id); From 8edb1f2c729c00a6d909897574e5f9b5faf02e94 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Mon, 27 Apr 2026 14:59:27 +0530 Subject: [PATCH 109/120] drm/xe/guc_pc: Reorder forcewake in xe_guc_pc_fini_hw() xe_guc_pc_stop() doesn't perform any MMIO operation that requires forcewake in it's code path. Move it before pc_set_cur_freq() which writes to RPNSWREQ and actually requires it. Signed-off-by: Raag Jadav Reviewed-by: Rodrigo Vivi Link: https://patch.msgid.link/20260427092928.1181893-3-raag.jadav@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_guc_pc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c index 9530cddbd11d..59f2fa79ad42 100644 --- a/drivers/gpu/drm/xe/xe_guc_pc.c +++ b/drivers/gpu/drm/xe/xe_guc_pc.c @@ -1340,10 +1340,10 @@ static void xe_guc_pc_fini_hw(void *arg) if (xe_device_wedged(xe)) return; - CLASS(xe_force_wake, fw_ref)(gt_to_fw(pc_to_gt(pc)), XE_FW_GT); xe_guc_pc_stop(pc); /* Bind requested freq to mert_freq_cap before unload */ + CLASS(xe_force_wake, fw_ref)(gt_to_fw(pc_to_gt(pc)), XE_FW_GT); pc_set_cur_freq(pc, min(pc_max_freq_cap(pc), xe_guc_pc_get_rpe_freq(pc))); } From e70d1c5fedfac919278a96aae0984f1927a55137 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Mon, 27 Apr 2026 14:59:28 +0530 Subject: [PATCH 110/120] drm/xe/gt: Drop redundant forcewake xe_gt_suspend_prepare() doesn't perform any MMIO operation that requires forcewake in it's code path. Drop it. Signed-off-by: Raag Jadav Reviewed-by: Rodrigo Vivi $ Link: https://patch.msgid.link/20260427092928.1181893-4-raag.jadav@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_gt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index 8a31c963c372..cdc678d1ae1f 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -993,7 +993,6 @@ void xe_gt_reset_async(struct xe_gt *gt) void xe_gt_suspend_prepare(struct xe_gt *gt) { - CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL); xe_uc_suspend_prepare(>->uc); } From 3096d3e9f44afe011d2017ddade416924e1c99d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Tue, 28 Apr 2026 12:25:25 +0200 Subject: [PATCH 111/120] drm/xe: Don't use UTS_RELEASE directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UTS_RELEASE evaluates to a static string and changes quite easily (e.g. uncommitted changes in the source tree or new commits). So when checking if a patch introduces changes to the resulting binary each usage of UTS_RELEASE is source of annoyance. Instead of using UTS_RELEASE directly use init_utsname()->release which evaluates to the same string but with that a change of UTS_RELEASE doesn't affect xe_devcoredump.o. Signed-off-by: Uwe Kleine-König (The Capable Hub) Reviewed-by: Jani Nikula Acked-by: José Roberto de Souza Link: https://patch.msgid.link/20260428102527.189593-2-u.kleine-koenig@baylibre.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_devcoredump.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c index ec206f512795..5f2b90b18f97 100644 --- a/drivers/gpu/drm/xe/xe_devcoredump.c +++ b/drivers/gpu/drm/xe/xe_devcoredump.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include @@ -101,7 +101,7 @@ static ssize_t __xe_devcoredump_read(char *buffer, ssize_t count, drm_puts(&p, "**** Xe Device Coredump ****\n"); drm_printf(&p, "Reason: %s\n", ss->reason); - drm_puts(&p, "kernel: " UTS_RELEASE "\n"); + drm_printf(&p, "kernel: %s\n", init_utsname()->release); drm_puts(&p, "module: " KBUILD_MODNAME "\n"); ts = ktime_to_timespec64(ss->snapshot_time); From bfaf87e84ca3ca3f6e275f9ae56da47a8b55ffd1 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 16 Apr 2026 15:17:19 -0300 Subject: [PATCH 112/120] drm/xe/hdcp: Add NULL check for media_gt in intel_hdcp_gsc_check_status() When media GT is disabled via configfs, there is no allocation for media_gt, which is kept as NULL. In such scenario, intel_hdcp_gsc_check_status() results in a kernel pagefault error due to >->uc.gsc being evaluated as an invalid memory address. Fix that by introducing a NULL check on media_gt and bailing out early if so. While at it, also drop the NULL check for gsc, since it can't be NULL if media_gt is not NULL. v2: - Get address for gsc only after checking that gt is not NULL. (Shuicheng) - Drop the NULL check for gsc. (Shuicheng) v3: - Add "Fixes" and "Cc: " tags. (Matt) Fixes: 4af50beb4e0f ("drm/xe: Use gsc_proxy_init_done to check proxy status") Cc: # v6.10+ Reviewed-by: Matt Roper Reviewed-by: Shuicheng Lin Link: https://patch.msgid.link/20260416-check-for-null-media_gt-in-intel_hdcp_gsc_check_status-v2-1-9adb9fd3b621@intel.com Signed-off-by: Gustavo Sousa --- drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c index 29c72aa4b0d2..33494b86205d 100644 --- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c @@ -37,9 +37,17 @@ static bool intel_hdcp_gsc_check_status(struct drm_device *drm) struct xe_device *xe = to_xe_device(drm); struct xe_tile *tile = xe_device_get_root_tile(xe); struct xe_gt *gt = tile->media_gt; - struct xe_gsc *gsc = >->uc.gsc; + struct xe_gsc *gsc; - if (!gsc || !xe_uc_fw_is_available(&gsc->fw)) { + if (!gt) { + drm_dbg_kms(&xe->drm, + "not checking GSC status for HDCP2.x: media GT not present or disabled\n"); + return false; + } + + gsc = >->uc.gsc; + + if (!xe_uc_fw_is_available(&gsc->fw)) { drm_dbg_kms(&xe->drm, "GSC Components not ready for HDCP2.x\n"); return false; From f4fe5f96ba1d4125c1f11e7a9117f14411129acf Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Wed, 22 Apr 2026 15:50:25 +0000 Subject: [PATCH 113/120] drm/xe/mcr: Remove unused xe_gt_mcr_steering_info_to_dss_id() The function xe_gt_mcr_steering_info_to_dss_id() has had no callers since commit fa597710be6e ("drm/xe/guc: Cache DSS info when creating capture register list") which removed the only call site in xe_guc_capture.c. Remove the dead function and its declaration. No functional change. Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20260422155025.3660484-1-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_gt_mcr.c | 13 ------------- drivers/gpu/drm/xe/xe_gt_mcr.h | 1 - 2 files changed, 14 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.c b/drivers/gpu/drm/xe/xe_gt_mcr.c index 89e105cee09b..df281688c617 100644 --- a/drivers/gpu/drm/xe/xe_gt_mcr.c +++ b/drivers/gpu/drm/xe/xe_gt_mcr.c @@ -428,19 +428,6 @@ void xe_gt_mcr_get_dss_steering(const struct xe_gt *gt, unsigned int dss, u16 *g *instance = dss % gt->steering_dss_per_grp; } -/** - * xe_gt_mcr_steering_info_to_dss_id - Get DSS ID from group/instance steering - * @gt: GT structure - * @group: steering group ID - * @instance: steering instance ID - * - * Return: the converted DSS id. - */ -u32 xe_gt_mcr_steering_info_to_dss_id(struct xe_gt *gt, u16 group, u16 instance) -{ - return group * dss_per_group(gt) + instance; -} - static void init_steering_dss(struct xe_gt *gt) { gt->steering_dss_per_grp = dss_per_group(gt); diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.h b/drivers/gpu/drm/xe/xe_gt_mcr.h index 283a1c9770e2..2be9419b8acc 100644 --- a/drivers/gpu/drm/xe/xe_gt_mcr.h +++ b/drivers/gpu/drm/xe/xe_gt_mcr.h @@ -33,7 +33,6 @@ bool xe_gt_mcr_get_nonterminated_steering(struct xe_gt *gt, void xe_gt_mcr_steering_dump(struct xe_gt *gt, struct drm_printer *p); void xe_gt_mcr_get_dss_steering(const struct xe_gt *gt, unsigned int dss, u16 *group, u16 *instance); -u32 xe_gt_mcr_steering_info_to_dss_id(struct xe_gt *gt, u16 group, u16 instance); /* * Loop over each DSS and determine the group and instance IDs that From 7b5c60226753e5cd43073ff1dad5d1b983691521 Mon Sep 17 00:00:00 2001 From: Ashutosh Dixit Date: Mon, 27 Apr 2026 15:11:31 -0700 Subject: [PATCH 114/120] drm/xe/oa: Use xe_map layer OA code should have used xe_map layer to begin with. In CRI, the OA buffer can be located both in system and device memory. For these reasons, move OA code to use the xe_map layer when accessing the OA buffer. v2: Use xe_map layer and put_user in xe_oa_copy_to_user (Umesh) v3: To avoid performance impact in v2, revert to v1 but move xe_map_copy_to_user() to xe_map.h v4: Use bounce buffer and copy_to_user in xe_oa_copy_to_user v5: Fix offsets in oa_timestamp() and oa_timestamp_clear() (Umesh) v6: Rename head/tail in helper args to report_offset (Umesh) v7: Add xe_assert in xe_oa_copy_to_user (Umesh) Signed-off-by: Ashutosh Dixit Reviewed-by: Umesh Nerlige Ramappa Link: https://patch.msgid.link/20260427221133.2500532-2-ashutosh.dixit@intel.com --- drivers/gpu/drm/xe/xe_oa.c | 107 ++++++++++++++++++------------- drivers/gpu/drm/xe/xe_oa_types.h | 4 +- 2 files changed, 65 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c index 6337e671c97a..6ded3c2fce34 100644 --- a/drivers/gpu/drm/xe/xe_oa.c +++ b/drivers/gpu/drm/xe/xe_oa.c @@ -213,32 +213,40 @@ static u32 xe_oa_hw_tail_read(struct xe_oa_stream *stream) #define oa_report_header_64bit(__s) \ ((__s)->oa_buffer.format->header == HDR_64_BIT) -static u64 oa_report_id(struct xe_oa_stream *stream, void *report) +static u64 oa_report_id(struct xe_oa_stream *stream, u32 report_offset) { - return oa_report_header_64bit(stream) ? *(u64 *)report : *(u32 *)report; -} + struct iosys_map *map = &stream->oa_buffer.bo->vmap; -static void oa_report_id_clear(struct xe_oa_stream *stream, u32 *report) -{ - if (oa_report_header_64bit(stream)) - *(u64 *)report = 0; - else - *report = 0; -} - -static u64 oa_timestamp(struct xe_oa_stream *stream, void *report) -{ return oa_report_header_64bit(stream) ? - *((u64 *)report + 1) : - *((u32 *)report + 1); + xe_map_rd(stream->oa->xe, map, report_offset, u64) : + xe_map_rd(stream->oa->xe, map, report_offset, u32); } -static void oa_timestamp_clear(struct xe_oa_stream *stream, u32 *report) +static void oa_report_id_clear(struct xe_oa_stream *stream, u32 report_offset) { - if (oa_report_header_64bit(stream)) - *(u64 *)&report[2] = 0; - else - report[1] = 0; + struct iosys_map *map = &stream->oa_buffer.bo->vmap; + + oa_report_header_64bit(stream) ? + xe_map_wr(stream->oa->xe, map, report_offset, u64, 0) : + xe_map_wr(stream->oa->xe, map, report_offset, u32, 0); +} + +static u64 oa_timestamp(struct xe_oa_stream *stream, u32 report_offset) +{ + struct iosys_map *map = &stream->oa_buffer.bo->vmap; + + return oa_report_header_64bit(stream) ? + xe_map_rd(stream->oa->xe, map, report_offset + 8, u64) : + xe_map_rd(stream->oa->xe, map, report_offset + 4, u32); +} + +static void oa_timestamp_clear(struct xe_oa_stream *stream, u32 report_offset) +{ + struct iosys_map *map = &stream->oa_buffer.bo->vmap; + + oa_report_header_64bit(stream) ? + xe_map_wr(stream->oa->xe, map, report_offset + 8, u64, 0) : + xe_map_wr(stream->oa->xe, map, report_offset + 4, u32, 0); } static bool xe_oa_buffer_check_unlocked(struct xe_oa_stream *stream) @@ -275,9 +283,7 @@ static bool xe_oa_buffer_check_unlocked(struct xe_oa_stream *stream) * they were written. If not : (╯°□°)╯︵ ┻━┻ */ while (xe_oa_circ_diff(stream, tail, stream->oa_buffer.tail) >= report_size) { - void *report = stream->oa_buffer.vaddr + tail; - - if (oa_report_id(stream, report) || oa_timestamp(stream, report)) + if (oa_report_id(stream, tail) || oa_timestamp(stream, tail)) break; tail = xe_oa_circ_diff(stream, tail, report_size); @@ -311,30 +317,37 @@ static enum hrtimer_restart xe_oa_poll_check_timer_cb(struct hrtimer *hrtimer) return HRTIMER_RESTART; } +static unsigned long +xe_oa_copy_to_user(struct xe_oa_stream *stream, void __user *dst, u32 report_offset, u32 len) +{ + xe_assert(stream->oa->xe, len <= stream->oa_buffer.format->size); + + xe_map_memcpy_from(stream->oa->xe, stream->oa_buffer.bounce, + &stream->oa_buffer.bo->vmap, report_offset, len); + return copy_to_user(dst, stream->oa_buffer.bounce, len); +} + static int xe_oa_append_report(struct xe_oa_stream *stream, char __user *buf, - size_t count, size_t *offset, const u8 *report) + size_t count, size_t *offset, u32 report_offset) { int report_size = stream->oa_buffer.format->size; int report_size_partial; - u8 *oa_buf_end; if ((count - *offset) < report_size) return -ENOSPC; buf += *offset; - oa_buf_end = stream->oa_buffer.vaddr + stream->oa_buffer.circ_size; - report_size_partial = oa_buf_end - report; + report_size_partial = stream->oa_buffer.circ_size - report_offset; if (report_size_partial < report_size) { - if (copy_to_user(buf, report, report_size_partial)) + if (xe_oa_copy_to_user(stream, buf, report_offset, report_size_partial)) return -EFAULT; buf += report_size_partial; - if (copy_to_user(buf, stream->oa_buffer.vaddr, - report_size - report_size_partial)) + if (xe_oa_copy_to_user(stream, buf, 0, report_size - report_size_partial)) return -EFAULT; - } else if (copy_to_user(buf, report, report_size)) { + } else if (xe_oa_copy_to_user(stream, buf, report_offset, report_size)) { return -EFAULT; } @@ -347,7 +360,6 @@ static int xe_oa_append_reports(struct xe_oa_stream *stream, char __user *buf, size_t count, size_t *offset) { int report_size = stream->oa_buffer.format->size; - u8 *oa_buf_base = stream->oa_buffer.vaddr; u32 gtt_offset = xe_bo_ggtt_addr(stream->oa_buffer.bo); size_t start_offset = *offset; unsigned long flags; @@ -364,26 +376,24 @@ static int xe_oa_append_reports(struct xe_oa_stream *stream, char __user *buf, for (; xe_oa_circ_diff(stream, tail, head); head = xe_oa_circ_incr(stream, head, report_size)) { - u8 *report = oa_buf_base + head; - - ret = xe_oa_append_report(stream, buf, count, offset, report); + ret = xe_oa_append_report(stream, buf, count, offset, head); if (ret) break; if (!(stream->oa_buffer.circ_size % report_size)) { /* Clear out report id and timestamp to detect unlanded reports */ - oa_report_id_clear(stream, (void *)report); - oa_timestamp_clear(stream, (void *)report); + oa_report_id_clear(stream, head); + oa_timestamp_clear(stream, head); } else { - u8 *oa_buf_end = stream->oa_buffer.vaddr + stream->oa_buffer.circ_size; - u32 part = oa_buf_end - report; + struct iosys_map *map = &stream->oa_buffer.bo->vmap; + u32 part = stream->oa_buffer.circ_size - head; /* Zero out the entire report */ if (report_size <= part) { - memset(report, 0, report_size); + xe_map_memset(stream->oa->xe, map, head, 0, report_size); } else { - memset(report, 0, part); - memset(oa_buf_base, 0, report_size - part); + xe_map_memset(stream->oa->xe, map, head, 0, part); + xe_map_memset(stream->oa->xe, map, 0, 0, report_size - part); } } } @@ -436,7 +446,8 @@ static void xe_oa_init_oa_buffer(struct xe_oa_stream *stream) spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags); /* Zero out the OA buffer since we rely on zero report id and timestamp fields */ - memset(stream->oa_buffer.vaddr, 0, xe_bo_size(stream->oa_buffer.bo)); + xe_map_memset(stream->oa->xe, &stream->oa_buffer.bo->vmap, 0, 0, + xe_bo_size(stream->oa_buffer.bo)); } static u32 __format_to_oactrl(const struct xe_oa_format *format, int counter_sel_mask) @@ -699,6 +710,7 @@ static int num_lri_dwords(int num_regs) static void xe_oa_free_oa_buffer(struct xe_oa_stream *stream) { xe_bo_unpin_map_no_vm(stream->oa_buffer.bo); + kfree(stream->oa_buffer.bounce); } static void xe_oa_free_configs(struct xe_oa_stream *stream) @@ -889,9 +901,16 @@ static int xe_oa_alloc_oa_buffer(struct xe_oa_stream *stream, size_t size) return PTR_ERR(bo); stream->oa_buffer.bo = bo; + /* mmap implementation requires OA buffer to be in system memory */ xe_assert(stream->oa->xe, bo->vmap.is_iomem == 0); - stream->oa_buffer.vaddr = bo->vmap.vaddr; + + stream->oa_buffer.bounce = kmalloc(stream->oa_buffer.format->size, GFP_KERNEL); + if (!stream->oa_buffer.bounce) { + xe_bo_unpin_map_no_vm(stream->oa_buffer.bo); + return -ENOMEM; + } + return 0; } diff --git a/drivers/gpu/drm/xe/xe_oa_types.h b/drivers/gpu/drm/xe/xe_oa_types.h index 8906c3084b5f..3d9ec8490899 100644 --- a/drivers/gpu/drm/xe/xe_oa_types.h +++ b/drivers/gpu/drm/xe/xe_oa_types.h @@ -164,8 +164,8 @@ struct xe_oa_buffer { /** @bo: xe_bo backing the OA buffer */ struct xe_bo *bo; - /** @vaddr: mapped vaddr of the OA buffer */ - u8 *vaddr; + /** @bounce: bounce buffer used with xe_map layer */ + void *bounce; /** @ptr_lock: Lock protecting reads/writes to head/tail pointers */ spinlock_t ptr_lock; From 41255b2f1e03b7f949c6b9b491f789d7ea9c49a3 Mon Sep 17 00:00:00 2001 From: Ashutosh Dixit Date: Mon, 27 Apr 2026 15:11:32 -0700 Subject: [PATCH 115/120] drm/xe/oa: Use drm_gem_mmap_obj for OA buffer mmap OA buffer mmap can currently only mmap OA buffer in system memory. CRI MERTOA buffer can be located in device memory. Switch OA buffer mmap to using drm_gem_mmap_obj, which can handle mmap's of both system and device memory buffers. Signed-off-by: Ashutosh Dixit Reviewed-by: Umesh Nerlige Ramappa Link: https://patch.msgid.link/20260427221133.2500532-3-ashutosh.dixit@intel.com --- drivers/gpu/drm/xe/xe_oa.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c index 6ded3c2fce34..83797c9479f7 100644 --- a/drivers/gpu/drm/xe/xe_oa.c +++ b/drivers/gpu/drm/xe/xe_oa.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -902,9 +903,6 @@ static int xe_oa_alloc_oa_buffer(struct xe_oa_stream *stream, size_t size) stream->oa_buffer.bo = bo; - /* mmap implementation requires OA buffer to be in system memory */ - xe_assert(stream->oa->xe, bo->vmap.is_iomem == 0); - stream->oa_buffer.bounce = kmalloc(stream->oa_buffer.format->size, GFP_KERNEL); if (!stream->oa_buffer.bounce) { xe_bo_unpin_map_no_vm(stream->oa_buffer.bo); @@ -1692,8 +1690,6 @@ static int xe_oa_mmap(struct file *file, struct vm_area_struct *vma) { struct xe_oa_stream *stream = file->private_data; struct xe_bo *bo = stream->oa_buffer.bo; - unsigned long start = vma->vm_start; - int i, ret; if (xe_observation_paranoid && !perfmon_capable()) { drm_dbg(&stream->oa->xe->drm, "Insufficient privilege to map OA buffer\n"); @@ -1701,7 +1697,7 @@ static int xe_oa_mmap(struct file *file, struct vm_area_struct *vma) } /* Can mmap the entire OA buffer or nothing (no partial OA buffer mmaps) */ - if (vma->vm_end - vma->vm_start != xe_bo_size(stream->oa_buffer.bo)) { + if (vma->vm_end - vma->vm_start != xe_bo_size(bo)) { drm_dbg(&stream->oa->xe->drm, "Wrong mmap size, must be OA buffer size\n"); return -EINVAL; } @@ -1717,17 +1713,7 @@ static int xe_oa_mmap(struct file *file, struct vm_area_struct *vma) vm_flags_mod(vma, VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP | VM_DONTCOPY, VM_MAYWRITE | VM_MAYEXEC); - xe_assert(stream->oa->xe, bo->ttm.ttm->num_pages == vma_pages(vma)); - for (i = 0; i < bo->ttm.ttm->num_pages; i++) { - ret = remap_pfn_range(vma, start, page_to_pfn(bo->ttm.ttm->pages[i]), - PAGE_SIZE, vma->vm_page_prot); - if (ret) - break; - - start += PAGE_SIZE; - } - - return ret; + return drm_gem_mmap_obj(&bo->ttm.base, xe_bo_size(bo), vma); } static const struct file_operations xe_oa_fops = { From c59395e215b950dd7bb5ac7236d16e4be58f4040 Mon Sep 17 00:00:00 2001 From: Ashutosh Dixit Date: Mon, 27 Apr 2026 15:11:33 -0700 Subject: [PATCH 116/120] drm/xe/oa: Implement Wa_14026633728 CRI Wa_14026633728 requires MERTOA buffer to be allocated in device memory, not system memory (which is the default for OA buffers). v2: Move WA to xe_device_wa_oob.rules and use XE_DEVICE_WA() (Matt Roper) Signed-off-by: Ashutosh Dixit Reviewed-by: Umesh Nerlige Ramappa Link: https://patch.msgid.link/20260427221133.2500532-4-ashutosh.dixit@intel.com --- drivers/gpu/drm/xe/xe_device_wa_oob.rules | 1 + drivers/gpu/drm/xe/xe_oa.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_device_wa_oob.rules b/drivers/gpu/drm/xe/xe_device_wa_oob.rules index d129cddb6ead..92371c490529 100644 --- a/drivers/gpu/drm/xe/xe_device_wa_oob.rules +++ b/drivers/gpu/drm/xe/xe_device_wa_oob.rules @@ -4,3 +4,4 @@ 22019338487_display PLATFORM(LUNARLAKE) 14022085890 SUBPLATFORM(BATTLEMAGE, G21) 14026539277 PLATFORM(NOVALAKE_P), PLATFORM_STEP(A0, B0) +14026633728 PLATFORM(CRESCENTISLAND) diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c index 83797c9479f7..5de5bf19240a 100644 --- a/drivers/gpu/drm/xe/xe_oa.c +++ b/drivers/gpu/drm/xe/xe_oa.c @@ -15,6 +15,7 @@ #include #include +#include #include "abi/guc_actions_slpc_abi.h" #include "instructions/xe_mi_commands.h" @@ -250,6 +251,11 @@ static void oa_timestamp_clear(struct xe_oa_stream *stream, u32 report_offset) xe_map_wr(stream->oa->xe, map, report_offset + 4, u32, 0); } +static bool mert_wa_14026633728(struct xe_oa_stream *s) +{ + return s->oa_unit->type == DRM_XE_OA_UNIT_TYPE_MERT && XE_DEVICE_WA(s->oa->xe, 14026633728); +} + static bool xe_oa_buffer_check_unlocked(struct xe_oa_stream *stream) { u32 gtt_offset = xe_bo_ggtt_addr(stream->oa_buffer.bo); @@ -893,11 +899,14 @@ static void xe_oa_stream_destroy(struct xe_oa_stream *stream) static int xe_oa_alloc_oa_buffer(struct xe_oa_stream *stream, size_t size) { + u32 vram = mert_wa_14026633728(stream) ? + XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(stream->oa->xe)) : + XE_BO_FLAG_SYSTEM; struct xe_bo *bo; bo = xe_bo_create_pin_map_novm(stream->oa->xe, stream->gt->tile, size, ttm_bo_type_kernel, - XE_BO_FLAG_SYSTEM | XE_BO_FLAG_GGTT, false); + vram | XE_BO_FLAG_GGTT, false); if (IS_ERR(bo)) return PTR_ERR(bo); From a68247371b6eb33013429037b28ff713aa60fc5a Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Tue, 28 Apr 2026 11:18:24 +0530 Subject: [PATCH 117/120] drm/xe/sysctrl: Add system controller interrupt handler Add system controller interrupt handler which is denoted by 11th bit in GFX master interrupt register. While at it, add worker for scheduling system controller work. Co-developed-by: Soham Purkait Signed-off-by: Soham Purkait Signed-off-by: Raag Jadav Reviewed-by: Mallesh Koujalagi Reviewed-by: Riana Tauro Link: https://patch.msgid.link/20260428054826.1202076-2-raag.jadav@intel.com Signed-off-by: Riana Tauro --- drivers/gpu/drm/xe/regs/xe_irq_regs.h | 1 + drivers/gpu/drm/xe/xe_irq.c | 2 ++ drivers/gpu/drm/xe/xe_sysctrl.c | 35 +++++++++++++++++++++------ drivers/gpu/drm/xe/xe_sysctrl.h | 1 + drivers/gpu/drm/xe/xe_sysctrl_types.h | 4 +++ 5 files changed, 36 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/regs/xe_irq_regs.h b/drivers/gpu/drm/xe/regs/xe_irq_regs.h index 9d74f454d3ff..1d6b976c4de0 100644 --- a/drivers/gpu/drm/xe/regs/xe_irq_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_irq_regs.h @@ -22,6 +22,7 @@ #define DISPLAY_IRQ REG_BIT(16) #define SOC_H2DMEMINT_IRQ REG_BIT(13) #define I2C_IRQ REG_BIT(12) +#define SYSCTRL_IRQ REG_BIT(11) #define GT_DW_IRQ(x) REG_BIT(x) /* diff --git a/drivers/gpu/drm/xe/xe_irq.c b/drivers/gpu/drm/xe/xe_irq.c index 7560a45f7f64..9e49e2241da4 100644 --- a/drivers/gpu/drm/xe/xe_irq.c +++ b/drivers/gpu/drm/xe/xe_irq.c @@ -24,6 +24,7 @@ #include "xe_mmio.h" #include "xe_pxp.h" #include "xe_sriov.h" +#include "xe_sysctrl.h" #include "xe_tile.h" /* @@ -525,6 +526,7 @@ static irqreturn_t dg1_irq_handler(int irq, void *arg) xe_heci_csc_irq_handler(xe, master_ctl); xe_display_irq_handler(xe, master_ctl); xe_i2c_irq_handler(xe, master_ctl); + xe_sysctrl_irq_handler(xe, master_ctl); xe_mert_irq_handler(xe, master_ctl); gu_misc_iir = gu_misc_irq_ack(xe, master_ctl); } diff --git a/drivers/gpu/drm/xe/xe_sysctrl.c b/drivers/gpu/drm/xe/xe_sysctrl.c index 2bcef304eb9a..7de3e73bd8e0 100644 --- a/drivers/gpu/drm/xe/xe_sysctrl.c +++ b/drivers/gpu/drm/xe/xe_sysctrl.c @@ -8,6 +8,7 @@ #include +#include "regs/xe_irq_regs.h" #include "regs/xe_sysctrl_regs.h" #include "xe_device.h" #include "xe_mmio.h" @@ -30,10 +31,16 @@ static void sysctrl_fini(void *arg) { struct xe_device *xe = arg; + struct xe_sysctrl *sc = &xe->sc; + disable_work_sync(&sc->work); xe->soc_remapper.set_sysctrl_region(xe, 0); } +static void xe_sysctrl_work(struct work_struct *work) +{ +} + /** * xe_sysctrl_init() - Initialize System Controller subsystem * @xe: xe device instance @@ -55,12 +62,6 @@ int xe_sysctrl_init(struct xe_device *xe) if (!xe->info.has_sysctrl) return 0; - xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX); - - ret = devm_add_action_or_reset(xe->drm.dev, sysctrl_fini, xe); - if (ret) - return ret; - sc->mmio = devm_kzalloc(xe->drm.dev, sizeof(*sc->mmio), GFP_KERNEL); if (!sc->mmio) return -ENOMEM; @@ -73,9 +74,29 @@ int xe_sysctrl_init(struct xe_device *xe) if (ret) return ret; + xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX); xe_sysctrl_mailbox_init(sc); + INIT_WORK(&sc->work, xe_sysctrl_work); - return 0; + return devm_add_action_or_reset(xe->drm.dev, sysctrl_fini, xe); +} + +/** + * xe_sysctrl_irq_handler() - Handler for System Controller interrupts + * @xe: xe device instance + * @master_ctl: interrupt register + * + * Handle interrupts generated by System Controller. + */ +void xe_sysctrl_irq_handler(struct xe_device *xe, u32 master_ctl) +{ + struct xe_sysctrl *sc = &xe->sc; + + if (!xe->info.has_sysctrl || !sc->work.func) + return; + + if (master_ctl & SYSCTRL_IRQ) + schedule_work(&sc->work); } /** diff --git a/drivers/gpu/drm/xe/xe_sysctrl.h b/drivers/gpu/drm/xe/xe_sysctrl.h index f3b0f3716b2f..f7469bfc9324 100644 --- a/drivers/gpu/drm/xe/xe_sysctrl.h +++ b/drivers/gpu/drm/xe/xe_sysctrl.h @@ -17,6 +17,7 @@ static inline struct xe_device *sc_to_xe(struct xe_sysctrl *sc) } int xe_sysctrl_init(struct xe_device *xe); +void xe_sysctrl_irq_handler(struct xe_device *xe, u32 master_ctl); void xe_sysctrl_pm_resume(struct xe_device *xe); #endif diff --git a/drivers/gpu/drm/xe/xe_sysctrl_types.h b/drivers/gpu/drm/xe/xe_sysctrl_types.h index 8217f6befe70..5f408d6491ef 100644 --- a/drivers/gpu/drm/xe/xe_sysctrl_types.h +++ b/drivers/gpu/drm/xe/xe_sysctrl_types.h @@ -8,6 +8,7 @@ #include #include +#include struct xe_mmio; @@ -27,6 +28,9 @@ struct xe_sysctrl { /** @phase_bit: Message boundary phase toggle bit (0 or 1) */ bool phase_bit; + + /** @work: Pending events worker */ + struct work_struct work; }; #endif From 21677c5ea98ac16657c572b4a0dee6893ecda1c6 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Tue, 28 Apr 2026 11:18:25 +0530 Subject: [PATCH 118/120] drm/xe/sysctrl: Add system controller event support System controller reports different types of events to GFX endpoint for different usecases, add initial support for them. This will be further extended to service those usecases. Signed-off-by: Raag Jadav Reviewed-by: Mallesh Koujalagi Link: https://patch.msgid.link/20260428054826.1202076-3-raag.jadav@intel.com Signed-off-by: Riana Tauro --- drivers/gpu/drm/xe/Makefile | 1 + drivers/gpu/drm/xe/xe_sysctrl.c | 10 +++ drivers/gpu/drm/xe/xe_sysctrl.h | 1 + drivers/gpu/drm/xe/xe_sysctrl_event.c | 87 +++++++++++++++++++ drivers/gpu/drm/xe/xe_sysctrl_event_types.h | 57 ++++++++++++ drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h | 18 ++++ drivers/gpu/drm/xe/xe_sysctrl_types.h | 3 + 7 files changed, 177 insertions(+) create mode 100644 drivers/gpu/drm/xe/xe_sysctrl_event.c create mode 100644 drivers/gpu/drm/xe/xe_sysctrl_event_types.h diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 8e31b14239ec..f22297545ae6 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -125,6 +125,7 @@ xe-y += xe_bb.o \ xe_survivability_mode.o \ xe_sync.o \ xe_sysctrl.o \ + xe_sysctrl_event.o \ xe_sysctrl_mailbox.o \ xe_tile.o \ xe_tile_sysfs.o \ diff --git a/drivers/gpu/drm/xe/xe_sysctrl.c b/drivers/gpu/drm/xe/xe_sysctrl.c index 7de3e73bd8e0..1db20be8158b 100644 --- a/drivers/gpu/drm/xe/xe_sysctrl.c +++ b/drivers/gpu/drm/xe/xe_sysctrl.c @@ -12,6 +12,7 @@ #include "regs/xe_sysctrl_regs.h" #include "xe_device.h" #include "xe_mmio.h" +#include "xe_pm.h" #include "xe_soc_remapper.h" #include "xe_sysctrl.h" #include "xe_sysctrl_mailbox.h" @@ -39,6 +40,11 @@ static void sysctrl_fini(void *arg) static void xe_sysctrl_work(struct work_struct *work) { + struct xe_sysctrl *sc = container_of(work, struct xe_sysctrl, work); + struct xe_device *xe = sc_to_xe(sc); + + guard(xe_pm_runtime)(xe); + xe_sysctrl_event(sc); } /** @@ -74,6 +80,10 @@ int xe_sysctrl_init(struct xe_device *xe) if (ret) return ret; + ret = devm_mutex_init(xe->drm.dev, &sc->event_lock); + if (ret) + return ret; + xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX); xe_sysctrl_mailbox_init(sc); INIT_WORK(&sc->work, xe_sysctrl_work); diff --git a/drivers/gpu/drm/xe/xe_sysctrl.h b/drivers/gpu/drm/xe/xe_sysctrl.h index f7469bfc9324..090dffb6d55f 100644 --- a/drivers/gpu/drm/xe/xe_sysctrl.h +++ b/drivers/gpu/drm/xe/xe_sysctrl.h @@ -16,6 +16,7 @@ static inline struct xe_device *sc_to_xe(struct xe_sysctrl *sc) return container_of(sc, struct xe_device, sc); } +void xe_sysctrl_event(struct xe_sysctrl *sc); int xe_sysctrl_init(struct xe_device *xe); void xe_sysctrl_irq_handler(struct xe_device *xe, u32 master_ctl); void xe_sysctrl_pm_resume(struct xe_device *xe); diff --git a/drivers/gpu/drm/xe/xe_sysctrl_event.c b/drivers/gpu/drm/xe/xe_sysctrl_event.c new file mode 100644 index 000000000000..5a5721699ce3 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_sysctrl_event.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2026 Intel Corporation + */ + +#include "xe_device.h" +#include "xe_irq.h" +#include "xe_printk.h" +#include "xe_sysctrl.h" +#include "xe_sysctrl_event_types.h" +#include "xe_sysctrl_mailbox.h" +#include "xe_sysctrl_mailbox_types.h" + +static void get_pending_event(struct xe_sysctrl *sc, struct xe_sysctrl_mailbox_command *command) +{ + struct xe_sysctrl_event_response *response = command->data_out; + struct xe_device *xe = sc_to_xe(sc); + u32 count = XE_SYSCTRL_EVENT_FLOOD; + size_t len; + int ret; + + do { + memset(response, 0, sizeof(*response)); + + ret = xe_sysctrl_send_command(sc, command, &len); + if (ret) { + xe_err(xe, "sysctrl: failed to get pending event %d\n", ret); + return; + } + + if (len != sizeof(*response)) { + xe_err(xe, "sysctrl: unexpected event response length %zu (expected %zu)\n", + len, sizeof(*response)); + return; + } + + if (response->event == XE_SYSCTRL_EVENT_THRESHOLD_CROSSED) + xe_warn(xe, "[RAS]: counter threshold crossed\n"); + else + xe_warn(xe, "sysctrl: unexpected event %#x\n", response->event); + + if (!--count) { + xe_err(xe, "sysctrl: event flooding\n"); + return; + } + + xe_dbg(xe, "sysctrl: %u events pending\n", response->count); + } while (response->count); +} + +static void event_request_prepare(struct xe_device *xe, struct xe_sysctrl_app_msg_hdr *header, + struct xe_sysctrl_event_request *request) +{ + struct pci_dev *pdev = to_pci_dev(xe->drm.dev); + + header->data = REG_FIELD_PREP(APP_HDR_GROUP_ID_MASK, XE_SYSCTRL_GROUP_GFSP) | + REG_FIELD_PREP(APP_HDR_COMMAND_MASK, XE_SYSCTRL_CMD_GET_PENDING_EVENT); + + request->vector = xe_device_has_msix(xe) ? XE_IRQ_DEFAULT_MSIX : 0; + request->fn = PCI_FUNC(pdev->devfn); +} + +/** + * xe_sysctrl_event() - Handler for System Controller events + * @sc: System Controller instance + * + * Handle events generated by System Controller. + */ +void xe_sysctrl_event(struct xe_sysctrl *sc) +{ + struct xe_sysctrl_mailbox_command command = {}; + struct xe_sysctrl_event_response response = {}; + struct xe_sysctrl_event_request request = {}; + struct xe_sysctrl_app_msg_hdr header = {}; + + xe_device_assert_mem_access(sc_to_xe(sc)); + event_request_prepare(sc_to_xe(sc), &header, &request); + + command.header = header; + command.data_in = &request; + command.data_in_len = sizeof(request); + command.data_out = &response; + command.data_out_len = sizeof(response); + + guard(mutex)(&sc->event_lock); + get_pending_event(sc, &command); +} diff --git a/drivers/gpu/drm/xe/xe_sysctrl_event_types.h b/drivers/gpu/drm/xe/xe_sysctrl_event_types.h new file mode 100644 index 000000000000..c16c66b9fa7f --- /dev/null +++ b/drivers/gpu/drm/xe/xe_sysctrl_event_types.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_SYSCTRL_EVENT_TYPES_H_ +#define _XE_SYSCTRL_EVENT_TYPES_H_ + +#include + +#define XE_SYSCTRL_EVENT_DATA_LEN 59 + +/* Modify as needed */ +#define XE_SYSCTRL_EVENT_FLOOD 16 + +/** + * enum xe_sysctrl_event - Events reported by System Controller + * + * @XE_SYSCTRL_EVENT_THRESHOLD_CROSSED: Error counter threshold crossed + */ +enum xe_sysctrl_event { + XE_SYSCTRL_EVENT_THRESHOLD_CROSSED = 0x01, +}; + +/** + * struct xe_sysctrl_event_request - Request structure for pending event + */ +struct xe_sysctrl_event_request { + /** @vector: MSI-X vector that was triggered */ + u32 vector; + /** @fn: Function index (0-7) of PCIe device */ + u32 fn:8; + /** @reserved: Reserved for future use */ + u32 reserved:24; + /** @reserved1: Reserved for future use */ + u32 reserved1[2]; +} __packed; + +/** + * struct xe_sysctrl_event_response - Response structure for pending event + */ +struct xe_sysctrl_event_response { + /** @count: Pending event count after this response */ + u32 count; + /** @event: Pending event type */ + u32 event; + /** @timestamp: Timestamp of most recent event */ + u64 timestamp; + /** @extended: Event has extended payload */ + u32 extended:1; + /** @reserved: Reserved for future use */ + u32 reserved:31; + /** @data: Generic event data */ + u32 data[XE_SYSCTRL_EVENT_DATA_LEN]; +} __packed; + +#endif /* _XE_SYSCTRL_EVENT_TYPES_H_ */ diff --git a/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h b/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h index 89456aec6097..84d7c647e743 100644 --- a/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h +++ b/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h @@ -10,6 +10,24 @@ #include "abi/xe_sysctrl_abi.h" +/** + * enum xe_sysctrl_group - System Controller command groups + * + * @XE_SYSCTRL_GROUP_GFSP: GFSP group + */ +enum xe_sysctrl_group { + XE_SYSCTRL_GROUP_GFSP = 0x01, +}; + +/** + * enum xe_sysctrl_gfsp_cmd - Commands supported by GFSP group + * + * @XE_SYSCTRL_CMD_GET_PENDING_EVENT: Retrieve pending event + */ +enum xe_sysctrl_gfsp_cmd { + XE_SYSCTRL_CMD_GET_PENDING_EVENT = 0x07, +}; + /** * struct xe_sysctrl_mailbox_command - System Controller mailbox command */ diff --git a/drivers/gpu/drm/xe/xe_sysctrl_types.h b/drivers/gpu/drm/xe/xe_sysctrl_types.h index 5f408d6491ef..66ba24f43017 100644 --- a/drivers/gpu/drm/xe/xe_sysctrl_types.h +++ b/drivers/gpu/drm/xe/xe_sysctrl_types.h @@ -31,6 +31,9 @@ struct xe_sysctrl { /** @work: Pending events worker */ struct work_struct work; + + /** @event_lock: Mutex protecting pending events */ + struct mutex event_lock; }; #endif From d34b42ffb1dd15603fd20fb8c59891fd30e5988d Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Tue, 28 Apr 2026 11:18:26 +0530 Subject: [PATCH 119/120] drm/xe/ras: Introduce correctable error handling Add initial support for correctable error handling which is serviced using system controller event. Currently we only log the errors in dmesg but this serves as a foundation for RAS infrastructure and will be further extended to facilitate other RAS features. Signed-off-by: Raag Jadav Reviewed-by: Mallesh Koujalagi Reviewed-by: Riana Tauro Link: https://patch.msgid.link/20260428054826.1202076-4-raag.jadav@intel.com Signed-off-by: Riana Tauro --- drivers/gpu/drm/xe/Makefile | 1 + drivers/gpu/drm/xe/xe_ras.c | 93 +++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_ras.h | 15 +++++ drivers/gpu/drm/xe/xe_ras_types.h | 73 +++++++++++++++++++++ drivers/gpu/drm/xe/xe_sysctrl_event.c | 3 +- 5 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/xe/xe_ras.c create mode 100644 drivers/gpu/drm/xe/xe_ras.h create mode 100644 drivers/gpu/drm/xe/xe_ras_types.h diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index f22297545ae6..bd1697733335 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -113,6 +113,7 @@ xe-y += xe_bb.o \ xe_pxp_submit.o \ xe_query.o \ xe_range_fence.o \ + xe_ras.o \ xe_reg_sr.o \ xe_reg_whitelist.o \ xe_ring_ops.o \ diff --git a/drivers/gpu/drm/xe/xe_ras.c b/drivers/gpu/drm/xe/xe_ras.c new file mode 100644 index 000000000000..4cb16b419b0c --- /dev/null +++ b/drivers/gpu/drm/xe/xe_ras.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2026 Intel Corporation + */ + +#include "xe_device.h" +#include "xe_printk.h" +#include "xe_ras.h" +#include "xe_ras_types.h" +#include "xe_sysctrl.h" +#include "xe_sysctrl_event_types.h" + +/* Severity of detected errors */ +enum xe_ras_severity { + XE_RAS_SEV_NOT_SUPPORTED = 0, + XE_RAS_SEV_CORRECTABLE, + XE_RAS_SEV_UNCORRECTABLE, + XE_RAS_SEV_INFORMATIONAL, + XE_RAS_SEV_MAX +}; + +/* Major IP blocks/components where errors can originate */ +enum xe_ras_component { + XE_RAS_COMP_NOT_SUPPORTED = 0, + XE_RAS_COMP_DEVICE_MEMORY, + XE_RAS_COMP_CORE_COMPUTE, + XE_RAS_COMP_RESERVED, + XE_RAS_COMP_PCIE, + XE_RAS_COMP_FABRIC, + XE_RAS_COMP_SOC_INTERNAL, + XE_RAS_COMP_MAX +}; + +static const char *const xe_ras_severities[] = { + [XE_RAS_SEV_NOT_SUPPORTED] = "Not Supported", + [XE_RAS_SEV_CORRECTABLE] = "Correctable Error", + [XE_RAS_SEV_UNCORRECTABLE] = "Uncorrectable Error", + [XE_RAS_SEV_INFORMATIONAL] = "Informational Error", +}; +static_assert(ARRAY_SIZE(xe_ras_severities) == XE_RAS_SEV_MAX); + +static const char *const xe_ras_components[] = { + [XE_RAS_COMP_NOT_SUPPORTED] = "Not Supported", + [XE_RAS_COMP_DEVICE_MEMORY] = "Device Memory", + [XE_RAS_COMP_CORE_COMPUTE] = "Core Compute", + [XE_RAS_COMP_RESERVED] = "Reserved", + [XE_RAS_COMP_PCIE] = "PCIe", + [XE_RAS_COMP_FABRIC] = "Fabric", + [XE_RAS_COMP_SOC_INTERNAL] = "SoC Internal", +}; +static_assert(ARRAY_SIZE(xe_ras_components) == XE_RAS_COMP_MAX); + +static inline const char *sev_to_str(u8 severity) +{ + if (severity >= XE_RAS_SEV_MAX) + severity = XE_RAS_SEV_NOT_SUPPORTED; + + return xe_ras_severities[severity]; +} + +static inline const char *comp_to_str(u8 component) +{ + if (component >= XE_RAS_COMP_MAX) + component = XE_RAS_COMP_NOT_SUPPORTED; + + return xe_ras_components[component]; +} + +void xe_ras_counter_threshold_crossed(struct xe_device *xe, + struct xe_sysctrl_event_response *response) +{ + struct xe_ras_threshold_crossed *pending = (void *)&response->data; + struct xe_ras_error_class *errors = pending->counters; + u32 id, ncounters = pending->ncounters; + + BUILD_BUG_ON(sizeof(response->data) < sizeof(*pending)); + xe_device_assert_mem_access(xe); + + if (!ncounters || ncounters > XE_RAS_NUM_COUNTERS) + xe_err(xe, "sysctrl: unexpected counter threshold crossed %u\n", ncounters); + else + xe_warn(xe, "[RAS]: counter threshold crossed, %u new errors\n", ncounters); + + for (id = 0; id < ncounters && id < XE_RAS_NUM_COUNTERS; id++) { + u8 severity, component; + + severity = errors[id].common.severity; + component = errors[id].common.component; + + xe_warn(xe, "[RAS]: %s %s detected\n", + comp_to_str(component), sev_to_str(severity)); + } +} diff --git a/drivers/gpu/drm/xe/xe_ras.h b/drivers/gpu/drm/xe/xe_ras.h new file mode 100644 index 000000000000..ea90593b62dc --- /dev/null +++ b/drivers/gpu/drm/xe/xe_ras.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_RAS_H_ +#define _XE_RAS_H_ + +struct xe_device; +struct xe_sysctrl_event_response; + +void xe_ras_counter_threshold_crossed(struct xe_device *xe, + struct xe_sysctrl_event_response *response); + +#endif diff --git a/drivers/gpu/drm/xe/xe_ras_types.h b/drivers/gpu/drm/xe/xe_ras_types.h new file mode 100644 index 000000000000..4e63c67f806a --- /dev/null +++ b/drivers/gpu/drm/xe/xe_ras_types.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_RAS_TYPES_H_ +#define _XE_RAS_TYPES_H_ + +#include + +#define XE_RAS_NUM_COUNTERS 16 + +/** + * struct xe_ras_error_common - Error fields that are common across all products + */ +struct xe_ras_error_common { + /** @severity: Error severity */ + u8 severity; + /** @component: IP block where error originated */ + u8 component; +} __packed; + +/** + * struct xe_ras_error_unit - Error unit information + */ +struct xe_ras_error_unit { + /** @tile: Tile identifier */ + u8 tile; + /** @instance: Instance identifier specific to IP */ + u32 instance; +} __packed; + +/** + * struct xe_ras_error_cause - Error cause information + */ +struct xe_ras_error_cause { + /** @cause: Cause/checker */ + u32 cause; + /** @reserved: For future use */ + u8 reserved; +} __packed; + +/** + * struct xe_ras_error_product - Error fields that are specific to the product + */ +struct xe_ras_error_product { + /** @unit: Unit within IP block */ + struct xe_ras_error_unit unit; + /** @cause: Cause/checker */ + struct xe_ras_error_cause cause; +} __packed; + +/** + * struct xe_ras_error_class - Combines common and product-specific parts + */ +struct xe_ras_error_class { + /** @common: Common error type and component */ + struct xe_ras_error_common common; + /** @product: Product-specific unit and cause */ + struct xe_ras_error_product product; +} __packed; + +/** + * struct xe_ras_threshold_crossed - Data for threshold crossed event + */ +struct xe_ras_threshold_crossed { + /** @ncounters: Number of error counters that crossed thresholds */ + u32 ncounters; + /** @counters: Array of error counters that crossed threshold */ + struct xe_ras_error_class counters[XE_RAS_NUM_COUNTERS]; +} __packed; + +#endif diff --git a/drivers/gpu/drm/xe/xe_sysctrl_event.c b/drivers/gpu/drm/xe/xe_sysctrl_event.c index 5a5721699ce3..b4d17329af6c 100644 --- a/drivers/gpu/drm/xe/xe_sysctrl_event.c +++ b/drivers/gpu/drm/xe/xe_sysctrl_event.c @@ -6,6 +6,7 @@ #include "xe_device.h" #include "xe_irq.h" #include "xe_printk.h" +#include "xe_ras.h" #include "xe_sysctrl.h" #include "xe_sysctrl_event_types.h" #include "xe_sysctrl_mailbox.h" @@ -35,7 +36,7 @@ static void get_pending_event(struct xe_sysctrl *sc, struct xe_sysctrl_mailbox_c } if (response->event == XE_SYSCTRL_EVENT_THRESHOLD_CROSSED) - xe_warn(xe, "[RAS]: counter threshold crossed\n"); + xe_ras_counter_threshold_crossed(xe, response); else xe_warn(xe, "sysctrl: unexpected event %#x\n", response->event); From 438a9200d6abdae2be64a5ce085cee0244a7c231 Mon Sep 17 00:00:00 2001 From: Tejas Upadhyay Date: Wed, 29 Apr 2026 15:01:39 +0530 Subject: [PATCH 120/120] drm/xe: Use drmm_mutex_init for VRAM manager lock Replace mutex_init()/mutex_destroy() with drmm_mutex_init() for the VRAM manager lock. This leverages DRM managed infrastructure to automatically destroy the mutex during device teardown, eliminating manual mutex_destroy() calls in both the normal fini path and the gpu_buddy_init() error path. Assisted-by: Claude:claude-opus-4.6 Reviewed-by: Matthew Auld Reviewed-by: Matthew Brost Link: https://patch.msgid.link/20260429093138.3899280-2-tejas.upadhyay@intel.com Signed-off-by: Tejas Upadhyay --- drivers/gpu/drm/xe/xe_ttm_vram_mgr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c index 5fd0d5506a7e..6ba47996bc7c 100644 --- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c +++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c @@ -292,8 +292,6 @@ static void xe_ttm_vram_mgr_fini(struct drm_device *dev, void *arg) ttm_resource_manager_cleanup(&mgr->manager); ttm_set_driver_manager(&xe->ttm, mgr->mem_type, NULL); - - mutex_destroy(&mgr->lock); } int __xe_ttm_vram_mgr_init(struct xe_device *xe, struct xe_ttm_vram_mgr *mgr, @@ -312,7 +310,9 @@ int __xe_ttm_vram_mgr_init(struct xe_device *xe, struct xe_ttm_vram_mgr *mgr, man->func = &xe_ttm_vram_mgr_func; mgr->mem_type = mem_type; - mutex_init(&mgr->lock); + err = drmm_mutex_init(&xe->drm, &mgr->lock); + if (err) + return err; mgr->default_page_size = default_page_size; mgr->visible_size = io_size; mgr->visible_avail = io_size;