From 71d61e3e299a17139e47f980a4d6f425b2c59bf7 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Mon, 11 May 2026 15:41:34 +0000 Subject: [PATCH 01/31] drm/xe/gsc: Fix double-free of managed BO in error path The error path in xe_gsc_init_post_hwconfig() explicitly frees a BO allocated with xe_managed_bo_create_pin_map() via xe_bo_unpin_map_no_vm(). Since the managed BO already has a devm cleanup action registered, this causes a double-free when devm unwinds during probe failure. Remove the explicit free and let devm handle it, consistent with all other xe_managed_bo_create_pin_map() callers. Fixes: 2e5d47fe7839 ("drm/xe/uc: Use managed bo for HuC and GSC objects") Reviewed-by: Daniele Ceraolo Spurio Assisted-by: Claude:claude-opus-4.6 Link: https://patch.msgid.link/20260511154134.223696-1-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_gsc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c index 0d13e357fb43..aab59dc647fb 100644 --- a/drivers/gpu/drm/xe/xe_gsc.c +++ b/drivers/gpu/drm/xe/xe_gsc.c @@ -482,8 +482,7 @@ int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc) EXEC_QUEUE_FLAG_PERMANENT, 0); if (IS_ERR(q)) { xe_gt_err(gt, "Failed to create queue for GSC submission\n"); - err = PTR_ERR(q); - goto out_bo; + return PTR_ERR(q); } wq = alloc_ordered_workqueue("gsc-ordered-wq", 0); @@ -506,8 +505,6 @@ int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc) out_q: xe_exec_queue_put(q); -out_bo: - xe_bo_unpin_map_no_vm(bo); return err; } From 1d60990cdb0b6fbf70ec5fdd96c0b214c455b71e Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Mon, 11 May 2026 15:33:07 +0000 Subject: [PATCH 02/31] drm/xe/gt_idle: Use NSEC_PER_MSEC instead of float literal The residency multiplier conversion in get_residency_ms() used the floating-point literal 1e6 as the divisor of mul_u64_u32_div(). While the compiler constant-folds this to an integer, using float literals in kernel code is bad practice since the kernel generally avoids floating-point operations. Replace 1e6 with the standard NSEC_PER_MSEC macro from , which is both self-documenting (ns to ms conversion) and unambiguously integer. Add the corresponding include rather than relying on transitive inclusion. No functional change. Assisted-by: Claude:claude-opus-4.6 Reviewed-by: Nitin Gote Link: https://patch.msgid.link/20260511153307.223435-1-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_gt_idle.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_gt_idle.c b/drivers/gpu/drm/xe/xe_gt_idle.c index 4a2d9edb6a4c..04b24e1c8b78 100644 --- a/drivers/gpu/drm/xe/xe_gt_idle.c +++ b/drivers/gpu/drm/xe/xe_gt_idle.c @@ -3,6 +3,8 @@ * Copyright © 2023 Intel Corporation */ +#include + #include #include @@ -93,7 +95,7 @@ static u64 get_residency_ms(struct xe_gt_idle *gtidle, u64 cur_residency) gtidle->cur_residency = cur_residency; /* residency multiplier in ns, convert to ms */ - cur_residency = mul_u64_u32_div(cur_residency, gtidle->residency_multiplier, 1e6); + cur_residency = mul_u64_u32_div(cur_residency, gtidle->residency_multiplier, NSEC_PER_MSEC); return cur_residency; } From 86ebfbf1fb152f1898fdc9a70005f7ffad083b48 Mon Sep 17 00:00:00 2001 From: Jakub Kolakowski Date: Tue, 31 Mar 2026 15:22:59 +0000 Subject: [PATCH 03/31] drm/xe/sriov: Mark NVL as SR-IOV capable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable SR-IOV support for NVL platforms. Signed-off-by: Jakub Kolakowski Cc: Michal Wajdeczko Cc: Piotr Piórkowski Cc: Dnyaneshwar Bhadane Cc: Matt Roper Reviewed-by: Tomasz Lis Link: https://patch.msgid.link/20260331152259.58270-1-jakub1.kolakowski@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index 12d3be7f9f6c..1243c7d8ed10 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -444,6 +444,7 @@ static const struct xe_device_desc nvls_desc = { .has_display = true, .has_flat_ccs = 1, .has_pre_prod_wa = 1, + .has_sriov = true, .max_gt_per_tile = 2, MULTI_LRC_MASK, .require_force_probe = true, @@ -482,6 +483,7 @@ static const struct xe_device_desc nvlp_desc = { .has_flat_ccs = 1, .has_page_reclaim_hw_assist = true, .has_pre_prod_wa = true, + .has_sriov = true, .max_gt_per_tile = 2, MULTI_LRC_MASK, .require_force_probe = true, From 9172676bf1b4adba1992e5c4dedbc9af27701253 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 12 May 2026 20:33:36 +0200 Subject: [PATCH 04/31] drm/xe: Drop unused drm/drm_atomic_helper.h include We don't need this header in xe_device.c file. Signed-off-by: Michal Wajdeczko Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260512183342.3374-2-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_device.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 4b45b617a039..6512f1dfe691 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -10,7 +10,6 @@ #include #include -#include #include #include #include From b424e0db8282f2785e3b05240d62886f1cc8f4b3 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 12 May 2026 20:33:37 +0200 Subject: [PATCH 05/31] drm/xe/display: Drop xe_display_driver_remove() stub The function was removed by commit d41d048043c4 ("drm/xe/display: Drop xe_display_driver_remove()") but we missed to remove its stub. Signed-off-by: Michal Wajdeczko Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260512183342.3374-3-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/display/xe_display.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/xe/display/xe_display.h b/drivers/gpu/drm/xe/display/xe_display.h index 76db95c25f7e..fb1db84db966 100644 --- a/drivers/gpu/drm/xe/display/xe_display.h +++ b/drivers/gpu/drm/xe/display/xe_display.h @@ -42,7 +42,6 @@ void xe_display_pm_runtime_resume(struct xe_device *xe); static inline int xe_display_driver_probe_defer(struct pci_dev *pdev) { return 0; } static inline void xe_display_driver_set_hooks(struct drm_driver *driver) { } -static inline void xe_display_driver_remove(struct xe_device *xe) {} static inline int xe_display_probe(struct xe_device *xe) { return 0; } From 9350f47228833751789db9563e5926511f09e016 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 12 May 2026 20:33:38 +0200 Subject: [PATCH 06/31] drm/xe/display: Prefer forward declarations There is no need to include xe_device.h in the xe_display.h header. Include it in the xe_display.c file instead. Signed-off-by: Michal Wajdeczko Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260512183342.3374-4-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/display/xe_display.c | 1 + drivers/gpu/drm/xe/display/xe_display.h | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 0747044f7c2a..263e92203c9d 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -36,6 +36,7 @@ #include "intel_hotplug.h" #include "intel_opregion.h" #include "skl_watermark.h" +#include "xe_device.h" #include "xe_display_bo.h" #include "xe_display_pcode.h" #include "xe_display_rpm.h" diff --git a/drivers/gpu/drm/xe/display/xe_display.h b/drivers/gpu/drm/xe/display/xe_display.h index fb1db84db966..95acf0fd8e7b 100644 --- a/drivers/gpu/drm/xe/display/xe_display.h +++ b/drivers/gpu/drm/xe/display/xe_display.h @@ -6,9 +6,11 @@ #ifndef _XE_DISPLAY_H_ #define _XE_DISPLAY_H_ -#include "xe_device.h" +#include struct drm_driver; +struct pci_dev; +struct xe_device; #if IS_ENABLED(CONFIG_DRM_XE_DISPLAY) From 358315f019cbc5017ad3acf0bb05950a423cf1b6 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 12 May 2026 20:33:39 +0200 Subject: [PATCH 07/31] drm/xe/display: Add macro with display driver ops Instead of updating the drm_driver.fbdev_probe field in the runtime, we can use macro which value depends on the actual Kconfig setup. The .fbdev_probe hook will not be used by the drm core unless we also enable a DRIVER_MODESET driver feature flag, and this flag still depends on the xe_modparam.probe_display parameter. Signed-off-by: Michal Wajdeczko Cc: Jani Nikula Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260512183342.3374-5-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/display/xe_display.c | 12 ++++++++---- drivers/gpu/drm/xe/display/xe_display.h | 11 +++++++++++ drivers/gpu/drm/xe/xe_device.c | 2 ++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 263e92203c9d..7e7d476da8ce 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -85,10 +85,6 @@ void xe_display_driver_set_hooks(struct drm_driver *driver) if (!xe_modparam.probe_display) return; -#ifdef CONFIG_DRM_FBDEV_EMULATION - driver->fbdev_probe = intel_fbdev_driver_fbdev_probe; -#endif - driver->driver_features |= DRIVER_MODESET | DRIVER_ATOMIC; } @@ -603,3 +599,11 @@ int xe_display_probe(struct xe_device *xe) unset_display_features(xe); return 0; } + +#ifdef CONFIG_DRM_FBDEV_EMULATION +int xe_display_driver_fbdev_probe(struct drm_fb_helper *fbh, + struct drm_fb_helper_surface_size *sizes) +{ + return intel_fbdev_driver_fbdev_probe(fbh, sizes); +} +#endif diff --git a/drivers/gpu/drm/xe/display/xe_display.h b/drivers/gpu/drm/xe/display/xe_display.h index 95acf0fd8e7b..deec0232532e 100644 --- a/drivers/gpu/drm/xe/display/xe_display.h +++ b/drivers/gpu/drm/xe/display/xe_display.h @@ -9,6 +9,8 @@ #include struct drm_driver; +struct drm_fb_helper; +struct drm_fb_helper_surface_size; struct pci_dev; struct xe_device; @@ -16,6 +18,8 @@ struct xe_device; bool xe_display_driver_probe_defer(struct pci_dev *pdev); void xe_display_driver_set_hooks(struct drm_driver *driver); +int xe_display_driver_fbdev_probe(struct drm_fb_helper *fbh, + struct drm_fb_helper_surface_size *sizes); int xe_display_probe(struct xe_device *xe); @@ -40,8 +44,15 @@ void xe_display_pm_runtime_suspend(struct xe_device *xe); void xe_display_pm_runtime_suspend_late(struct xe_device *xe); void xe_display_pm_runtime_resume(struct xe_device *xe); +#define XE_DISPLAY_DRIVER_OPS \ + .fbdev_probe = PTR_IF(IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION), \ + xe_display_driver_fbdev_probe) + #else +#define XE_DISPLAY_DRIVER_OPS \ + .fbdev_probe = NULL + static inline int xe_display_driver_probe_defer(struct pci_dev *pdev) { return 0; } static inline void xe_display_driver_set_hooks(struct drm_driver *driver) { } diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 6512f1dfe691..3bca4c1d1d5f 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -414,6 +414,7 @@ static struct drm_driver regular_driver = { .major = DRIVER_MAJOR, .minor = DRIVER_MINOR, .patchlevel = DRIVER_PATCHLEVEL, + XE_DISPLAY_DRIVER_OPS, }; #ifdef CONFIG_PCI_IOV @@ -435,6 +436,7 @@ static struct drm_driver admin_only_driver = { .major = DRIVER_MAJOR, .minor = DRIVER_MINOR, .patchlevel = DRIVER_PATCHLEVEL, + XE_DISPLAY_DRIVER_OPS, }; /** From 7caa8cad3ae04c7b18792e5c18002f2c60db26c7 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 12 May 2026 20:33:40 +0200 Subject: [PATCH 08/31] drm/xe/display: Add macro with display driver features Instead of updating drm_driver.driver_features in the runtime, we can use macro which value depends on the CONFIG_DRM_XE_DISPLAY. And if display support is later disabled by the xe_modparam then we will clear related bits in the drm_device.driver_features instead. Signed-off-by: Michal Wajdeczko Cc: Jani Nikula Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260512183342.3374-6-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/display/xe_display.c | 4 +--- drivers/gpu/drm/xe/display/xe_display.h | 2 ++ drivers/gpu/drm/xe/xe_device.c | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 7e7d476da8ce..7e5382fc161d 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -84,13 +84,11 @@ void xe_display_driver_set_hooks(struct drm_driver *driver) { if (!xe_modparam.probe_display) return; - - driver->driver_features |= DRIVER_MODESET | DRIVER_ATOMIC; } static void unset_display_features(struct xe_device *xe) { - xe->drm.driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC); + xe->drm.driver_features &= ~XE_DISPLAY_DRIVER_FEATURES; } static void xe_display_fini_early(void *arg) diff --git a/drivers/gpu/drm/xe/display/xe_display.h b/drivers/gpu/drm/xe/display/xe_display.h index deec0232532e..d2b105d5f2a1 100644 --- a/drivers/gpu/drm/xe/display/xe_display.h +++ b/drivers/gpu/drm/xe/display/xe_display.h @@ -44,12 +44,14 @@ void xe_display_pm_runtime_suspend(struct xe_device *xe); void xe_display_pm_runtime_suspend_late(struct xe_device *xe); void xe_display_pm_runtime_resume(struct xe_device *xe); +#define XE_DISPLAY_DRIVER_FEATURES (DRIVER_MODESET | DRIVER_ATOMIC) #define XE_DISPLAY_DRIVER_OPS \ .fbdev_probe = PTR_IF(IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION), \ xe_display_driver_fbdev_probe) #else +#define XE_DISPLAY_DRIVER_FEATURES 0 #define XE_DISPLAY_DRIVER_OPS \ .fbdev_probe = NULL diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 3bca4c1d1d5f..c053e4d2692f 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -393,6 +393,7 @@ bool xe_is_xe_file(const struct file *file) static struct drm_driver regular_driver = { .driver_features = + XE_DISPLAY_DRIVER_FEATURES | DRIVER_GEM | DRIVER_RENDER | DRIVER_SYNCOBJ | DRIVER_SYNCOBJ_TIMELINE | DRIVER_GEM_GPUVA, @@ -425,6 +426,7 @@ static const struct drm_ioctl_desc xe_ioctls_admin_only[] = { static struct drm_driver admin_only_driver = { .driver_features = + XE_DISPLAY_DRIVER_FEATURES | DRIVER_GEM | DRIVER_RENDER | DRIVER_GEM_GPUVA, .open = xe_file_open, .postclose = xe_file_close, From 839ffd94f08353b09c4c855634718fbc768ddce2 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 12 May 2026 20:33:41 +0200 Subject: [PATCH 09/31] drm/xe/display: Drop xe_display_driver_set_hooks() This function is now no-op. Signed-off-by: Michal Wajdeczko Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260512183342.3374-7-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/display/xe_display.c | 16 ---------------- drivers/gpu/drm/xe/display/xe_display.h | 3 +-- drivers/gpu/drm/xe/xe_device.c | 2 -- 3 files changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 7e5382fc161d..d6aea18025af 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -70,22 +70,6 @@ bool xe_display_driver_probe_defer(struct pci_dev *pdev) return intel_display_driver_probe_defer(pdev); } -/** - * xe_display_driver_set_hooks - Add driver flags and hooks for display - * @driver: DRM device driver - * - * Set features and function hooks in @driver that are needed for driving the - * display IP. This sets the driver's capability of driving display, regardless - * if the device has it enabled - * - * Note: This is called before xe or display device creation. - */ -void xe_display_driver_set_hooks(struct drm_driver *driver) -{ - if (!xe_modparam.probe_display) - return; -} - static void unset_display_features(struct xe_device *xe) { xe->drm.driver_features &= ~XE_DISPLAY_DRIVER_FEATURES; diff --git a/drivers/gpu/drm/xe/display/xe_display.h b/drivers/gpu/drm/xe/display/xe_display.h index d2b105d5f2a1..60291cb154df 100644 --- a/drivers/gpu/drm/xe/display/xe_display.h +++ b/drivers/gpu/drm/xe/display/xe_display.h @@ -17,7 +17,7 @@ struct xe_device; #if IS_ENABLED(CONFIG_DRM_XE_DISPLAY) bool xe_display_driver_probe_defer(struct pci_dev *pdev); -void xe_display_driver_set_hooks(struct drm_driver *driver); + int xe_display_driver_fbdev_probe(struct drm_fb_helper *fbh, struct drm_fb_helper_surface_size *sizes); @@ -56,7 +56,6 @@ void xe_display_pm_runtime_resume(struct xe_device *xe); .fbdev_probe = NULL static inline int xe_display_driver_probe_defer(struct pci_dev *pdev) { return 0; } -static inline void xe_display_driver_set_hooks(struct drm_driver *driver) { } static inline int xe_display_probe(struct xe_device *xe) { return 0; } diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index c053e4d2692f..7519cda3f42c 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -491,8 +491,6 @@ struct xe_device *xe_device_create(struct pci_dev *pdev, driver = &admin_only_driver; #endif - xe_display_driver_set_hooks(driver); - err = aperture_remove_conflicting_pci_devices(pdev, driver->name); if (err) return ERR_PTR(err); From 4de503bde4d76e8d75b226c316ba9f879c09cfb9 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 12 May 2026 20:33:42 +0200 Subject: [PATCH 10/31] drm/xe: Make drm_driver const After removing runtime modification to our drm_driver definitions, we can make them const as they should be. Signed-off-by: Michal Wajdeczko Cc: Rodrigo Vivi Cc: Jani Nikula Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260512183342.3374-8-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 7519cda3f42c..576095cf0952 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -391,7 +391,7 @@ bool xe_is_xe_file(const struct file *file) return file->f_op == &xe_driver_fops; } -static struct drm_driver regular_driver = { +static const struct drm_driver regular_driver = { .driver_features = XE_DISPLAY_DRIVER_FEATURES | DRIVER_GEM | @@ -424,7 +424,7 @@ static const struct drm_ioctl_desc xe_ioctls_admin_only[] = { DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl, DRM_RENDER_ALLOW), }; -static struct drm_driver admin_only_driver = { +static const struct drm_driver admin_only_driver = { .driver_features = XE_DISPLAY_DRIVER_FEATURES | DRIVER_GEM | DRIVER_RENDER | DRIVER_GEM_GPUVA, @@ -478,7 +478,7 @@ 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; + const struct drm_driver *driver = ®ular_driver; struct xe_device *xe; int err; From 314e31c9a8a1c421ee4f7f755b9348aefbbca090 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 14 May 2026 17:57:26 +0200 Subject: [PATCH 11/31] drm/xe/vf: Fix signature of print functions We have plugged-in existing VF print functions into our GT debugfs show helper as-is, but we missed that the helper expects functions to return int, while they were defined as void. This can lead to errors being reported when CFI is enabled. Fixes: 63d8cb8fe3dd ("drm/xe/vf: Expose SR-IOV VF attributes to GT debugfs") Signed-off-by: Michal Wajdeczko Cc: Mohanram Meenakshisundaram Reviewed-by: Shuicheng Lin Link: https://patch.msgid.link/20260514155726.7165-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 24 ++++++++++++++++++------ drivers/gpu/drm/xe/xe_gt_sriov_vf.h | 6 +++--- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c index 8989c8e1be95..0cd9d77f3351 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c @@ -1137,13 +1137,15 @@ void xe_gt_sriov_vf_write32(struct xe_gt *gt, struct xe_reg reg, u32 val) } /** - * xe_gt_sriov_vf_print_config - Print VF self config. + * xe_gt_sriov_vf_print_config() - Print VF self config. * @gt: the &xe_gt * @p: the &drm_printer * * This function is for VF use only. + * + * Return: always 0. */ -void xe_gt_sriov_vf_print_config(struct xe_gt *gt, struct drm_printer *p) +int xe_gt_sriov_vf_print_config(struct xe_gt *gt, struct drm_printer *p) { struct xe_gt_sriov_vf_selfconfig *config = >->sriov.vf.self_config; struct xe_device *xe = gt_to_xe(gt); @@ -1170,16 +1172,20 @@ void xe_gt_sriov_vf_print_config(struct xe_gt *gt, struct drm_printer *p) drm_printf(p, "GuC contexts:\t%u\n", config->num_ctxs); drm_printf(p, "GuC doorbells:\t%u\n", config->num_dbs); + + return 0; } /** - * xe_gt_sriov_vf_print_runtime - Print VF's runtime regs received from PF. + * xe_gt_sriov_vf_print_runtime() - Print VF's runtime regs received from PF. * @gt: the &xe_gt * @p: the &drm_printer * * This function is for VF use only. + * + * Return: always 0. */ -void xe_gt_sriov_vf_print_runtime(struct xe_gt *gt, struct drm_printer *p) +int xe_gt_sriov_vf_print_runtime(struct xe_gt *gt, struct drm_printer *p) { struct vf_runtime_reg *vf_regs = gt->sriov.vf.runtime.regs; unsigned int size = gt->sriov.vf.runtime.num_regs; @@ -1188,16 +1194,20 @@ void xe_gt_sriov_vf_print_runtime(struct xe_gt *gt, struct drm_printer *p) for (; size--; vf_regs++) drm_printf(p, "%#x = %#x\n", vf_regs->offset, vf_regs->value); + + return 0; } /** - * xe_gt_sriov_vf_print_version - Print VF ABI versions. + * xe_gt_sriov_vf_print_version() - Print VF ABI versions. * @gt: the &xe_gt * @p: the &drm_printer * * This function is for VF use only. + * + * Return: always 0. */ -void xe_gt_sriov_vf_print_version(struct xe_gt *gt, struct drm_printer *p) +int xe_gt_sriov_vf_print_version(struct xe_gt *gt, struct drm_printer *p) { struct xe_device *xe = gt_to_xe(gt); struct xe_uc_fw_version *guc_version = >->sriov.vf.guc_version; @@ -1227,6 +1237,8 @@ void xe_gt_sriov_vf_print_version(struct xe_gt *gt, struct drm_printer *p) GUC_RELAY_VERSION_LATEST_MAJOR, GUC_RELAY_VERSION_LATEST_MINOR); drm_printf(p, "\thandshake:\t%u.%u\n", pf_version->major, pf_version->minor); + + return 0; } static bool vf_post_migration_shutdown(struct xe_gt *gt) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h index a6f7127521a5..79878f21b1da 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h @@ -35,9 +35,9 @@ bool xe_gt_sriov_vf_sched_groups_enabled(struct xe_gt *gt); u32 xe_gt_sriov_vf_read32(struct xe_gt *gt, struct xe_reg reg); void xe_gt_sriov_vf_write32(struct xe_gt *gt, struct xe_reg reg, u32 val); -void xe_gt_sriov_vf_print_config(struct xe_gt *gt, struct drm_printer *p); -void xe_gt_sriov_vf_print_runtime(struct xe_gt *gt, struct drm_printer *p); -void xe_gt_sriov_vf_print_version(struct xe_gt *gt, struct drm_printer *p); +int xe_gt_sriov_vf_print_config(struct xe_gt *gt, struct drm_printer *p); +int xe_gt_sriov_vf_print_runtime(struct xe_gt *gt, struct drm_printer *p); +int xe_gt_sriov_vf_print_version(struct xe_gt *gt, struct drm_printer *p); int xe_gt_sriov_vf_wait_valid_ggtt(struct xe_gt *gt); int xe_vf_migration_fixups_complete_count(struct xe_gt *gt); From ff1d386a8359746d9699ac30336e3b0684c68958 Mon Sep 17 00:00:00 2001 From: Mohanram Meenakshisundaram Date: Thu, 14 May 2026 23:19:18 +0530 Subject: [PATCH 12/31] drm/xe/pf: Fix CFI failure in debugfs access Reading debugfs file (/sys/kernel/debug/dri/0/gt*/pf/adverse_events) with CFI (Control Flow Integrity) enabled, the kernel panics at xe_gt_debugfs_simple_show+0x82/0xc0. xe_gt_debugfs_simple_show() declare a function pointer expecting int return type, but xe_gt_sriov_pf_monitor_print_events() is void return type, leading to CFI failure and kernel panic. [507620.973657] CFI failure at xe_gt_debugfs_simple_show+0x82/0xc0 [xe] (target: xe_gt_sriov_pf_monitor_print_events+0x0/0x130 [xe]; expected type: 0xd72c7139) Fix xe_gt_sriov_pf_monitor_print_events() function by updating to return an int type. Fixes: 1c99d3d3edab ("drm/xe/pf: Expose PF monitor details via debugfs") Signed-off-by: Mohanram Meenakshisundaram Reviewed-by: Michal Wajdeczko Signed-off-by: Michal Wajdeczko Link: https://patch.msgid.link/20260514174918.1556357-2-mohanram.meenakshisundaram@intel.com --- drivers/gpu/drm/xe/xe_gt_sriov_pf_monitor.c | 6 +++++- drivers/gpu/drm/xe/xe_gt_sriov_pf_monitor.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_monitor.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_monitor.c index 7d532bded02a..a85ba4435378 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_monitor.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_monitor.c @@ -114,8 +114,10 @@ int xe_gt_sriov_pf_monitor_process_guc2pf(struct xe_gt *gt, const u32 *msg, u32 * VFs with no events are not printed. * * This function can only be called on PF. + * + * Return: always 0 */ -void xe_gt_sriov_pf_monitor_print_events(struct xe_gt *gt, struct drm_printer *p) +int xe_gt_sriov_pf_monitor_print_events(struct xe_gt *gt, struct drm_printer *p) { unsigned int n, total_vfs = xe_gt_sriov_pf_get_totalvfs(gt); const struct xe_gt_sriov_monitor *data; @@ -144,4 +146,6 @@ void xe_gt_sriov_pf_monitor_print_events(struct xe_gt *gt, struct drm_printer *p #undef __format #undef __value } + + return 0; } diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_monitor.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_monitor.h index 7ca9351a271b..0b8f088d3a16 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_monitor.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_monitor.h @@ -13,7 +13,7 @@ struct drm_printer; struct xe_gt; void xe_gt_sriov_pf_monitor_flr(struct xe_gt *gt, u32 vfid); -void xe_gt_sriov_pf_monitor_print_events(struct xe_gt *gt, struct drm_printer *p); +int xe_gt_sriov_pf_monitor_print_events(struct xe_gt *gt, struct drm_printer *p); #ifdef CONFIG_PCI_IOV int xe_gt_sriov_pf_monitor_process_guc2pf(struct xe_gt *gt, const u32 *msg, u32 len); From 8f765f0c054e0fb39980a76b4c899b027395929d Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 14 May 2026 18:44:44 -0300 Subject: [PATCH 13/31] drm/xe: Define CACHE_MODE_1 as MCR register CACHE_MODE_1 is a MCR register for all platforms that currently use it in the Xe driver. Use XE_REG_MCR() when defining it. Fixes: 8cd7e9759766 ("drm/xe: Add missing DG2 lrc workarounds") Fixes: ff063430caa8 ("drm/xe/mtl: Add some initial MTL workarounds") Bspec: 66534, 67788 Reviewed-by: Matt Roper Link: https://patch.msgid.link/20260514-rtp-mcr-check-v3-1-30dd47855fee@intel.com Signed-off-by: Gustavo Sousa --- 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 16c87ce3f614..408933aee08a 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -152,7 +152,7 @@ #define XEHPG_INSTDONE_GEOM_SVGUNIT XE_REG_MCR(0x666c) -#define CACHE_MODE_1 XE_REG(0x7004, XE_REG_OPTION_MASKED) +#define CACHE_MODE_1 XE_REG_MCR(0x7004, XE_REG_OPTION_MASKED) #define MSAA_OPTIMIZATION_REDUC_DISABLE REG_BIT(11) #define COMMON_SLICE_CHICKEN1 XE_REG(0x7010, XE_REG_OPTION_MASKED) From a672725fdbfc3ea430130039d677c7dc98d59df8 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 14 May 2026 18:44:45 -0300 Subject: [PATCH 14/31] drm/xe: Define and use MCR version of COMMON_SLICE_CHICKEN1 The register COMMON_SLICE_CHICKEN1 is a MCR register on Xe2. Let's make sure to define a MCR version of it and use it for the relevant IP versions. Use XEHP_ as prefix for the register name, since it is MCR as of Xe_HP. Fixes: a5d221924e13 ("drm/xe/xe2_hpg: Add set of workarounds") Fixes: 9f18b55b6d3f ("drm/xe/xe2: Add workaround 18033852989") Bspec: 66534, 71185 Reviewed-by: Matt Roper Link: https://patch.msgid.link/20260514-rtp-mcr-check-v3-2-30dd47855fee@intel.com Signed-off-by: Gustavo Sousa --- drivers/gpu/drm/xe/regs/xe_gt_regs.h | 1 + drivers/gpu/drm/xe/xe_wa.c | 2 +- 2 files changed, 2 insertions(+), 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 408933aee08a..b21c66a1b777 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -156,6 +156,7 @@ #define MSAA_OPTIMIZATION_REDUC_DISABLE REG_BIT(11) #define COMMON_SLICE_CHICKEN1 XE_REG(0x7010, XE_REG_OPTION_MASKED) +#define XEHP_COMMON_SLICE_CHICKEN1 XE_REG_MCR(0x7010, XE_REG_OPTION_MASKED) #define DISABLE_BOTTOM_CLIP_RECTANGLE_TEST REG_BIT(14) #define HIZ_CHICKEN XE_REG(0x7018, XE_REG_OPTION_MASKED) diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c index 49f5e3e4c7cc..d6f94486673e 100644 --- a/drivers/gpu/drm/xe/xe_wa.c +++ b/drivers/gpu/drm/xe/xe_wa.c @@ -664,7 +664,7 @@ static const struct xe_rtp_entry_sr lrc_was[] = { }, { XE_RTP_NAME("18033852989"), XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2004), ENGINE_CLASS(RENDER)), - XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN1, DISABLE_BOTTOM_CLIP_RECTANGLE_TEST)) + XE_RTP_ACTIONS(SET(XEHP_COMMON_SLICE_CHICKEN1, DISABLE_BOTTOM_CLIP_RECTANGLE_TEST)) }, { XE_RTP_NAME("15016589081"), XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2004), ENGINE_CLASS(RENDER)), From 75f65f1a4c06da1d87f28570a9d4cdad28f13360 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 14 May 2026 18:44:46 -0300 Subject: [PATCH 15/31] drm/xe: Define and use MCR version of COMMON_SLICE_CHICKEN4 The register COMMON_SLICE_CHICKEN4 is a MCR register on both Xe2 and Xe3. Let's make sure to define a MCR version of it and use it for the relevant IP versions. Use XEHP_ as prefix for the register name, since it is MCR as of Xe_HP. v2: - Also change for one entry in lrc_tunnings, which was caught by manual testing and add corresponging Fixes tag in commit message. (Gustavo) Fixes: 8d6f16f1f082 ("drm/xe: Extend Wa_22021007897 to Xe3 platforms") Fixes: e5c13e2c505b ("drm/xe/xe2hpg: Add Wa_22021007897") Fixes: 8ccf5f6b2295 ("drm/xe/tuning: Apply windower hardware filtering setting on Xe3 and Xe3p") Bspec: 66534, 71185, 74417 Reviewed-by: Matt Roper Link: https://patch.msgid.link/20260514-rtp-mcr-check-v3-3-30dd47855fee@intel.com Signed-off-by: Gustavo Sousa --- drivers/gpu/drm/xe/regs/xe_gt_regs.h | 1 + drivers/gpu/drm/xe/xe_tuning.c | 2 +- drivers/gpu/drm/xe/xe_wa.c | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h index b21c66a1b777..08251c7a1a4b 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -179,6 +179,7 @@ #define XEHPG_SC_INSTDONE_EXTRA2 XE_REG_MCR(0x7108) #define COMMON_SLICE_CHICKEN4 XE_REG(0x7300, XE_REG_OPTION_MASKED) +#define XEHP_COMMON_SLICE_CHICKEN4 XE_REG_MCR(0x7300, XE_REG_OPTION_MASKED) #define SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE REG_BIT(12) #define DISABLE_TDC_LOAD_BALANCING_CALC REG_BIT(6) #define HW_FILTERING REG_BIT(5) diff --git a/drivers/gpu/drm/xe/xe_tuning.c b/drivers/gpu/drm/xe/xe_tuning.c index ce39b77a084a..9a1b3862e192 100644 --- a/drivers/gpu/drm/xe/xe_tuning.c +++ b/drivers/gpu/drm/xe/xe_tuning.c @@ -134,7 +134,7 @@ static const struct xe_rtp_entry_sr engine_tunings[] = { static const struct xe_rtp_entry_sr lrc_tunings[] = { { XE_RTP_NAME("Tuning: Windower HW Filtering"), XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3599), ENGINE_CLASS(RENDER)), - XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN4, HW_FILTERING)) + XE_RTP_ACTIONS(SET(XEHP_COMMON_SLICE_CHICKEN4, HW_FILTERING)) }, /* DG2 */ diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c index d6f94486673e..cb811f8a7781 100644 --- a/drivers/gpu/drm/xe/xe_wa.c +++ b/drivers/gpu/drm/xe/xe_wa.c @@ -767,7 +767,7 @@ static const struct xe_rtp_entry_sr lrc_was[] = { }, { XE_RTP_NAME("22021007897"), XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 2002), ENGINE_CLASS(RENDER)), - XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN4, SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE)) + XE_RTP_ACTIONS(SET(XEHP_COMMON_SLICE_CHICKEN4, SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE)) }, /* Xe3_LPG */ @@ -783,7 +783,7 @@ static const struct xe_rtp_entry_sr lrc_was[] = { }, { XE_RTP_NAME("22021007897"), XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3005), ENGINE_CLASS(RENDER)), - XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN4, SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE)) + XE_RTP_ACTIONS(SET(XEHP_COMMON_SLICE_CHICKEN4, SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE)) }, { XE_RTP_NAME("14024681466"), XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3005), ENGINE_CLASS(RENDER)), From 94069111b862018749423e6fdc811b832d73285a Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 14 May 2026 18:44:47 -0300 Subject: [PATCH 16/31] drm/xe: Extract xe_hw_engine_setup_reg_lrc() The steps for processing RTP rules that build up an engine's reg_lrc arguably belongs to xe_hw_engine.c and should be encapsulated into a function in that unit. Move that logic to a new function called xe_hw_engine_setup_reg_lrc(). Reviewed-by: Matt Roper Link: https://patch.msgid.link/20260514-rtp-mcr-check-v3-4-30dd47855fee@intel.com Signed-off-by: Gustavo Sousa --- drivers/gpu/drm/xe/xe_gt.c | 5 +---- drivers/gpu/drm/xe/xe_hw_engine.c | 15 +++++++++++++-- drivers/gpu/drm/xe/xe_hw_engine.h | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index cdc678d1ae1f..c4b25daad542 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -393,10 +393,7 @@ int xe_gt_record_default_lrcs(struct xe_gt *gt) if (gt->default_lrc[hwe->class]) continue; - xe_reg_sr_init(&hwe->reg_lrc, hwe->name, xe); - xe_wa_process_lrc(hwe); - xe_hw_engine_setup_default_lrc_state(hwe); - xe_tuning_process_lrc(hwe); + xe_hw_engine_setup_reg_lrc(hwe); default_lrc = drmm_kzalloc(&xe->drm, xe_gt_lrc_size(gt, hwe->class), diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index 0f0e08bcc182..05f0932dbb94 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -337,8 +337,8 @@ static bool xe_rtp_cfeg_wmtp_disabled(const struct xe_device *xe, return xe_mmio_read32(&hwe->gt->mmio, XEHP_FUSE4) & CFEG_WMTP_DISABLE; } -void -xe_hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe) +static void +hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe) { struct xe_gt *gt = hwe->gt; const u8 mocs_write_idx = gt->mocs.uc_index; @@ -375,6 +375,17 @@ xe_hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe) &hwe->reg_lrc, true); } +void xe_hw_engine_setup_reg_lrc(struct xe_hw_engine *hwe) +{ + struct xe_gt *gt = hwe->gt; + struct xe_device *xe = gt_to_xe(gt); + + xe_reg_sr_init(&hwe->reg_lrc, hwe->name, xe); + xe_wa_process_lrc(hwe); + hw_engine_setup_default_lrc_state(hwe); + xe_tuning_process_lrc(hwe); +} + static void hw_engine_setup_default_state(struct xe_hw_engine *hwe) { diff --git a/drivers/gpu/drm/xe/xe_hw_engine.h b/drivers/gpu/drm/xe/xe_hw_engine.h index ee9218773b51..c3ee37f8cfc0 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.h +++ b/drivers/gpu/drm/xe/xe_hw_engine.h @@ -59,7 +59,7 @@ struct xe_hw_engine_snapshot * xe_hw_engine_snapshot_capture(struct xe_hw_engine *hwe, struct xe_exec_queue *q); void xe_hw_engine_snapshot_free(struct xe_hw_engine_snapshot *snapshot); void xe_hw_engine_print(struct xe_hw_engine *hwe, struct drm_printer *p); -void xe_hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe); +void xe_hw_engine_setup_reg_lrc(struct xe_hw_engine *hwe); bool xe_hw_engine_is_reserved(struct xe_hw_engine *hwe); From 5f7266c3f3ff72c3dd482db5c590a61181dccfb3 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 14 May 2026 18:44:48 -0300 Subject: [PATCH 17/31] drm/xe/kunit: Use KUNIT_EXPECT_EQ() in xe_wa_gt() Use KUNIT_EXPECT_EQ() in xe_wa_gt() as reg_sr errors in one GT do not impact the next GT in the test. Reviewed-by: Michal Wajdeczko Reviewed-by: Matt Roper Link: https://patch.msgid.link/20260514-rtp-mcr-check-v3-5-30dd47855fee@intel.com Signed-off-by: Gustavo Sousa --- drivers/gpu/drm/xe/tests/xe_wa_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/tests/xe_wa_test.c b/drivers/gpu/drm/xe/tests/xe_wa_test.c index 49d191043dfa..2bf6fab015cd 100644 --- a/drivers/gpu/drm/xe/tests/xe_wa_test.c +++ b/drivers/gpu/drm/xe/tests/xe_wa_test.c @@ -55,7 +55,7 @@ static void xe_wa_gt(struct kunit *test) xe_wa_process_gt(gt); xe_tuning_process_gt(gt); - KUNIT_ASSERT_EQ(test, gt->reg_sr.errors, 0); + KUNIT_EXPECT_EQ(test, gt->reg_sr.errors, 0); } } From cdf8489533f4dd9639fd0c266dd2ec8f7a543e34 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 14 May 2026 18:44:49 -0300 Subject: [PATCH 18/31] drm/xe/mcr: Extract reg_in_steering_type_ranges() The logic to check if a register falls within one of the ranges for a steering type is already duplicated in xe_gt_mcr_get_nonterminated_steering(). We will also want to use that same logic in another upcoming function. Let's factor out that logic and put it into a function named reg_in_steering_type_ranges(). Reviewed-by: Matt Roper Link: https://patch.msgid.link/20260514-rtp-mcr-check-v3-6-30dd47855fee@intel.com Signed-off-by: Gustavo Sousa --- drivers/gpu/drm/xe/xe_gt_mcr.c | 41 +++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.c b/drivers/gpu/drm/xe/xe_gt_mcr.c index df281688c617..2b2a4d9c3749 100644 --- a/drivers/gpu/drm/xe/xe_gt_mcr.c +++ b/drivers/gpu/drm/xe/xe_gt_mcr.c @@ -600,6 +600,20 @@ void xe_gt_mcr_set_implicit_defaults(struct xe_gt *gt) } } +static bool reg_in_steering_type_ranges(struct xe_gt *gt, + struct xe_reg reg, + int type) +{ + if (!gt->steering[type].ranges) + return false; + + for (int i = 0; gt->steering[type].ranges[i].end > 0; i++) + if (xe_mmio_in_range(>->mmio, >->steering[type].ranges[i], reg)) + return true; + + return false; +} + /* * xe_gt_mcr_get_nonterminated_steering - find group/instance values that * will steer a register to a non-terminated instance @@ -621,30 +635,21 @@ bool xe_gt_mcr_get_nonterminated_steering(struct xe_gt *gt, u8 *group, u8 *instance) { const struct xe_reg reg = to_xe_reg(reg_mcr); - const struct xe_mmio_range *implicit_ranges; for (int type = 0; type < IMPLICIT_STEERING; type++) { - if (!gt->steering[type].ranges) - continue; + if (reg_in_steering_type_ranges(gt, reg, type)) { + drm_WARN(>_to_xe(gt)->drm, !gt->steering[type].initialized, + "Uninitialized usage of MCR register %s/%#x\n", + xe_steering_types[type].name, reg.addr); - for (int i = 0; gt->steering[type].ranges[i].end > 0; i++) { - if (xe_mmio_in_range(>->mmio, >->steering[type].ranges[i], reg)) { - drm_WARN(>_to_xe(gt)->drm, !gt->steering[type].initialized, - "Uninitialized usage of MCR register %s/%#x\n", - xe_steering_types[type].name, reg.addr); - - *group = gt->steering[type].group_target; - *instance = gt->steering[type].instance_target; - return true; - } + *group = gt->steering[type].group_target; + *instance = gt->steering[type].instance_target; + return true; } } - implicit_ranges = gt->steering[IMPLICIT_STEERING].ranges; - if (implicit_ranges) - for (int i = 0; implicit_ranges[i].end > 0; i++) - if (xe_mmio_in_range(>->mmio, &implicit_ranges[i], reg)) - return false; + if (reg_in_steering_type_ranges(gt, reg, IMPLICIT_STEERING)) + return false; /* * Not found in a steering table and not a register with implicit From 058da4a2b164e477b02ca0562f01a9eb9e621cdd Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 14 May 2026 18:44:50 -0300 Subject: [PATCH 19/31] drm/xe/reg_sr: Do sanity check for MCR vs non-MCR The type struct xe_reg_mcr exists to ensure that the correct API is used when handling MCR registers. However, for the register save/restore functionality, the RTP processing always cast the register to a struct xe_reg and then apply_one_mmio() selects the MMIO API based on the "mcr" field of the register instance. This allows the developer to commit mistakes like passing a MCR register for an RTP action for a GT where the respective register is not MCR; and vice-versa. To capture such scenarios, do a sanity check in xe_reg_sr_add() that, upon an inconsistency: - "fixes" the register type by favoring what we have in our MCR range tables instead of what the developer selected for the save/restore entry; - raises a notice-level message to inform about the inconsistency. Note: As a collateral of this change, we need to include MCR initialization in xe_wa_test.c, otherwise a bunch of test cases end up failing because xe_gt_mcr_check_reg() will always return false, meaning that will incorrectly say that a MCR register is not MCR. v2: - Downgrade messages to notice level so as not to block CI execution when inconsistencies are found. (Matt) - Add missing EXPORT_SYMBOL_IF_KUNIT() calls. (Gustavo) Reviewed-by: Matt Roper Link: https://patch.msgid.link/20260514-rtp-mcr-check-v3-7-30dd47855fee@intel.com Signed-off-by: Gustavo Sousa --- drivers/gpu/drm/xe/tests/xe_rtp_test.c | 71 +++++++++++++++++++++++--- drivers/gpu/drm/xe/tests/xe_wa_test.c | 12 ++++- drivers/gpu/drm/xe/xe_gt.c | 3 ++ drivers/gpu/drm/xe/xe_gt_mcr.c | 24 +++++++++ drivers/gpu/drm/xe/xe_gt_mcr.h | 1 + drivers/gpu/drm/xe/xe_reg_sr.c | 36 +++++++++++++ 6 files changed, 139 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/xe/tests/xe_rtp_test.c b/drivers/gpu/drm/xe/tests/xe_rtp_test.c index e5a0f985a700..5d78f2283df9 100644 --- a/drivers/gpu/drm/xe/tests/xe_rtp_test.c +++ b/drivers/gpu/drm/xe/tests/xe_rtp_test.c @@ -9,24 +9,30 @@ #include #include +#include #include #include "regs/xe_gt_regs.h" #include "regs/xe_reg_defs.h" #include "xe_device.h" #include "xe_device_types.h" +#include "xe_gt_mcr.h" #include "xe_kunit_helpers.h" #include "xe_pci_test.h" #include "xe_reg_sr.h" #include "xe_rtp.h" -#define REGULAR_REG1 XE_REG(1) -#define REGULAR_REG2 XE_REG(2) -#define REGULAR_REG3 XE_REG(3) -#define MCR_REG1 XE_REG_MCR(1) -#define MCR_REG2 XE_REG_MCR(2) -#define MCR_REG3 XE_REG_MCR(3) -#define MASKED_REG1 XE_REG(1, XE_REG_OPTION_MASKED) +#define REGULAR_REG1 XE_REG(1) +#define REGULAR_REG2 XE_REG(2) +#define REGULAR_REG3 XE_REG(3) +#define REGULAR_REG4 XE_REG(4) +#define BAD_REGULAR_REG5 XE_REG(5) +#define MCR_REG1 XE_REG_MCR(1) +#define MCR_REG2 XE_REG_MCR(2) +#define MCR_REG3 XE_REG_MCR(3) +#define BAD_MCR_REG4 XE_REG_MCR(4) +#define MCR_REG5 XE_REG_MCR(5) +#define MASKED_REG1 XE_REG(1, XE_REG_OPTION_MASKED) #undef XE_REG_MCR #define XE_REG_MCR(...) XE_REG(__VA_ARGS__, .mcr = 1) @@ -48,6 +54,23 @@ struct rtp_test_case { const struct xe_rtp_entry *entries; }; +static bool fake_xe_gt_mcr_check_reg(struct xe_gt *gt, struct xe_reg reg) +{ + /* + * All supported platforms in this imaginary setup will always have REG4 + * as a non-MCR register and REG5 as MCR, meaning that BAD_MCR_REG4 and + * BAD_REGULAR_REG5 represent programming errors to be captured by our + * tests. + */ + if (reg.raw == BAD_REGULAR_REG5.raw) + return true; + + if (reg.raw == BAD_MCR_REG4.raw) + return false; + + return reg.mcr; +} + static bool match_yes(const struct xe_device *xe, const struct xe_gt *gt, const struct xe_hw_engine *hwe) { @@ -304,6 +327,38 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = { {} }, }, + { + .name = "bad-mcr-reg-forced-to-regular", + .expected_reg = REGULAR_REG4, + .expected_set_bits = REG_BIT(0), + .expected_clr_bits = REG_BIT(0), + .expected_active = BIT(0), + .expected_count_sr_entries = 1, + .expected_sr_errors = 1, + .entries = (const struct xe_rtp_entry_sr[]) { + { XE_RTP_NAME("bad-mcr-regular-reg"), + XE_RTP_RULES(FUNC(match_yes)), + XE_RTP_ACTIONS(SET(BAD_MCR_REG4, REG_BIT(0))) + }, + {} + }, + }, + { + .name = "bad-regular-reg-forced-to-mcr", + .expected_reg = MCR_REG5, + .expected_set_bits = REG_BIT(0), + .expected_clr_bits = REG_BIT(0), + .expected_active = BIT(0), + .expected_count_sr_entries = 1, + .expected_sr_errors = 1, + .entries = (const struct xe_rtp_entry_sr[]) { + { XE_RTP_NAME("bad-regular-reg"), + XE_RTP_RULES(FUNC(match_yes)), + XE_RTP_ACTIONS(SET(BAD_REGULAR_REG5, REG_BIT(0))) + }, + {} + }, + }, }; static void xe_rtp_process_to_sr_tests(struct kunit *test) @@ -523,6 +578,8 @@ static int xe_rtp_test_init(struct kunit *test) xe->drm.dev = dev; test->priv = xe; + kunit_activate_static_stub(test, xe_gt_mcr_check_reg, fake_xe_gt_mcr_check_reg); + return 0; } diff --git a/drivers/gpu/drm/xe/tests/xe_wa_test.c b/drivers/gpu/drm/xe/tests/xe_wa_test.c index 2bf6fab015cd..ff0e2502b39f 100644 --- a/drivers/gpu/drm/xe/tests/xe_wa_test.c +++ b/drivers/gpu/drm/xe/tests/xe_wa_test.c @@ -9,6 +9,8 @@ #include #include "xe_device.h" +#include "xe_gt.h" +#include "xe_gt_mcr.h" #include "xe_kunit_helpers.h" #include "xe_pci_test.h" #include "xe_reg_sr.h" @@ -19,8 +21,10 @@ static int xe_wa_test_init(struct kunit *test) { const struct xe_pci_fake_data *param = test->param_value; struct xe_pci_fake_data data = *param; - struct xe_device *xe; struct device *dev; + struct xe_device *xe; + struct xe_gt *gt; + int id; int ret; dev = drm_kunit_helper_alloc_device(test); @@ -33,6 +37,12 @@ static int xe_wa_test_init(struct kunit *test) ret = xe_pci_fake_device_init(xe); KUNIT_ASSERT_EQ(test, ret, 0); + /* Needed for sanitize_mcr(). */ + for_each_gt(gt, xe, id) { + xe_gt_mcr_init_early(gt); + xe_gt_mmio_init(gt); + } + if (!param->graphics_verx100) xe->info.step = param->step; diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index c4b25daad542..783eb6d631b5 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -7,6 +7,8 @@ #include +#include + #include #include @@ -785,6 +787,7 @@ void xe_gt_mmio_init(struct xe_gt *gt) if (IS_SRIOV_VF(xe)) gt->mmio.sriov_vf_gt = gt; } +EXPORT_SYMBOL_IF_KUNIT(xe_gt_mmio_init); void xe_gt_record_user_engines(struct xe_gt *gt) { diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.c b/drivers/gpu/drm/xe/xe_gt_mcr.c index 2b2a4d9c3749..04f0098070a4 100644 --- a/drivers/gpu/drm/xe/xe_gt_mcr.c +++ b/drivers/gpu/drm/xe/xe_gt_mcr.c @@ -3,6 +3,9 @@ * Copyright © 2022 Intel Corporation */ +#include +#include + #include "xe_gt_mcr.h" #include "regs/xe_gt_regs.h" @@ -553,6 +556,7 @@ void xe_gt_mcr_init_early(struct xe_gt *gt) /* Mark instance 0 as initialized, we need this early for VRAM and CCS probe. */ gt->steering[INSTANCE0].initialized = true; } +EXPORT_SYMBOL_IF_KUNIT(xe_gt_mcr_init_early); /** * xe_gt_mcr_init - Normal initialization of the MCR support @@ -614,6 +618,26 @@ static bool reg_in_steering_type_ranges(struct xe_gt *gt, return false; } +/* + * xe_gt_mcr_check_reg - check if a register is recognized by this GT as MCR + * @gt: GT structure + * @reg: The register to check + * + * Returns true if the register offset falls within one of the MMIO ranges + * classified as MCR for the GT. + */ +bool xe_gt_mcr_check_reg(struct xe_gt *gt, struct xe_reg reg) +{ + KUNIT_STATIC_STUB_REDIRECT(xe_gt_mcr_check_reg, gt, reg); + + for (int type = 0; type <= IMPLICIT_STEERING; type++) + if (reg_in_steering_type_ranges(gt, reg, type)) + return true; + + return false; +} +EXPORT_SYMBOL_IF_KUNIT(xe_gt_mcr_check_reg); + /* * xe_gt_mcr_get_nonterminated_steering - find group/instance values that * will steer a register to a non-terminated instance diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.h b/drivers/gpu/drm/xe/xe_gt_mcr.h index 2be9419b8acc..75374662f10d 100644 --- a/drivers/gpu/drm/xe/xe_gt_mcr.h +++ b/drivers/gpu/drm/xe/xe_gt_mcr.h @@ -26,6 +26,7 @@ void xe_gt_mcr_unicast_write(struct xe_gt *gt, struct xe_reg_mcr mcr_reg, void xe_gt_mcr_multicast_write(struct xe_gt *gt, struct xe_reg_mcr mcr_reg, u32 value); +bool xe_gt_mcr_check_reg(struct xe_gt *gt, struct xe_reg reg); bool xe_gt_mcr_get_nonterminated_steering(struct xe_gt *gt, struct xe_reg_mcr reg_mcr, u8 *group, u8 *instance); diff --git a/drivers/gpu/drm/xe/xe_reg_sr.c b/drivers/gpu/drm/xe/xe_reg_sr.c index 2df0277efb2f..e328f5072557 100644 --- a/drivers/gpu/drm/xe/xe_reg_sr.c +++ b/drivers/gpu/drm/xe/xe_reg_sr.c @@ -70,14 +70,49 @@ static void reg_sr_inc_error(struct xe_reg_sr *sr) #endif } +static struct xe_reg sanitize_mcr(struct xe_reg_sr *sr, + const struct xe_reg_sr_entry *e, + struct xe_gt *gt) +{ + struct xe_reg reg = e->reg; + bool is_mcr; + + /* + * We need the gt structure to check MCR ranges. + */ + if (!gt) + return reg; + + is_mcr = xe_gt_mcr_check_reg(gt, reg); + + if (is_mcr && !reg.mcr) { + reg.mcr = 1; + xe_gt_notice(gt, "xe_reg_sr_entry using non-MCR register for address 0x%x, forcing MCR\n", + reg.addr); + reg_sr_inc_error(sr); + } + + if (!is_mcr && reg.mcr) { + reg.mcr = 0; + xe_gt_notice(gt, "xe_reg_sr_entry using MCR register for address 0x%x, forcing non-MCR\n", + reg.addr); + reg_sr_inc_error(sr); + } + + return reg; +} + int xe_reg_sr_add(struct xe_reg_sr *sr, const struct xe_reg_sr_entry *e, struct xe_gt *gt) { unsigned long idx = e->reg.addr; struct xe_reg_sr_entry *pentry = xa_load(&sr->xa, idx); + struct xe_reg reg; int ret; + reg = sanitize_mcr(sr, e, gt); + if (pentry) { if (!compatible_entries(pentry, e)) { ret = -EINVAL; @@ -98,6 +133,7 @@ int xe_reg_sr_add(struct xe_reg_sr *sr, } *pentry = *e; + pentry->reg = reg; ret = xa_err(xa_store(&sr->xa, idx, pentry, GFP_KERNEL)); if (ret) goto fail_free; From d2d23c12789cf69eddc35b8d38cd8eaabd0168f1 Mon Sep 17 00:00:00 2001 From: Niranjana Vishwanathapura Date: Mon, 18 May 2026 12:16:40 -0700 Subject: [PATCH 20/31] drm/xe/multi_queue: Fix secondary queue error case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If xe_lrc_create() fails, the secondary queue added to the multi-queue group list is not removed before freeing the queue. Fix error path handling for secondary queues by removing it from the multi-queue group list at the right place. Reported-by: Sebastian Österlund Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/work_items/7979 Fixes: d716a5088c88 ("drm/xe/multi_queue: Handle tearing down of a multi queue") Cc: stable@vger.kernel.org # v7.0+ Signed-off-by: Niranjana Vishwanathapura Reviewed-by: Matthew Auld Link: https://patch.msgid.link/20260518191639.320890-2-niranjana.vishwanathapura@intel.com --- drivers/gpu/drm/xe/xe_guc_submit.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 4171eff4e8ad..afd8cc7bd231 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -1665,6 +1665,14 @@ static void guc_exec_queue_fini(struct xe_exec_queue *q) struct xe_guc_exec_queue *ge = q->guc; struct xe_guc *guc = exec_queue_to_guc(q); + if (xe_exec_queue_is_multi_queue_secondary(q)) { + struct xe_exec_queue_group *group = q->multi_queue.group; + + mutex_lock(&group->list_lock); + list_del(&q->multi_queue.link); + mutex_unlock(&group->list_lock); + } + release_guc_id(guc, q); xe_sched_entity_fini(&ge->entity); xe_sched_fini(&ge->sched); @@ -1686,14 +1694,6 @@ static void __guc_exec_queue_destroy_async(struct work_struct *w) guard(xe_pm_runtime)(guc_to_xe(guc)); trace_xe_exec_queue_destroy(q); - if (xe_exec_queue_is_multi_queue_secondary(q)) { - struct xe_exec_queue_group *group = q->multi_queue.group; - - mutex_lock(&group->list_lock); - list_del(&q->multi_queue.link); - mutex_unlock(&group->list_lock); - } - /* Confirm no work left behind accessing device structures */ cancel_delayed_work_sync(&ge->sched.base.work_tdr); From ae3c9b7472372228e83bf792874e6e625f7d043f Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Wed, 13 May 2026 16:07:14 -0300 Subject: [PATCH 21/31] drm/xe/guc: Use xe_device_is_l2_flush_optimized() We encapsulate the logic to check if the platform has L2 flush optimization feature in xe_device_is_l2_flush_optimized(), but guc_ctl_feature_flags() is using an open-coded version of that same type of check. Fix that by replacing the open-coded check with xe_device_is_l2_flush_optimized(). Reviewed-by: Himanshu Girotra Reviewed-by: Tejas Upadhyay Link: https://patch.msgid.link/20260513-guc-l2-flush-opt-use-xe_device_is_l2_flush_optimized-v1-1-36fa866d6ed8@intel.com Signed-off-by: Gustavo Sousa --- drivers/gpu/drm/xe/xe_guc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c index e468b638271b..4023700ff2a9 100644 --- a/drivers/gpu/drm/xe/xe_guc.c +++ b/drivers/gpu/drm/xe/xe_guc.c @@ -98,7 +98,7 @@ static u32 guc_ctl_feature_flags(struct xe_guc *guc) if (xe_guc_using_main_gamctrl_queues(guc)) flags |= GUC_CTL_MAIN_GAMCTRL_QUEUES; - if (GRAPHICS_VER(xe) >= 35 && !IS_DGFX(xe) && xe_gt_is_media_type(guc_to_gt(guc))) + if (xe_device_is_l2_flush_optimized(xe) && xe_gt_is_media_type(guc_to_gt(guc))) flags |= GUC_CTL_ENABLE_L2FLUSH_OPT; return flags; From 31f855a47c8beb8fee7d74374c9d21ba9ab06700 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 18 May 2026 21:25:39 +0200 Subject: [PATCH 22/31] drm/xe: Add IRQ page to HW engine definition For each HW engine definition, we already make changes to the IRQ offset, as required when using MSI-X, but we leave actual MEMIRQ page selection to the MEMIRQ handler, repeated on every interrupt. As a preparation step to simplify the MEMIRQ handler, store the MEMIRQ page number as part of the HW engine definition. Suggested-by: Ilia Levi Signed-off-by: Michal Wajdeczko Cc: Ilia Levi Reviewed-by: Ilia Levi Link: https://patch.msgid.link/20260518192547.600-2-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_hw_engine.c | 11 ++++++++--- drivers/gpu/drm/xe/xe_hw_engine_types.h | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index 05f0932dbb94..8c66ff6f3d3c 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -514,9 +514,14 @@ static void hw_engine_init_early(struct xe_gt *gt, struct xe_hw_engine *hwe, hwe->class = info->class; hwe->instance = info->instance; hwe->mmio_base = info->mmio_base; - hwe->irq_offset = xe_device_has_msix(gt_to_xe(gt)) ? - get_msix_irq_offset(gt, info->class) : - info->irq_offset; + if (xe_device_has_msix(gt_to_xe(gt))) { + hwe->irq_offset = get_msix_irq_offset(gt, info->class); + hwe->irq_page = info->instance; + + } else { + hwe->irq_offset = info->irq_offset; + hwe->irq_page = 0; + } hwe->domain = info->domain; hwe->name = info->name; hwe->fence_irq = >->fence_irq[info->class]; diff --git a/drivers/gpu/drm/xe/xe_hw_engine_types.h b/drivers/gpu/drm/xe/xe_hw_engine_types.h index 0f87128c6529..2cf898e682f5 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine_types.h +++ b/drivers/gpu/drm/xe/xe_hw_engine_types.h @@ -118,6 +118,8 @@ struct xe_hw_engine { u16 logical_instance; /** @irq_offset: IRQ offset of this hw engine */ u16 irq_offset; + /** @irq_page: MEMIRQ page used by this HW engine */ + u16 irq_page; /** @mmio_base: MMIO base address of this hw engine*/ u32 mmio_base; /** From e89b59652ccb0987c8f4647b4e7062516880756d Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 18 May 2026 21:25:40 +0200 Subject: [PATCH 23/31] drm/xe/memirq: Make page layout macros private There is no need to expose the macros describing memory-based interrupts page layouts in the .h file as we only use them in the private code. Move them to the .c file near the kernel-doc. Signed-off-by: Michal Wajdeczko Reviewed-by: Ilia Levi Link: https://patch.msgid.link/20260518192547.600-3-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_memirq.c | 7 +++++++ drivers/gpu/drm/xe/xe_memirq_types.h | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_memirq.c b/drivers/gpu/drm/xe/xe_memirq.c index 3848ff81c1f9..118c2285e893 100644 --- a/drivers/gpu/drm/xe/xe_memirq.c +++ b/drivers/gpu/drm/xe/xe_memirq.c @@ -152,6 +152,13 @@ static const char *guc_name(struct xe_guc *guc) * */ +/* ISR */ +#define XE_MEMIRQ_STATUS_OFFSET(inst) ((inst) * SZ_4K + 0x0) +/* IIR */ +#define XE_MEMIRQ_SOURCE_OFFSET(inst) ((inst) * SZ_4K + 0x400) +/* IMR */ +#define XE_MEMIRQ_ENABLE_OFFSET 0x440 + static inline bool hw_reports_to_instance_zero(struct xe_memirq *memirq) { /* diff --git a/drivers/gpu/drm/xe/xe_memirq_types.h b/drivers/gpu/drm/xe/xe_memirq_types.h index 9d0f6c1cdb9d..02ac938cadb4 100644 --- a/drivers/gpu/drm/xe/xe_memirq_types.h +++ b/drivers/gpu/drm/xe/xe_memirq_types.h @@ -10,13 +10,6 @@ struct xe_bo; -/* ISR */ -#define XE_MEMIRQ_STATUS_OFFSET(inst) ((inst) * SZ_4K + 0x0) -/* IIR */ -#define XE_MEMIRQ_SOURCE_OFFSET(inst) ((inst) * SZ_4K + 0x400) -/* IMR */ -#define XE_MEMIRQ_ENABLE_OFFSET 0x440 - /** * struct xe_memirq - Data used by the `Memory Based Interrupts`_. * From 0be1268ef0a0043b594b7cf95e9ed53f5e0a7d12 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 18 May 2026 21:25:41 +0200 Subject: [PATCH 24/31] drm/xe/memirq: Update GuC initialization and IRQ handler Introduce and use simple macro to calculate exact location of the status vector to avoid inline calculation. Fix type for the GuC source and status MEMIRQ addresses. Signed-off-by: Michal Wajdeczko Reviewed-by: Ilia Levi Link: https://patch.msgid.link/20260518192547.600-4-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_memirq.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_memirq.c b/drivers/gpu/drm/xe/xe_memirq.c index 118c2285e893..6d27102b8011 100644 --- a/drivers/gpu/drm/xe/xe_memirq.c +++ b/drivers/gpu/drm/xe/xe_memirq.c @@ -159,6 +159,9 @@ static const char *guc_name(struct xe_guc *guc) /* IMR */ #define XE_MEMIRQ_ENABLE_OFFSET 0x440 +/* engine ISR vector offset */ +#define XE_MEMIRQ_VECTOR_OFFSET(page, source) (XE_MEMIRQ_STATUS_OFFSET(page) + (source) * SZ_16) + static inline bool hw_reports_to_instance_zero(struct xe_memirq *memirq) { /* @@ -346,13 +349,14 @@ int xe_memirq_init_guc(struct xe_memirq *memirq, struct xe_guc *guc) { bool is_media = xe_gt_is_media_type(guc_to_gt(guc)); u32 offset = is_media ? ilog2(INTR_MGUC) : ilog2(INTR_GUC); - u32 source, status; + u64 source, status; int err; memirq_assert(memirq, xe_device_uses_memirq(memirq_to_xe(memirq))); - source = __memirq_source_page(memirq, 0) + offset; - status = __memirq_status_page(memirq, 0) + offset * SZ_16; + /* GuC expects exact locations, it doesn't add anything on its own */ + source = xe_bo_ggtt_addr(memirq->bo) + XE_MEMIRQ_SOURCE_OFFSET(0) + offset; + status = xe_bo_ggtt_addr(memirq->bo) + XE_MEMIRQ_VECTOR_OFFSET(0, offset); err = xe_guc_self_cfg64(guc, GUC_KLV_SELF_CFG_MEMIRQ_SOURCE_ADDR_KEY, source); @@ -520,7 +524,8 @@ bool xe_memirq_guc_sw_int_0_irq_pending(struct xe_memirq *memirq, struct xe_guc { struct xe_gt *gt = guc_to_gt(guc); u32 offset = xe_gt_is_media_type(gt) ? ilog2(INTR_MGUC) : ilog2(INTR_GUC); - struct iosys_map map = IOSYS_MAP_INIT_OFFSET(&memirq->status, offset * SZ_16); + struct iosys_map map = IOSYS_MAP_INIT_OFFSET(&memirq->bo->vmap, + XE_MEMIRQ_VECTOR_OFFSET(0, offset)); return memirq_received_noclear(memirq, &map, ilog2(GUC_INTR_SW_INT_0), guc_name(guc)); @@ -560,7 +565,8 @@ void xe_memirq_handler(struct xe_memirq *memirq) /* GuC and media GuC (if present) must be checked separately */ if (memirq_received(memirq, &memirq->source, ilog2(INTR_GUC), "SRC")) { - map = IOSYS_MAP_INIT_OFFSET(&memirq->status, ilog2(INTR_GUC) * SZ_16); + map = IOSYS_MAP_INIT_OFFSET(&memirq->bo->vmap, + XE_MEMIRQ_VECTOR_OFFSET(0, ilog2(INTR_GUC))); memirq_dispatch_guc(memirq, &map, &tile->primary_gt->uc.guc); } @@ -568,7 +574,8 @@ void xe_memirq_handler(struct xe_memirq *memirq) return; if (memirq_received(memirq, &memirq->source, ilog2(INTR_MGUC), "SRC")) { - map = IOSYS_MAP_INIT_OFFSET(&memirq->status, ilog2(INTR_MGUC) * SZ_16); + map = IOSYS_MAP_INIT_OFFSET(&memirq->bo->vmap, + XE_MEMIRQ_VECTOR_OFFSET(0, ilog2(INTR_MGUC))); memirq_dispatch_guc(memirq, &map, &tile->media_gt->uc.guc); } } From 37f1856e124b4b18e48ad59995c6dd70cfcb782b Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 18 May 2026 21:25:42 +0200 Subject: [PATCH 25/31] drm/xe/memirq: Use IRQ page from HW engine definition We can now drop repeated calculations of the actual IRQ page used by the engines from our memory based interrupt handler and other functions. Signed-off-by: Michal Wajdeczko Reviewed-by: Ilia Levi Link: https://patch.msgid.link/20260518192547.600-5-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_memirq.c | 38 +++++++++------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_memirq.c b/drivers/gpu/drm/xe/xe_memirq.c index 6d27102b8011..285fffea62d8 100644 --- a/drivers/gpu/drm/xe/xe_memirq.c +++ b/drivers/gpu/drm/xe/xe_memirq.c @@ -263,15 +263,6 @@ int xe_memirq_init(struct xe_memirq *memirq) return 0; } -static u32 __memirq_source_page(struct xe_memirq *memirq, u16 instance) -{ - memirq_assert(memirq, instance <= XE_HW_ENGINE_MAX_INSTANCE); - memirq_assert(memirq, memirq->bo); - - instance = hw_reports_to_instance_zero(memirq) ? instance : 0; - return xe_bo_ggtt_addr(memirq->bo) + XE_MEMIRQ_SOURCE_OFFSET(instance); -} - /** * xe_memirq_source_ptr - Get GGTT's offset of the `Interrupt Source Report Page`_. * @memirq: the &xe_memirq to query @@ -286,16 +277,7 @@ u32 xe_memirq_source_ptr(struct xe_memirq *memirq, struct xe_hw_engine *hwe) { memirq_assert(memirq, xe_device_uses_memirq(memirq_to_xe(memirq))); - return __memirq_source_page(memirq, hwe->instance); -} - -static u32 __memirq_status_page(struct xe_memirq *memirq, u16 instance) -{ - memirq_assert(memirq, instance <= XE_HW_ENGINE_MAX_INSTANCE); - memirq_assert(memirq, memirq->bo); - - instance = hw_reports_to_instance_zero(memirq) ? instance : 0; - return xe_bo_ggtt_addr(memirq->bo) + XE_MEMIRQ_STATUS_OFFSET(instance); + return xe_bo_ggtt_addr(memirq->bo) + XE_MEMIRQ_SOURCE_OFFSET(hwe->irq_page); } /** @@ -312,7 +294,7 @@ u32 xe_memirq_status_ptr(struct xe_memirq *memirq, struct xe_hw_engine *hwe) { memirq_assert(memirq, xe_device_uses_memirq(memirq_to_xe(memirq))); - return __memirq_status_page(memirq, hwe->instance); + return xe_bo_ggtt_addr(memirq->bo) + XE_MEMIRQ_STATUS_OFFSET(hwe->irq_page); } /** @@ -500,16 +482,16 @@ static void memirq_dispatch_guc(struct xe_memirq *memirq, struct iosys_map *stat */ void xe_memirq_hwe_handler(struct xe_memirq *memirq, struct xe_hw_engine *hwe) { - u16 offset = hwe->irq_offset; - u16 instance = hw_reports_to_instance_zero(memirq) ? hwe->instance : 0; - struct iosys_map src_offset = IOSYS_MAP_INIT_OFFSET(&memirq->bo->vmap, - XE_MEMIRQ_SOURCE_OFFSET(instance)); + struct iosys_map source = + IOSYS_MAP_INIT_OFFSET(&memirq->bo->vmap, + XE_MEMIRQ_SOURCE_OFFSET(hwe->irq_page)); - if (memirq_received(memirq, &src_offset, offset, "SRC")) { - struct iosys_map status_offset = + if (memirq_received(memirq, &source, hwe->irq_offset, "SRC")) { + struct iosys_map status = IOSYS_MAP_INIT_OFFSET(&memirq->bo->vmap, - XE_MEMIRQ_STATUS_OFFSET(instance) + offset * SZ_16); - memirq_dispatch_engine(memirq, &status_offset, hwe); + XE_MEMIRQ_VECTOR_OFFSET(hwe->irq_page, + hwe->irq_offset)); + memirq_dispatch_engine(memirq, &status, hwe); } } From 86d08fe942680bea5f77b414748a78a1ad7613f3 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 18 May 2026 21:25:43 +0200 Subject: [PATCH 26/31] drm/xe/memirq: Reduce buffer size When using MSI-X, we don't have to allocate the largest possible buffer to accommodate all potential engine instances. Loop through available engines, find highest engine instance and reduce buffer size to avoid memory waste. Signed-off-by: Michal Wajdeczko Cc: Ilia Levi Reviewed-by: Ilia Levi Link: https://patch.msgid.link/20260518192547.600-6-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_memirq.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_memirq.c b/drivers/gpu/drm/xe/xe_memirq.c index 285fffea62d8..92f1c1150d83 100644 --- a/drivers/gpu/drm/xe/xe_memirq.c +++ b/drivers/gpu/drm/xe/xe_memirq.c @@ -172,18 +172,35 @@ static inline bool hw_reports_to_instance_zero(struct xe_memirq *memirq) return xe_device_has_msix(memirq_to_xe(memirq)); } +static unsigned int hwe_max_count(struct xe_tile *tile) +{ + unsigned int max_instance = 0; + unsigned int gtid, hweid; + struct xe_hw_engine *hwe; + struct xe_gt *gt; + + for_each_gt_on_tile(gt, tile, gtid) + for_each_hw_engine(hwe, gt, hweid) + max_instance = max(max_instance, hwe->instance); + + return max_instance + 1; +} + static int memirq_alloc_pages(struct xe_memirq *memirq) { struct xe_device *xe = memirq_to_xe(memirq); struct xe_tile *tile = memirq_to_tile(memirq); - size_t bo_size = hw_reports_to_instance_zero(memirq) ? - XE_HW_ENGINE_MAX_INSTANCE * SZ_4K : SZ_4K; + unsigned int num_pages; struct xe_bo *bo; + size_t bo_size; int err; BUILD_BUG_ON(!IS_ALIGNED(XE_MEMIRQ_SOURCE_OFFSET(0), SZ_64)); BUILD_BUG_ON(!IS_ALIGNED(XE_MEMIRQ_STATUS_OFFSET(0), SZ_4K)); + num_pages = hw_reports_to_instance_zero(memirq) ? hwe_max_count(tile) : 1; + bo_size = num_pages * SZ_4K; + bo = xe_managed_bo_create_pin_map(xe, tile, bo_size, XE_BO_FLAG_SYSTEM | XE_BO_FLAG_GGTT | From becd6a78b56152ec95a34514ee0569fea477b5d0 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 18 May 2026 21:25:44 +0200 Subject: [PATCH 27/31] drm/xe/memirq: Update diagnostic message Instead printing static offset values, print number of allocated pages and the actual GGTT addresses of the page zero source and status and address of the common mask vector. Signed-off-by: Michal Wajdeczko Reviewed-by: Ilia Levi Link: https://patch.msgid.link/20260518192547.600-7-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_memirq.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_memirq.c b/drivers/gpu/drm/xe/xe_memirq.c index 92f1c1150d83..8dabd6744af9 100644 --- a/drivers/gpu/drm/xe/xe_memirq.c +++ b/drivers/gpu/drm/xe/xe_memirq.c @@ -226,9 +226,11 @@ static int memirq_alloc_pages(struct xe_memirq *memirq) memirq_assert(memirq, !memirq->status.is_iomem); memirq_assert(memirq, !memirq->mask.is_iomem); - memirq_debug(memirq, "page offsets: bo %#x bo_size %zu source %#x status %#x\n", - xe_bo_ggtt_addr(bo), bo_size, XE_MEMIRQ_SOURCE_OFFSET(0), - XE_MEMIRQ_STATUS_OFFSET(0)); + memirq_debug(memirq, "pages: count %u size %zu\n", num_pages, bo_size); + memirq_debug(memirq, "page0: source %#x status %#x mask %#x\n", + xe_bo_ggtt_addr(bo) + XE_MEMIRQ_SOURCE_OFFSET(0), + xe_bo_ggtt_addr(bo) + XE_MEMIRQ_STATUS_OFFSET(0), + xe_bo_ggtt_addr(bo) + XE_MEMIRQ_ENABLE_OFFSET); return 0; From 4c3077da4e100679d8e5d6e463746de0dd22bdfa Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 18 May 2026 21:25:45 +0200 Subject: [PATCH 28/31] drm/xe/memirq: Dump all source pages if MSI-X When using MSI-X, engines report their source/status on separate MEMIRQ pages, so we need to dump additional source pages, not just the first one. Signed-off-by: Michal Wajdeczko Cc: Ilia Levi Reviewed-by: Ilia Levi Link: https://patch.msgid.link/20260518192547.600-8-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_memirq.c | 18 +++++++++++++++--- drivers/gpu/drm/xe/xe_memirq_types.h | 2 ++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_memirq.c b/drivers/gpu/drm/xe/xe_memirq.c index 8dabd6744af9..609e0f3220cc 100644 --- a/drivers/gpu/drm/xe/xe_memirq.c +++ b/drivers/gpu/drm/xe/xe_memirq.c @@ -221,6 +221,7 @@ static int memirq_alloc_pages(struct xe_memirq *memirq) memirq->source = IOSYS_MAP_INIT_OFFSET(&bo->vmap, XE_MEMIRQ_SOURCE_OFFSET(0)); memirq->status = IOSYS_MAP_INIT_OFFSET(&bo->vmap, XE_MEMIRQ_STATUS_OFFSET(0)); memirq->mask = IOSYS_MAP_INIT_OFFSET(&bo->vmap, XE_MEMIRQ_ENABLE_OFFSET); + memirq->num_pages = num_pages; memirq_assert(memirq, !memirq->source.is_iomem); memirq_assert(memirq, !memirq->status.is_iomem); @@ -532,6 +533,18 @@ bool xe_memirq_guc_sw_int_0_irq_pending(struct xe_memirq *memirq, struct xe_guc guc_name(guc)); } +static void memirq_dump_source_pages(struct xe_memirq *memirq) +{ + memirq_assert(memirq, !memirq->bo->vmap.is_iomem); + + for (int n = 0; n < memirq->num_pages; n++) { + memirq_debug(memirq, "SOURCE %*ph\n", 32, + memirq->bo->vmap.vaddr + XE_MEMIRQ_SOURCE_OFFSET(n)); + memirq_debug(memirq, "SOURCE %*ph\n", 32, + memirq->bo->vmap.vaddr + XE_MEMIRQ_SOURCE_OFFSET(n) + 32); + } +} + /** * xe_memirq_handler - The `Memory Based Interrupts`_ Handler. * @memirq: the &xe_memirq @@ -551,9 +564,8 @@ void xe_memirq_handler(struct xe_memirq *memirq) if (!memirq->bo) return; - memirq_assert(memirq, !memirq->source.is_iomem); - memirq_debug(memirq, "SOURCE %*ph\n", 32, memirq->source.vaddr); - memirq_debug(memirq, "SOURCE %*ph\n", 32, memirq->source.vaddr + 32); + if (IS_ENABLED(CONFIG_DRM_XE_DEBUG_MEMIRQ)) + memirq_dump_source_pages(memirq); for_each_gt(gt, xe, gtid) { if (gt->tile != tile) diff --git a/drivers/gpu/drm/xe/xe_memirq_types.h b/drivers/gpu/drm/xe/xe_memirq_types.h index 02ac938cadb4..eab384342878 100644 --- a/drivers/gpu/drm/xe/xe_memirq_types.h +++ b/drivers/gpu/drm/xe/xe_memirq_types.h @@ -14,6 +14,7 @@ struct xe_bo; * struct xe_memirq - Data used by the `Memory Based Interrupts`_. * * @bo: buffer object with `Memory Based Interrupts Page Layout`_. + * @num_pages: number of per-instance source/status pages. * @source: iosys pointer to `Interrupt Source Report Page`_. * @status: iosys pointer to `Interrupt Status Report Page`_. * @mask: iosys pointer to Interrupt Enable Mask. @@ -21,6 +22,7 @@ struct xe_bo; */ struct xe_memirq { struct xe_bo *bo; + unsigned int num_pages; struct iosys_map source; struct iosys_map status; struct iosys_map mask; From 17e974818cd7313ed0d2697c0c5b9c600c9a939b Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 18 May 2026 21:25:46 +0200 Subject: [PATCH 29/31] drm/xe/memirq: Drop cached iosys_map for MEMIRQ mask It is used occasionally and iosys_map_wr() helper takes an offset parameter anyway. There is no extra benefit to keep a separate map. Signed-off-by: Michal Wajdeczko Reviewed-by: Ilia Levi Link: https://patch.msgid.link/20260518192547.600-9-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_memirq.c | 5 ++--- drivers/gpu/drm/xe/xe_memirq_types.h | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_memirq.c b/drivers/gpu/drm/xe/xe_memirq.c index 609e0f3220cc..4909dafe182d 100644 --- a/drivers/gpu/drm/xe/xe_memirq.c +++ b/drivers/gpu/drm/xe/xe_memirq.c @@ -220,12 +220,10 @@ static int memirq_alloc_pages(struct xe_memirq *memirq) memirq->bo = bo; memirq->source = IOSYS_MAP_INIT_OFFSET(&bo->vmap, XE_MEMIRQ_SOURCE_OFFSET(0)); memirq->status = IOSYS_MAP_INIT_OFFSET(&bo->vmap, XE_MEMIRQ_STATUS_OFFSET(0)); - memirq->mask = IOSYS_MAP_INIT_OFFSET(&bo->vmap, XE_MEMIRQ_ENABLE_OFFSET); memirq->num_pages = num_pages; memirq_assert(memirq, !memirq->source.is_iomem); memirq_assert(memirq, !memirq->status.is_iomem); - memirq_assert(memirq, !memirq->mask.is_iomem); memirq_debug(memirq, "pages: count %u size %zu\n", num_pages, bo_size); memirq_debug(memirq, "page0: source %#x status %#x mask %#x\n", @@ -246,7 +244,8 @@ static void memirq_set_enable(struct xe_memirq *memirq, bool enable) * We only care about the GT_MI_USER_INTERRUPT from the engines and * the GuC does not look at the ENABLE mask at all. */ - iosys_map_wr(&memirq->mask, 0, u32, enable ? GT_MI_USER_INTERRUPT : 0); + iosys_map_wr(&memirq->bo->vmap, XE_MEMIRQ_ENABLE_OFFSET, u32, + enable ? GT_MI_USER_INTERRUPT : 0); memirq->enabled = enable; } diff --git a/drivers/gpu/drm/xe/xe_memirq_types.h b/drivers/gpu/drm/xe/xe_memirq_types.h index eab384342878..4ea3d1976d4f 100644 --- a/drivers/gpu/drm/xe/xe_memirq_types.h +++ b/drivers/gpu/drm/xe/xe_memirq_types.h @@ -17,7 +17,6 @@ struct xe_bo; * @num_pages: number of per-instance source/status pages. * @source: iosys pointer to `Interrupt Source Report Page`_. * @status: iosys pointer to `Interrupt Status Report Page`_. - * @mask: iosys pointer to Interrupt Enable Mask. * @enabled: internal flag used to control processing of the interrupts. */ struct xe_memirq { @@ -25,7 +24,6 @@ struct xe_memirq { unsigned int num_pages; struct iosys_map source; struct iosys_map status; - struct iosys_map mask; bool enabled; }; From 8d8395e943129b457403030d1112a1f9e48b6c27 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 18 May 2026 21:25:47 +0200 Subject: [PATCH 30/31] drm/xe/memirq: Drop cached iosys_map for MEMIRQ status Since addition of the MSI-X support, we mostly rely on the offset calculations done by XE_MEMIRQ_STATUS_OFFSET. We don't use this separate map pointing to the first status page anymore. Signed-off-by: Michal Wajdeczko Reviewed-by: Ilia Levi Link: https://patch.msgid.link/20260518192547.600-10-michal.wajdeczko@intel.com --- drivers/gpu/drm/xe/xe_memirq.c | 2 -- drivers/gpu/drm/xe/xe_memirq_types.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_memirq.c b/drivers/gpu/drm/xe/xe_memirq.c index 4909dafe182d..9dfe965cb46e 100644 --- a/drivers/gpu/drm/xe/xe_memirq.c +++ b/drivers/gpu/drm/xe/xe_memirq.c @@ -219,11 +219,9 @@ static int memirq_alloc_pages(struct xe_memirq *memirq) memirq->bo = bo; memirq->source = IOSYS_MAP_INIT_OFFSET(&bo->vmap, XE_MEMIRQ_SOURCE_OFFSET(0)); - memirq->status = IOSYS_MAP_INIT_OFFSET(&bo->vmap, XE_MEMIRQ_STATUS_OFFSET(0)); memirq->num_pages = num_pages; memirq_assert(memirq, !memirq->source.is_iomem); - memirq_assert(memirq, !memirq->status.is_iomem); memirq_debug(memirq, "pages: count %u size %zu\n", num_pages, bo_size); memirq_debug(memirq, "page0: source %#x status %#x mask %#x\n", diff --git a/drivers/gpu/drm/xe/xe_memirq_types.h b/drivers/gpu/drm/xe/xe_memirq_types.h index 4ea3d1976d4f..c2b0b33d55cd 100644 --- a/drivers/gpu/drm/xe/xe_memirq_types.h +++ b/drivers/gpu/drm/xe/xe_memirq_types.h @@ -16,14 +16,12 @@ struct xe_bo; * @bo: buffer object with `Memory Based Interrupts Page Layout`_. * @num_pages: number of per-instance source/status pages. * @source: iosys pointer to `Interrupt Source Report Page`_. - * @status: iosys pointer to `Interrupt Status Report Page`_. * @enabled: internal flag used to control processing of the interrupts. */ struct xe_memirq { struct xe_bo *bo; unsigned int num_pages; struct iosys_map source; - struct iosys_map status; bool enabled; }; From 339fa0be9e4a5d69fa47e91f4a36574224fb478f Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Thu, 14 May 2026 20:32:10 +0000 Subject: [PATCH 31/31] drm/xe/oa: Fix exec_queue leak on width check in stream open In xe_oa_stream_open_ioctl(), when param.exec_q->width > 1 the function returns -EOPNOTSUPP directly, skipping the existing err_exec_q cleanup path. The exec_queue reference obtained by xe_exec_queue_lookup() is leaked. The exec queue holds a reference on the xe_file, which is only dropped during queue teardown. The leaked lookup ref is not on the file's exec_queue xarray, so file close cannot release it. This keeps both the exec queue and the file private state pinned indefinitely. Jump to err_exec_q instead of returning directly so the reference is released. Fixes: f0ed39830e60 ("xe/oa: Fix query mode of operation for OAR/OAC") Assisted-by: Claude:claude-opus-4.6 Reviewed-by: Ashutosh Dixit Link: https://patch.msgid.link/20260514203210.593488-1-shuicheng.lin@intel.com Signed-off-by: Shuicheng Lin --- drivers/gpu/drm/xe/xe_oa.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c index 7c9071abb44f..4bf4b1f65929 100644 --- a/drivers/gpu/drm/xe/xe_oa.c +++ b/drivers/gpu/drm/xe/xe_oa.c @@ -2051,8 +2051,10 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *f if (XE_IOCTL_DBG(oa->xe, !param.exec_q)) return -ENOENT; - if (XE_IOCTL_DBG(oa->xe, param.exec_q->width > 1)) - return -EOPNOTSUPP; + if (XE_IOCTL_DBG(oa->xe, param.exec_q->width > 1)) { + ret = -EOPNOTSUPP; + goto err_exec_q; + } } /*