From b2bce0e551e89af37cfcb1b1158d80f369eeea3f Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Mon, 10 Nov 2025 22:14:58 +0000 Subject: [PATCH 0001/1610] drm/xe/pat: Add helper to query compression enable status Add xe_pat_index_get_comp_en() helper function to check whether compression is enabled for a given PAT index by extracting the XE2_COMP_EN bit from the PAT table entry. There are no current users, however there are multiple in-flight series which will all use this helper. CC: Nitin Gote CC: Sanjay Yadav CC: Matt Roper Suggested-by: Matthew Auld Signed-off-by: Xin Wang Reviewed-by: Matt Roper Reviewed-by: Nitin Gote Reviewed-by: Matthew Auld Reviewed-by: Sanjay Yadav Signed-off-by: Matthew Auld Link: https://patch.msgid.link/20251110221458.1864507-2-x.wang@intel.com --- drivers/gpu/drm/xe/xe_pat.c | 6 ++++++ drivers/gpu/drm/xe/xe_pat.h | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_pat.c b/drivers/gpu/drm/xe/xe_pat.c index 68171cceea18..1b4d5d3def0f 100644 --- a/drivers/gpu/drm/xe/xe_pat.c +++ b/drivers/gpu/drm/xe/xe_pat.c @@ -196,6 +196,12 @@ u16 xe_pat_index_get_coh_mode(struct xe_device *xe, u16 pat_index) return xe->pat.table[pat_index].coh_mode; } +bool xe_pat_index_get_comp_en(struct xe_device *xe, u16 pat_index) +{ + WARN_ON(pat_index >= xe->pat.n_entries); + return !!(xe->pat.table[pat_index].value & XE2_COMP_EN); +} + static void program_pat(struct xe_gt *gt, const struct xe_pat_table_entry table[], int n_entries) { diff --git a/drivers/gpu/drm/xe/xe_pat.h b/drivers/gpu/drm/xe/xe_pat.h index 05dae03a5f54..b8559120989e 100644 --- a/drivers/gpu/drm/xe/xe_pat.h +++ b/drivers/gpu/drm/xe/xe_pat.h @@ -58,4 +58,14 @@ int xe_pat_dump(struct xe_gt *gt, struct drm_printer *p); */ u16 xe_pat_index_get_coh_mode(struct xe_device *xe, u16 pat_index); +/** + * xe_pat_index_get_comp_en - Extract the compression enable flag for + * the given pat_index. + * @xe: xe device + * @pat_index: The pat_index to query + * + * Return: true if compression is enabled for this pat_index, false otherwise. + */ +bool xe_pat_index_get_comp_en(struct xe_device *xe, u16 pat_index); + #endif From 8f565bdd14eec5611cc041dba4650e42ccdf71d9 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Wed, 12 Nov 2025 18:10:06 +0000 Subject: [PATCH 0002/1610] drm/xe: Prevent BIT() overflow when handling invalid prefetch region If user provides a large value (such as 0x80) for parameter prefetch_mem_region_instance in vm_bind ioctl, it will cause BIT(prefetch_region) overflow as below: " ------------[ cut here ]------------ UBSAN: shift-out-of-bounds in drivers/gpu/drm/xe/xe_vm.c:3414:7 shift exponent 128 is too large for 64-bit type 'long unsigned int' CPU: 8 UID: 0 PID: 53120 Comm: xe_exec_system_ Tainted: G W 6.18.0-rc1-lgci-xe-kernel+ #200 PREEMPT(voluntary) Tainted: [W]=WARN Hardware name: ASUS System Product Name/PRIME Z790-P WIFI, BIOS 0812 02/24/2023 Call Trace: dump_stack_lvl+0xa0/0xc0 dump_stack+0x10/0x20 ubsan_epilogue+0x9/0x40 __ubsan_handle_shift_out_of_bounds+0x10e/0x170 ? mutex_unlock+0x12/0x20 xe_vm_bind_ioctl.cold+0x20/0x3c [xe] ... " Fix it by validating prefetch_region before the BIT() usage. v2: Add Closes and Cc stable kernels. (Matt) Reported-by: Koen Koning Reported-by: Peter Senna Tschudin Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs") Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/6478 Cc: # v6.8+ Reviewed-by: Matthew Auld Signed-off-by: Shuicheng Lin Signed-off-by: Matthew Auld Link: https://patch.msgid.link/20251112181005.2120521-2-shuicheng.lin@intel.com --- drivers/gpu/drm/xe/xe_vm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 8fb5cc6a69ec..7cac646bdf1c 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -3411,8 +3411,10 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe, struct xe_vm *vm, op == DRM_XE_VM_BIND_OP_PREFETCH) || XE_IOCTL_DBG(xe, prefetch_region && op != DRM_XE_VM_BIND_OP_PREFETCH) || - XE_IOCTL_DBG(xe, (prefetch_region != DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC && - !(BIT(prefetch_region) & xe->info.mem_region_mask))) || + XE_IOCTL_DBG(xe, (prefetch_region != DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC && + /* Guard against undefined shift in BIT(prefetch_region) */ + (prefetch_region >= (sizeof(xe->info.mem_region_mask) * 8) || + !(BIT(prefetch_region) & xe->info.mem_region_mask)))) || XE_IOCTL_DBG(xe, obj && op == DRM_XE_VM_BIND_OP_UNMAP) || XE_IOCTL_DBG(xe, (flags & DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET) && From 562b0f254d8b1515a1c8d2a650f940d4f719300e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= Date: Fri, 14 Nov 2025 14:40:30 +0100 Subject: [PATCH 0003/1610] drm/xe/pf: Fix kernel-doc warning in migration_save_consume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kernel-doc for xe_sriov_pf_migration_save_consume() contained multiple "Return:" sections, causing a warning. Fix it by removing the extra line. Fixes: 67df4a5cbc583 ("drm/xe/pf: Add data structures and handlers for migration rings") Signed-off-by: Michał Winiarski Reviewed-by: Michal Wajdeczko Link: https://patch.msgid.link/20251114134030.1795947-1-michal.winiarski@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_sriov_pf_migration.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_sriov_pf_migration.c b/drivers/gpu/drm/xe/xe_sriov_pf_migration.c index 21b06ce6830a..de06cc690fc8 100644 --- a/drivers/gpu/drm/xe/xe_sriov_pf_migration.c +++ b/drivers/gpu/drm/xe/xe_sriov_pf_migration.c @@ -148,8 +148,6 @@ pf_migration_consume(struct xe_device *xe, unsigned int vfid) * Return: Pointer to &xe_sriov_packet on success, * NULL if ring is empty and no more migration data is expected, * ERR_PTR value in case of error. - * - * Return: 0 on success or a negative error code on failure. */ struct xe_sriov_packet * xe_sriov_pf_migration_save_consume(struct xe_device *xe, unsigned int vfid) From 9be4f0f687048ba77428ceca11994676736507b7 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 13 Nov 2025 15:40:39 -0800 Subject: [PATCH 0004/1610] drm/xe/kunit: Fix forcewake assertion in mocs test The MOCS kunit test calls KUNIT_ASSERT_TRUE_MSG() with a condition of 'true;' this prevents the assertion from ever failing. Replace KUNIT_ASSERT_TRUE_MSG with KUNIT_FAIL_AND_ABORT to get the intended failure behavior in cases where forcewake was not acquired successfully. Fixes: 51c0ee84e4dc ("drm/xe/tests/mocs: Hold XE_FORCEWAKE_ALL for LNCF regs") Cc: Tejas Upadhyay Cc: Gustavo Sousa Reviewed-by: Lucas De Marchi Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251113234038.2256106-2-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/tests/xe_mocs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/tests/xe_mocs.c b/drivers/gpu/drm/xe/tests/xe_mocs.c index 0e502feaca81..6bb278167aaf 100644 --- a/drivers/gpu/drm/xe/tests/xe_mocs.c +++ b/drivers/gpu/drm/xe/tests/xe_mocs.c @@ -49,7 +49,7 @@ static void read_l3cc_table(struct xe_gt *gt, fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) { xe_force_wake_put(gt_to_fw(gt), fw_ref); - KUNIT_ASSERT_TRUE_MSG(test, true, "Forcewake Failed.\n"); + KUNIT_FAIL_AND_ABORT(test, "Forcewake Failed.\n"); } for (i = 0; i < info->num_mocs_regs; i++) { From b1aa02acd03bfef3ed39c511d33c4a4303d2f9b1 Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Mon, 10 Nov 2025 23:26:58 +0000 Subject: [PATCH 0005/1610] drm/xe: Remove duplicate DRM_EXEC selection from Kconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are 2 identical "select DRM_EXEC" lines for DRM_XE. Remove one to clean up the configuration. Fixes: d490ecf57790 ("drm/xe: Rework xe_exec and the VM rebind worker to use the drm_exec helper") Cc: Thomas Hellström Cc: Lucas De Marchi Signed-off-by: Shuicheng Lin Reviewed-by: Nitin Gote Reviewed-by: Lucas De Marchi Link: https://patch.msgid.link/20251110232657.1807998-2-shuicheng.lin@intel.com Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig index 7219f6b884b6..4b288eb3f5b0 100644 --- a/drivers/gpu/drm/xe/Kconfig +++ b/drivers/gpu/drm/xe/Kconfig @@ -13,7 +13,6 @@ config DRM_XE select TMPFS select DRM_BUDDY select DRM_CLIENT_SELECTION - select DRM_EXEC select DRM_KMS_HELPER select DRM_KUNIT_TEST_HELPERS if DRM_XE_KUNIT_TEST != n select DRM_PANEL From dab751b4240f0f0eadea81f93ff0b439379bc6ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= Date: Fri, 14 Nov 2025 11:07:13 +0100 Subject: [PATCH 0006/1610] drm/xe/pf: Drop the VF VRAM BO reference on successful restore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The reference is only dropped on error. Fix it by adding the missing xe_bo_put(). Fixes: 49cf1b9b609fe ("drm/xe/pf: Handle VRAM migration data as part of PF control") Reported-by: Adam Miszczak Reviewed-by: Matthew Auld Link: https://patch.msgid.link/20251114100713.1776073-1-michal.winiarski@intel.com Signed-off-by: Michał Winiarski --- drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c index 35a12d48dcc1..7540a3854dc7 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c @@ -661,6 +661,8 @@ static int pf_restore_vf_vram_mig_data(struct xe_gt *gt, unsigned int vfid, goto err; } + xe_bo_put(vram); + return 0; err: xe_bo_put(vram); From 78ff838a8ab78b3cd438e382ff5204b93db3237e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= Date: Fri, 14 Nov 2025 13:23:39 +0100 Subject: [PATCH 0007/1610] drm/xe/pf: Check for fence error on VRAM save/restore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code incorrectly assumes that the VRAM save/restore fence is valid. Fix it by checking for error. Fixes: 49cf1b9b609fe ("drm/xe/pf: Handle VRAM migration data as part of PF control") Suggested-by: Matthew Auld Reviewed-by: Matthew Auld Reviewed-by: Michal Wajdeczko Link: https://patch.msgid.link/20251114122339.1791026-1-michal.winiarski@intel.com Signed-off-by: Michał Winiarski --- drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c index 7540a3854dc7..d5d918ddce4f 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c @@ -571,6 +571,10 @@ static int pf_save_vram_chunk(struct xe_gt *gt, unsigned int vfid, fence = __pf_save_restore_vram(gt, vfid, src_vram, src_vram_offset, data->bo, 0, size, true); + if (IS_ERR(fence)) { + ret = PTR_ERR(fence); + goto fail; + } ret = dma_fence_wait_timeout(fence, false, PF_VRAM_SAVE_RESTORE_TIMEOUT); dma_fence_put(fence); @@ -654,6 +658,11 @@ static int pf_restore_vf_vram_mig_data(struct xe_gt *gt, unsigned int vfid, fence = __pf_save_restore_vram(gt, vfid, vram, data->hdr.offset, data->bo, 0, data->hdr.size, false); + if (IS_ERR(fence)) { + ret = PTR_ERR(fence); + goto err; + } + ret = dma_fence_wait_timeout(fence, false, PF_VRAM_SAVE_RESTORE_TIMEOUT); dma_fence_put(fence); if (!ret) { From c34a14bce7090862ebe5a64abe8d85df75e62737 Mon Sep 17 00:00:00 2001 From: Venkata Ramana Nayana Date: Fri, 7 Nov 2025 14:01:41 +0530 Subject: [PATCH 0008/1610] drm/xe/irq: Handle msix vector0 interrupt Current gu2host handler registered as MSI-X vector 0 and as per bspec for a msix vector 0 interrupt, the driver must check the legacy registers 190008(TILE_INT_REG), 190060h (GT INTR Identity Reg 0) and other registers mentioned in "Interrupt Service Routine Pseudocode" otherwise it will block the next interrupts. To overcome this issue replacing guc2host handler with legacy xe_irq_handler. Fixes: da889070be7b2 ("drm/xe/irq: Separate MSI and MSI-X flows") Bspec: 62357 Signed-off-by: Venkata Ramana Nayana Reviewed-by: Balasubramani Vivekanandan Link: https://patch.msgid.link/20251107083141.2080189-1-venkata.ramana.nayana@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_irq.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_irq.c b/drivers/gpu/drm/xe/xe_irq.c index e5ed0242f7b1..024e13e606ec 100644 --- a/drivers/gpu/drm/xe/xe_irq.c +++ b/drivers/gpu/drm/xe/xe_irq.c @@ -897,22 +897,6 @@ static int xe_irq_msix_init(struct xe_device *xe) return 0; } -static irqreturn_t guc2host_irq_handler(int irq, void *arg) -{ - struct xe_device *xe = arg; - struct xe_tile *tile; - u8 id; - - if (!atomic_read(&xe->irq.enabled)) - return IRQ_NONE; - - for_each_tile(tile, xe, id) - xe_guc_irq_handler(&tile->primary_gt->uc.guc, - GUC_INTR_GUC2HOST); - - return IRQ_HANDLED; -} - static irqreturn_t xe_irq_msix_default_hwe_handler(int irq, void *arg) { unsigned int tile_id, gt_id; @@ -1029,7 +1013,7 @@ int xe_irq_msix_request_irqs(struct xe_device *xe) u16 msix; msix = GUC2HOST_MSIX; - err = xe_irq_msix_request_irq(xe, guc2host_irq_handler, xe, + err = xe_irq_msix_request_irq(xe, xe_irq_handler(xe), xe, DRIVER_NAME "-guc2host", false, &msix); if (err) return err; From de72d9df4f453c08da3d4a15ce75fbd5f891bd2e Mon Sep 17 00:00:00 2001 From: Vinod Govindapillai Date: Tue, 11 Nov 2025 14:46:06 +0200 Subject: [PATCH 0009/1610] drm/i915/fbc: Apply Wa_15018326506 Disable FBC in bmg as per the wa recommendation. v2: use the bmg platform instead of a specific stepping v3: wa to Wa Bspec: 74212 Signed-off-by: Vinod Govindapillai Reviewed-by: Mika Kahola Acked-by: Uma Shankar Link: https://patch.msgid.link/20251111124606.402380-1-vinod.govindapillai@intel.com Signed-off-by: Vinod Govindapillai --- drivers/gpu/drm/i915/display/intel_display_wa.c | 2 ++ drivers/gpu/drm/i915/display/intel_display_wa.h | 1 + drivers/gpu/drm/i915/display/intel_fbc.c | 10 ++++++++++ 3 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.c b/drivers/gpu/drm/i915/display/intel_display_wa.c index e38e5e87877c..b2e71fa61c0a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_wa.c +++ b/drivers/gpu/drm/i915/display/intel_display_wa.c @@ -70,6 +70,8 @@ bool __intel_display_wa(struct intel_display *display, enum intel_display_wa wa, return DISPLAY_VER(display) == 13; case INTEL_DISPLAY_WA_22014263786: return IS_DISPLAY_VERx100(display, 1100, 1400); + case INTEL_DISPLAY_WA_15018326506: + return display->platform.battlemage; default: drm_WARN(display->drm, 1, "Missing Wa number: %s\n", name); break; diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.h b/drivers/gpu/drm/i915/display/intel_display_wa.h index 3644e8e2b724..f648b00cb97d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_wa.h +++ b/drivers/gpu/drm/i915/display/intel_display_wa.h @@ -26,6 +26,7 @@ enum intel_display_wa { INTEL_DISPLAY_WA_16025573575, INTEL_DISPLAY_WA_14011503117, INTEL_DISPLAY_WA_22014263786, + INTEL_DISPLAY_WA_15018326506, }; bool __intel_display_wa(struct intel_display *display, enum intel_display_wa wa, const char *name); diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 437d2fda20a7..205c7266af43 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1521,6 +1521,16 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, return 0; } + /* + * Wa_15018326506: + * Fixes: Underrun during media decode + * Workaround: Do not enable FBC + */ + if (intel_display_wa(display, 15018326506)) { + plane_state->no_fbc_reason = "Wa_15018326506"; + return 0; + } + /* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */ if (intel_display_vtd_active(display) && (display->platform.skylake || display->platform.broxton)) { From 1f2cf5295cdba71818288c9e495b4ef5097565ed Mon Sep 17 00:00:00 2001 From: Satyanarayana K V P Date: Tue, 18 Nov 2025 12:07:44 +0000 Subject: [PATCH 0010/1610] drm/xe/sa: Shadow buffer support in the sub-allocator pool The existing sub-allocator is limited to managing a single buffer object. This enhancement introduces shadow buffer functionality to support scenarios requiring dual buffer management. The changes include added shadow buffer object creation capability, Management for both primary and shadow buffers, and appropriate locking mechanisms for thread-safe operations. This enables more flexible buffer allocation strategies in scenarios where shadow buffering is required. Signed-off-by: Satyanarayana K V P Suggested-by: Matthew Brost Cc: Michal Wajdeczko Cc: Matthew Auld Reviewed-by: Matthew Brost Signed-off-by: Matthew Brost Link: https://patch.msgid.link/20251118120745.3460172-2-satyanarayana.k.v.p@intel.com --- drivers/gpu/drm/xe/xe_guc_buf.c | 2 +- drivers/gpu/drm/xe/xe_sa.c | 67 +++++++++++++++++++++++++++- drivers/gpu/drm/xe/xe_sa.h | 20 ++++++++- drivers/gpu/drm/xe/xe_sa_types.h | 3 ++ drivers/gpu/drm/xe/xe_sriov_vf_ccs.c | 3 ++ 5 files changed, 91 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_buf.c b/drivers/gpu/drm/xe/xe_guc_buf.c index 3ce442500130..c36fc31e0438 100644 --- a/drivers/gpu/drm/xe/xe_guc_buf.c +++ b/drivers/gpu/drm/xe/xe_guc_buf.c @@ -30,7 +30,7 @@ static int guc_buf_cache_init(struct xe_guc_buf_cache *cache, u32 size) struct xe_gt *gt = cache_to_gt(cache); struct xe_sa_manager *sam; - sam = __xe_sa_bo_manager_init(gt_to_tile(gt), size, 0, sizeof(u32)); + sam = __xe_sa_bo_manager_init(gt_to_tile(gt), size, 0, sizeof(u32), 0); if (IS_ERR(sam)) return PTR_ERR(sam); cache->sam = sam; diff --git a/drivers/gpu/drm/xe/xe_sa.c b/drivers/gpu/drm/xe/xe_sa.c index 63a5263dcf1b..a87c1436c7c1 100644 --- a/drivers/gpu/drm/xe/xe_sa.c +++ b/drivers/gpu/drm/xe/xe_sa.c @@ -29,6 +29,7 @@ static void xe_sa_bo_manager_fini(struct drm_device *drm, void *arg) kvfree(sa_manager->cpu_ptr); sa_manager->bo = NULL; + sa_manager->shadow = NULL; } /** @@ -37,12 +38,14 @@ static void xe_sa_bo_manager_fini(struct drm_device *drm, void *arg) * @size: number of bytes to allocate * @guard: number of bytes to exclude from suballocations * @align: alignment for each suballocated chunk + * @flags: flags for suballocator * * Prepares the suballocation manager for suballocations. * * Return: a pointer to the &xe_sa_manager or an ERR_PTR on failure. */ -struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 guard, u32 align) +struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, + u32 guard, u32 align, u32 flags) { struct xe_device *xe = tile_to_xe(tile); struct xe_sa_manager *sa_manager; @@ -79,6 +82,26 @@ struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u3 memset(sa_manager->cpu_ptr, 0, bo->ttm.base.size); } + if (flags & XE_SA_BO_MANAGER_FLAG_SHADOW) { + struct xe_bo *shadow; + + ret = drmm_mutex_init(&xe->drm, &sa_manager->swap_guard); + if (ret) + return ERR_PTR(ret); + + shadow = 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(shadow)) { + drm_err(&xe->drm, "Failed to prepare %uKiB BO for SA manager (%pe)\n", + size / SZ_1K, shadow); + return ERR_CAST(shadow); + } + sa_manager->shadow = shadow; + } + drm_suballoc_manager_init(&sa_manager->base, managed_size, align); ret = drmm_add_action_or_reset(&xe->drm, xe_sa_bo_manager_fini, sa_manager); @@ -88,6 +111,48 @@ struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u3 return sa_manager; } +/** + * xe_sa_bo_swap_shadow() - Swap the SA BO with shadow BO. + * @sa_manager: the XE sub allocator manager + * + * Swaps the sub-allocator primary buffer object with shadow buffer object. + * + * Return: None. + */ +void xe_sa_bo_swap_shadow(struct xe_sa_manager *sa_manager) +{ + struct xe_device *xe = tile_to_xe(sa_manager->bo->tile); + + xe_assert(xe, sa_manager->shadow); + lockdep_assert_held(&sa_manager->swap_guard); + + swap(sa_manager->bo, sa_manager->shadow); + if (!sa_manager->bo->vmap.is_iomem) + sa_manager->cpu_ptr = sa_manager->bo->vmap.vaddr; +} + +/** + * xe_sa_bo_sync_shadow() - Sync the SA Shadow BO with primary BO. + * @sa_bo: the sub-allocator buffer object. + * + * Synchronize sub-allocator shadow buffer object with primary buffer object. + * + * Return: None. + */ +void xe_sa_bo_sync_shadow(struct drm_suballoc *sa_bo) +{ + struct xe_sa_manager *sa_manager = to_xe_sa_manager(sa_bo->manager); + struct xe_device *xe = tile_to_xe(sa_manager->bo->tile); + + xe_assert(xe, sa_manager->shadow); + lockdep_assert_held(&sa_manager->swap_guard); + + xe_map_memcpy_to(xe, &sa_manager->shadow->vmap, + drm_suballoc_soffset(sa_bo), + xe_sa_bo_cpu_addr(sa_bo), + drm_suballoc_size(sa_bo)); +} + /** * __xe_sa_bo_new() - Make a suballocation but use custom gfp flags. * @sa_manager: the &xe_sa_manager diff --git a/drivers/gpu/drm/xe/xe_sa.h b/drivers/gpu/drm/xe/xe_sa.h index 1be744350836..05e9a4e00e78 100644 --- a/drivers/gpu/drm/xe/xe_sa.h +++ b/drivers/gpu/drm/xe/xe_sa.h @@ -14,12 +14,14 @@ struct dma_fence; struct xe_tile; -struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 guard, u32 align); +#define XE_SA_BO_MANAGER_FLAG_SHADOW BIT(0) +struct xe_sa_manager *__xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, + u32 guard, u32 align, u32 flags); struct drm_suballoc *__xe_sa_bo_new(struct xe_sa_manager *sa_manager, u32 size, gfp_t gfp); static inline struct xe_sa_manager *xe_sa_bo_manager_init(struct xe_tile *tile, u32 size, u32 align) { - return __xe_sa_bo_manager_init(tile, size, SZ_4K, align); + return __xe_sa_bo_manager_init(tile, size, SZ_4K, align, 0); } /** @@ -69,4 +71,18 @@ static inline void *xe_sa_bo_cpu_addr(struct drm_suballoc *sa) drm_suballoc_soffset(sa); } +void xe_sa_bo_swap_shadow(struct xe_sa_manager *sa_manager); +void xe_sa_bo_sync_shadow(struct drm_suballoc *sa_bo); + +/** + * xe_sa_bo_swap_guard() - Retrieve the SA BO swap guard within sub-allocator. + * @sa_manager: the &xe_sa_manager + * + * Return: Sub alloctor swap guard mutex. + */ +static inline struct mutex *xe_sa_bo_swap_guard(struct xe_sa_manager *sa_manager) +{ + return &sa_manager->swap_guard; +} + #endif diff --git a/drivers/gpu/drm/xe/xe_sa_types.h b/drivers/gpu/drm/xe/xe_sa_types.h index cb7238799dcb..1085c9c37d6b 100644 --- a/drivers/gpu/drm/xe/xe_sa_types.h +++ b/drivers/gpu/drm/xe/xe_sa_types.h @@ -12,6 +12,9 @@ struct xe_bo; struct xe_sa_manager { struct drm_suballoc_manager base; struct xe_bo *bo; + struct xe_bo *shadow; + /** @swap_guard: Timeline guard updating @bo and @shadow */ + struct mutex swap_guard; void *cpu_ptr; bool is_iomem; }; diff --git a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c index 797a4b866226..9959d619addc 100644 --- a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c +++ b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c @@ -162,9 +162,12 @@ static int alloc_bb_pool(struct xe_tile *tile, struct xe_sriov_vf_ccs_ctx *ctx) 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); 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); ctx->mem.ccs_bb_pool = sa_manager; From fa18290bf0723b02bfa8d30d2e14722f0d096c2c Mon Sep 17 00:00:00 2001 From: Satyanarayana K V P Date: Tue, 18 Nov 2025 12:07:45 +0000 Subject: [PATCH 0011/1610] drm/xe/vf: Shadow buffer management for CCS read/write operations CCS copy command consist of 5-dword sequence. If vCPU halts during save/restore operations while these sequences are being programmed, incomplete writes can cause page faults during IGPU CCS metadata saving. Use shadow buffer management to prevent partial write issues during CCS operations. Signed-off-by: Satyanarayana K V P Suggested-by: Matthew Brost Cc: Michal Wajdeczko Cc: Matthew Auld Reviewed-by: Matthew Brost Signed-off-by: Matthew Brost Link: https://patch.msgid.link/20251118120745.3460172-3-satyanarayana.k.v.p@intel.com --- drivers/gpu/drm/xe/xe_migrate.c | 57 ++++++++++++++++++++++++++-- drivers/gpu/drm/xe/xe_migrate.h | 3 ++ drivers/gpu/drm/xe/xe_sriov_vf_ccs.c | 19 ++++++++-- drivers/gpu/drm/xe/xe_sriov_vf_ccs.h | 1 + 4 files changed, 73 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c index 2184af413b91..f3b66b55acfb 100644 --- a/drivers/gpu/drm/xe/xe_migrate.c +++ b/drivers/gpu/drm/xe/xe_migrate.c @@ -34,6 +34,7 @@ #include "xe_res_cursor.h" #include "xe_sa.h" #include "xe_sched_job.h" +#include "xe_sriov_vf_ccs.h" #include "xe_sync.h" #include "xe_trace_bo.h" #include "xe_validation.h" @@ -1103,12 +1104,16 @@ 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_sriov_vf_ccs_ctx *ctx; + struct xe_sa_manager *bb_pool; u64 size = xe_bo_size(src_bo); struct xe_bb *bb = NULL; u64 src_L0, src_L0_ofs; u32 src_L0_pt; int err; + ctx = &xe->sriov.vf.ccs.contexts[read_write]; + xe_res_first_sg(xe_bo_sg(src_bo), 0, size, &src_it); xe_res_first_sg(xe_bo_sg(src_bo), xe_bo_ccs_pages_start(src_bo), @@ -1141,11 +1146,15 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, size -= src_L0; } + bb_pool = ctx->mem.ccs_bb_pool; + guard(mutex) (xe_sa_bo_swap_guard(bb_pool)); + xe_sa_bo_swap_shadow(bb_pool); + bb = xe_bb_ccs_new(gt, batch_size, read_write); if (IS_ERR(bb)) { drm_err(&xe->drm, "BB allocation failed.\n"); err = PTR_ERR(bb); - goto err_ret; + return err; } batch_size_allocated = batch_size; @@ -1194,10 +1203,52 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, xe_assert(xe, (batch_size_allocated == bb->len)); src_bo->bb_ccs[read_write] = bb; + xe_sriov_vf_ccs_rw_update_bb_addr(ctx); + xe_sa_bo_sync_shadow(bb->bo); return 0; +} -err_ret: - return err; +/** + * xe_migrate_ccs_rw_copy_clear() - Clear the CCS read/write batch buffer + * content. + * @src_bo: The buffer object @src is currently bound to. + * @read_write : Creates BB commands for CCS read/write. + * + * Directly clearing the BB lacks atomicity and can lead to undefined + * behavior if the vCPU is halted mid-operation during the clearing + * process. To avoid this issue, we use a shadow buffer object approach. + * + * First swap the SA BO address with the shadow BO, perform the clearing + * operation on the BB, update the shadow BO in the ring buffer, then + * sync the shadow and the actual buffer to maintain consistency. + * + * Returns: None. + */ +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_device *xe = xe_bo_device(src_bo); + struct xe_sriov_vf_ccs_ctx *ctx; + struct xe_sa_manager *bb_pool; + u32 *cs; + + xe_assert(xe, IS_SRIOV_VF(xe)); + + 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); + + 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); + + xe_sa_bo_sync_shadow(bb->bo); + + xe_bb_free(bb, NULL); + src_bo->bb_ccs[read_write] = NULL; } /** diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h index 260e298e5dd7..464c05dde1ba 100644 --- a/drivers/gpu/drm/xe/xe_migrate.h +++ b/drivers/gpu/drm/xe/xe_migrate.h @@ -134,6 +134,9 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, struct xe_bo *src_bo, enum xe_sriov_vf_ccs_rw_ctxs read_write); +void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo, + enum xe_sriov_vf_ccs_rw_ctxs read_write); + struct xe_lrc *xe_migrate_lrc(struct xe_migrate *migrate); struct xe_exec_queue *xe_migrate_exec_queue(struct xe_migrate *migrate); struct dma_fence *xe_migrate_vram_copy_chunk(struct xe_bo *vram_bo, u64 vram_offset, diff --git a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c index 9959d619addc..33f4238604e1 100644 --- a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c +++ b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c @@ -150,7 +150,8 @@ static int alloc_bb_pool(struct xe_tile *tile, struct xe_sriov_vf_ccs_ctx *ctx) 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_16); + 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", @@ -384,6 +385,18 @@ err_ret: return err; } +#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); + struct xe_lrc *lrc = xe_exec_queue_lrc(ctx->mig_q); + struct xe_device *xe = gt_to_xe(ctx->mig_q->gt); + + xe_device_wmb(xe); + xe_map_wr(xe, &lrc->bo->vmap, XE_SRIOV_VF_CCS_RW_BB_ADDR_OFFSET, u32, addr); + xe_device_wmb(xe); +} + /** * xe_sriov_vf_ccs_attach_bo - Insert CCS read write commands in the BO. * @bo: the &buffer object to which batch buffer commands will be added. @@ -444,9 +457,7 @@ int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo) if (!bb) continue; - memset(bb->cs, MI_NOOP, bb->len * sizeof(u32)); - xe_bb_free(bb, NULL); - bo->bb_ccs[ctx_id] = NULL; + xe_migrate_ccs_rw_copy_clear(bo, ctx_id); } return 0; } diff --git a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h index f8ca6efce9ee..00e58b36c510 100644 --- a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h +++ b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h @@ -20,6 +20,7 @@ int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo); int xe_sriov_vf_ccs_register_context(struct xe_device *xe); void xe_sriov_vf_ccs_rebase(struct xe_device *xe); void xe_sriov_vf_ccs_print(struct xe_device *xe, struct drm_printer *p); +void xe_sriov_vf_ccs_rw_update_bb_addr(struct xe_sriov_vf_ccs_ctx *ctx); static inline bool xe_sriov_vf_ccs_ready(struct xe_device *xe) { From 37fc7b7b3ab0e3bb900657199cd3770a4fda03fb Mon Sep 17 00:00:00 2001 From: Dibin Moolakadan Subrahmanian Date: Tue, 11 Nov 2025 19:24:03 +0530 Subject: [PATCH 0012/1610] drm/i915/fbdev: Hold runtime PM ref during fbdev BO creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During fbdev probe, the xe driver allocates and pins a framebuffer BO (via xe_bo_create_pin_map_novm() → xe_ggtt_insert_bo()). Without a runtime PM reference, xe_pm_runtime_get_noresume() warns about missing outer PM protection as below: xe 0000:03:00.0: [drm] Missing outer runtime PM protection Acquire a runtime PM reference before framebuffer allocation to ensure xe_ggtt_insert_bo() executes under active runtime PM context. Changes in v2: - Update commit message to add Fixes tag (Jani Nikula) Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/6350 Fixes: 44e694958b95 ("drm/xe/display: Implement display support") Cc: Jani Nikula Signed-off-by: Dibin Moolakadan Subrahmanian Reviewed-by: Jouni Högander Signed-off-by: Ankit Nautiyal Link: https://patch.msgid.link/20251111135403.3415947-1-dibin.moolakadan.subrahmanian@intel.com --- drivers/gpu/drm/i915/display/intel_fbdev.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index e5449c41cfa1..7173bd1cbffd 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -288,13 +288,18 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, drm_framebuffer_put(&fb->base); fb = NULL; } + + wakeref = intel_display_rpm_get(display); + if (!fb || drm_WARN_ON(display->drm, !intel_fb_bo(&fb->base))) { drm_dbg_kms(display->drm, "no BIOS fb, allocating a new one\n"); fb = __intel_fbdev_fb_alloc(display, sizes); - if (IS_ERR(fb)) - return PTR_ERR(fb); + if (IS_ERR(fb)) { + ret = PTR_ERR(fb); + goto out_unlock; + } } else { drm_dbg_kms(display->drm, "re-using BIOS fb\n"); prealloc = true; @@ -302,8 +307,6 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, sizes->fb_height = fb->base.height; } - wakeref = intel_display_rpm_get(display); - /* Pin the GGTT vma for our access via info->screen_base. * This also validates that any existing fb inherited from the * BIOS is suitable for own access. From d7e7a0048f6aceaadd19bda66de496c60b741cb1 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:31 +0200 Subject: [PATCH 0013/1610] drm/i915/cx0: Rename TBT functions to be ICL specific Rename pll functions to include ICL platform as these are used from ICL onwards. Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-2-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 9c7cf03cf022..8c345e1bdd94 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -3753,9 +3753,9 @@ static bool combo_pll_get_hw_state(struct intel_display *display, return icl_pll_get_hw_state(display, pll, dpll_hw_state, enable_reg); } -static bool tbt_pll_get_hw_state(struct intel_display *display, - struct intel_dpll *pll, - struct intel_dpll_hw_state *dpll_hw_state) +static bool icl_tbt_pll_get_hw_state(struct intel_display *display, + struct intel_dpll *pll, + struct intel_dpll_hw_state *dpll_hw_state) { return icl_pll_get_hw_state(display, pll, dpll_hw_state, TBT_PLL_ENABLE); } @@ -3984,9 +3984,9 @@ static void combo_pll_enable(struct intel_display *display, /* DVFS post sequence would be here. See the comment above. */ } -static void tbt_pll_enable(struct intel_display *display, - struct intel_dpll *pll, - const struct intel_dpll_hw_state *dpll_hw_state) +static void icl_tbt_pll_enable(struct intel_display *display, + struct intel_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) { const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; @@ -4069,8 +4069,8 @@ static void combo_pll_disable(struct intel_display *display, icl_pll_disable(display, pll, enable_reg); } -static void tbt_pll_disable(struct intel_display *display, - struct intel_dpll *pll) +static void icl_tbt_pll_disable(struct intel_display *display, + struct intel_dpll *pll) { icl_pll_disable(display, pll, TBT_PLL_ENABLE); } @@ -4142,10 +4142,10 @@ static const struct intel_dpll_funcs combo_pll_funcs = { .get_freq = icl_ddi_combo_pll_get_freq, }; -static const struct intel_dpll_funcs tbt_pll_funcs = { - .enable = tbt_pll_enable, - .disable = tbt_pll_disable, - .get_hw_state = tbt_pll_get_hw_state, +static const struct intel_dpll_funcs icl_tbt_pll_funcs = { + .enable = icl_tbt_pll_enable, + .disable = icl_tbt_pll_disable, + .get_hw_state = icl_tbt_pll_get_hw_state, .get_freq = icl_ddi_tbt_pll_get_freq, }; @@ -4159,7 +4159,7 @@ static const struct intel_dpll_funcs mg_pll_funcs = { static const struct dpll_info icl_plls[] = { { .name = "DPLL 0", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL0, }, { .name = "DPLL 1", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL1, }, - { .name = "TBT PLL", .funcs = &tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, + { .name = "TBT PLL", .funcs = &icl_tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, .is_alt_port_dpll = true, }, { .name = "MG PLL 1", .funcs = &mg_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, }, { .name = "MG PLL 2", .funcs = &mg_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, }, @@ -4207,7 +4207,7 @@ static const struct intel_dpll_funcs dkl_pll_funcs = { static const struct dpll_info tgl_plls[] = { { .name = "DPLL 0", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL0, }, { .name = "DPLL 1", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL1, }, - { .name = "TBT PLL", .funcs = &tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, + { .name = "TBT PLL", .funcs = &icl_tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, .is_alt_port_dpll = true, }, { .name = "TC PLL 1", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, }, { .name = "TC PLL 2", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, }, @@ -4285,7 +4285,7 @@ static const struct intel_dpll_mgr adls_pll_mgr = { static const struct dpll_info adlp_plls[] = { { .name = "DPLL 0", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL0, }, { .name = "DPLL 1", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL1, }, - { .name = "TBT PLL", .funcs = &tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, + { .name = "TBT PLL", .funcs = &icl_tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, .is_alt_port_dpll = true, }, { .name = "TC PLL 1", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, }, { .name = "TC PLL 2", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, }, From dca0eb029f5770e18308db966cdeec4bb4b5a659 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:32 +0200 Subject: [PATCH 0014/1610] drm/i915/cx0: Factor out C10 msgbus access start/end helpers Factor out functions to begin and complete C10 PHY programming sequences to make the code more concise. v2: Rename msgbus_update_config() to more descriptive msg_bus_access_commit() (Jani) Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-3-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 62 +++++++++++--------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index d98b4cf6b60e..e130c96d0018 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -444,6 +444,31 @@ static u8 intel_c10_get_tx_term_ctl(const struct intel_crtc_state *crtc_state) } } +static void intel_c10_msgbus_access_begin(struct intel_encoder *encoder, + u8 lane_mask) +{ + if (!intel_encoder_is_c10phy(encoder)) + return; + + intel_cx0_rmw(encoder, lane_mask, PHY_C10_VDR_CONTROL(1), + 0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED); +} + +static void intel_c10_msgbus_access_commit(struct intel_encoder *encoder, + u8 lane_mask, bool master_lane) +{ + u8 val = C10_VDR_CTRL_UPDATE_CFG; + + if (!intel_encoder_is_c10phy(encoder)) + return; + + if (master_lane) + val |= C10_VDR_CTRL_MASTER_LANE; + + intel_cx0_rmw(encoder, lane_mask, PHY_C10_VDR_CONTROL(1), + 0, val, MB_WRITE_COMMITTED); +} + void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { @@ -467,9 +492,9 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, return; } + intel_c10_msgbus_access_begin(encoder, owned_lane_mask); + if (intel_encoder_is_c10phy(encoder)) { - intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CONTROL(1), - 0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED); intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CMN(3), C10_CMN3_TXVBOOST_MASK, C10_CMN3_TXVBOOST(intel_c10_get_tx_vboost_lvl(crtc_state)), @@ -508,9 +533,7 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, 0, PHY_C10_VDR_OVRD_TX1 | PHY_C10_VDR_OVRD_TX2, MB_WRITE_COMMITTED); - if (intel_encoder_is_c10phy(encoder)) - intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CONTROL(1), - 0, C10_VDR_CTRL_UPDATE_CFG, MB_WRITE_COMMITTED); + intel_c10_msgbus_access_commit(encoder, owned_lane_mask, false); intel_cx0_phy_transaction_end(encoder, wakeref); } @@ -2114,9 +2137,7 @@ static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, * According to C10 VDR Register programming Sequence we need * to do this to read PHY internal registers from MsgBus. */ - intel_cx0_rmw(encoder, lane, PHY_C10_VDR_CONTROL(1), - 0, C10_VDR_CTRL_MSGBUS_ACCESS, - MB_WRITE_COMMITTED); + intel_c10_msgbus_access_begin(encoder, lane); for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++) pll_state->pll[i] = intel_cx0_read(encoder, lane, PHY_C10_VDR_PLL(i)); @@ -2135,9 +2156,7 @@ static void intel_c10_pll_program(struct intel_display *display, { int i; - intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1), - 0, C10_VDR_CTRL_MSGBUS_ACCESS, - MB_WRITE_COMMITTED); + intel_c10_msgbus_access_begin(encoder, INTEL_CX0_BOTH_LANES); /* Program the pll values only for the master lane */ for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++) @@ -2152,9 +2171,8 @@ static void intel_c10_pll_program(struct intel_display *display, intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CUSTOM_WIDTH, C10_VDR_CUSTOM_WIDTH_MASK, C10_VDR_CUSTOM_WIDTH_8_10, MB_WRITE_COMMITTED); - intel_cx0_rmw(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_CONTROL(1), - 0, C10_VDR_CTRL_MASTER_LANE | C10_VDR_CTRL_UPDATE_CFG, - MB_WRITE_COMMITTED); + + intel_c10_msgbus_access_commit(encoder, INTEL_CX0_LANE0, true); } static void intel_c10pll_dump_hw_state(struct intel_display *display, @@ -2938,11 +2956,7 @@ static void intel_cx0_program_phy_lane(struct intel_encoder *encoder, int lane_c bool dp_alt_mode = intel_tc_port_in_dp_alt_mode(enc_to_dig_port(encoder)); u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder); - if (intel_encoder_is_c10phy(encoder)) - intel_cx0_rmw(encoder, owned_lane_mask, - PHY_C10_VDR_CONTROL(1), 0, - C10_VDR_CTRL_MSGBUS_ACCESS, - MB_WRITE_COMMITTED); + intel_c10_msgbus_access_begin(encoder, owned_lane_mask); if (lane_reversal) disables = REG_GENMASK8(3, 0) >> lane_count; @@ -2967,11 +2981,7 @@ static void intel_cx0_program_phy_lane(struct intel_encoder *encoder, int lane_c MB_WRITE_COMMITTED); } - if (intel_encoder_is_c10phy(encoder)) - intel_cx0_rmw(encoder, owned_lane_mask, - PHY_C10_VDR_CONTROL(1), 0, - C10_VDR_CTRL_UPDATE_CFG, - MB_WRITE_COMMITTED); + intel_c10_msgbus_access_commit(encoder, owned_lane_mask, false); } static u32 intel_cx0_get_pclk_pll_request(u8 lane_mask) @@ -3236,9 +3246,7 @@ void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder, wakeref = intel_cx0_phy_transaction_begin(encoder); - if (intel_encoder_is_c10phy(encoder)) - intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CONTROL(1), 0, - C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED); + intel_c10_msgbus_access_begin(encoder, owned_lane_mask); for (i = 0; i < 4; i++) { int tx = i % 2 + 1; From 1cefc3ac7d8451cebcfce209c53933fb6309e4e5 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:33 +0200 Subject: [PATCH 0015/1610] drm/i915/cx0: Sanitize setting the Cx0 PLL use_c10 flag Sanitize setting the Cx0 PLL use_c10 flag during state computation and HW readout, making sure they happen the same way in the intel_c{10,20}pll_calc_state() and intel_c{10,20}pll_readout_hw_state() functions. Follow-up changes will add more state computation/HW readout, this change prepares for those as well. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-4-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 23 ++++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index e130c96d0018..93b18dc49ee5 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2125,12 +2125,15 @@ static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder, const struct intel_c10pll_state *pll_state); static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, - struct intel_c10pll_state *pll_state) + struct intel_cx0pll_state *cx0pll_state) { + struct intel_c10pll_state *pll_state = &cx0pll_state->c10; u8 lane = INTEL_CX0_LANE0; intel_wakeref_t wakeref; int i; + cx0pll_state->use_c10 = true; + wakeref = intel_cx0_phy_transaction_begin(encoder); /* @@ -2356,6 +2359,8 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, const struct intel_c20pll_state * const *tables; int i; + crtc_state->dpll_hw_state.cx0pll.use_c10 = false; + /* try computed C20 HDMI tables before using consolidated tables */ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { if (intel_c20_compute_hdmi_tmds_pll(crtc_state) == 0) @@ -2372,7 +2377,6 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, intel_cx0pll_update_ssc(encoder, &crtc_state->dpll_hw_state.cx0pll, intel_crtc_has_dp_encoder(crtc_state)); - crtc_state->dpll_hw_state.cx0pll.use_c10 = false; return 0; } } @@ -2439,13 +2443,16 @@ static int intel_c20pll_calc_port_clock(struct intel_encoder *encoder, } static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, - struct intel_c20pll_state *pll_state) + struct intel_cx0pll_state *cx0pll_state) { + struct intel_c20pll_state *pll_state = &cx0pll_state->c20; struct intel_display *display = to_intel_display(encoder); bool cntx; intel_wakeref_t wakeref; int i; + cx0pll_state->use_c10 = false; + wakeref = intel_cx0_phy_transaction_begin(encoder); /* 1. Read current context selection */ @@ -3444,12 +3451,10 @@ void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, if (pll_state->tbt_mode) return; - if (intel_encoder_is_c10phy(encoder)) { - intel_c10pll_readout_hw_state(encoder, &pll_state->c10); - pll_state->use_c10 = true; - } else { - intel_c20pll_readout_hw_state(encoder, &pll_state->c20); - } + if (intel_encoder_is_c10phy(encoder)) + intel_c10pll_readout_hw_state(encoder, pll_state); + else + intel_c20pll_readout_hw_state(encoder, pll_state); } static bool mtl_compare_hw_state_c10(const struct intel_c10pll_state *a, From 5050d4a0af1e3b4970adf321f4a9296fe2ac532f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:34 +0200 Subject: [PATCH 0016/1610] drm/i915/cx0: Sanitize calculating C20 PLL state from tables A follow up change adds a computation for the C20 PLL VDR state, which is common to both the HDMI algorithmic and DP/HDMI table based method. To prepare for that streamline the code. The C10 counterpart would benefit from the same change, leave that for later adding a TODO comment. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-5-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 68 ++++++++++++++------ 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 93b18dc49ee5..a1f2272fed14 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2072,6 +2072,10 @@ static void intel_c10pll_update_pll(struct intel_encoder *encoder, pll_state->c10.pll[i] = 0; } +/* + * TODO: Convert the following to align with intel_c20pll_find_table() and + * intel_c20pll_calc_state_from_table(). + */ static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder, const struct intel_c10pll_state * const *tables, bool is_dp, int port_clock, @@ -2325,7 +2329,7 @@ static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state) } static const struct intel_c20pll_state * const * -intel_c20_pll_tables_get(struct intel_crtc_state *crtc_state, +intel_c20_pll_tables_get(const struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(crtc_state); @@ -2353,35 +2357,57 @@ intel_c20_pll_tables_get(struct intel_crtc_state *crtc_state, return NULL; } -static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +static const struct intel_c20pll_state * +intel_c20_pll_find_table(const struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder) { const struct intel_c20pll_state * const *tables; int i; + tables = intel_c20_pll_tables_get(crtc_state, encoder); + if (!tables) + return NULL; + + for (i = 0; tables[i]; i++) + if (crtc_state->port_clock == tables[i]->clock) + return tables[i]; + + return NULL; +} + +static int intel_c20pll_calc_state_from_table(struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder) +{ + const struct intel_c20pll_state *table; + + table = intel_c20_pll_find_table(crtc_state, encoder); + if (!table) + return -EINVAL; + + crtc_state->dpll_hw_state.cx0pll.c20 = *table; + + intel_cx0pll_update_ssc(encoder, &crtc_state->dpll_hw_state.cx0pll, + intel_crtc_has_dp_encoder(crtc_state)); + + return 0; +} + +static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder) +{ + int err = -ENOENT; + crtc_state->dpll_hw_state.cx0pll.use_c10 = false; /* try computed C20 HDMI tables before using consolidated tables */ - if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { - if (intel_c20_compute_hdmi_tmds_pll(crtc_state) == 0) - return 0; - } + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) + /* TODO: Update SSC state for HDMI as well */ + err = intel_c20_compute_hdmi_tmds_pll(crtc_state); - tables = intel_c20_pll_tables_get(crtc_state, encoder); - if (!tables) - return -EINVAL; + if (err) + err = intel_c20pll_calc_state_from_table(crtc_state, encoder); - for (i = 0; tables[i]; i++) { - if (crtc_state->port_clock == tables[i]->clock) { - crtc_state->dpll_hw_state.cx0pll.c20 = *tables[i]; - intel_cx0pll_update_ssc(encoder, - &crtc_state->dpll_hw_state.cx0pll, - intel_crtc_has_dp_encoder(crtc_state)); - return 0; - } - } - - return -EINVAL; + return err; } int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, From 201c902870ec7b4141e4f403612a289701fafb80 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:35 +0200 Subject: [PATCH 0017/1610] drm/i915/cx0: Track the C20 PHY VDR state in the PLL state The Cx0 PLL enable programming needs to know if the PLL is in DP or HDMI mode. The PLL manager framework doesn't pass the CRTC state to the PLL's enable hook, so prepare here for the conversion to use the PLL manager for Cx0 PHY PLLs by tracking the DP/HDMI mode in the PLL state. This change has the advantage, that the VDR HW/SW state can be verified now. A follow up change will convert the PLL enable function to retrieve the DP/HDMI mode parameter from the PLL state. This also allows dropping the is_dp and port clock params from the intel_c20_pll_program() function, since it can retrieve these now from the PLL state. v2: Fix comment to under same multicomment line (Suraj) Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-6-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 119 +++++++++++++----- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 5 + 2 files changed, 92 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index a1f2272fed14..fd0409565c68 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2357,6 +2357,75 @@ intel_c20_pll_tables_get(const struct intel_crtc_state *crtc_state, return NULL; } +static u8 intel_c20_get_dp_rate(u32 clock); +static u8 intel_c20_get_hdmi_rate(u32 clock); +static int intel_get_c20_custom_width(u32 clock, bool dp); + +static void intel_c20_calc_vdr_params(struct intel_c20pll_vdr_state *vdr, bool is_dp, + int port_clock) +{ + vdr->custom_width = intel_get_c20_custom_width(port_clock, is_dp); + + vdr->serdes_rate = 0; + vdr->hdmi_rate = 0; + + if (is_dp) { + vdr->serdes_rate = PHY_C20_IS_DP | + PHY_C20_DP_RATE(intel_c20_get_dp_rate(port_clock)); + } else { + if (intel_hdmi_is_frl(port_clock)) + vdr->serdes_rate = PHY_C20_IS_HDMI_FRL; + + vdr->hdmi_rate = intel_c20_get_hdmi_rate(port_clock); + } +} + +#define PHY_C20_SERDES_RATE_MASK (PHY_C20_IS_DP | PHY_C20_DP_RATE_MASK | PHY_C20_IS_HDMI_FRL) + +static void intel_c20_readout_vdr_params(struct intel_encoder *encoder, + struct intel_c20pll_vdr_state *vdr, bool *cntx) +{ + u8 serdes; + + serdes = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE); + *cntx = serdes & PHY_C20_CONTEXT_TOGGLE; + + vdr->custom_width = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_WIDTH) & + PHY_C20_CUSTOM_WIDTH_MASK; + + vdr->serdes_rate = serdes & PHY_C20_SERDES_RATE_MASK; + if (!(vdr->serdes_rate & PHY_C20_IS_DP)) + vdr->hdmi_rate = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_HDMI_RATE) & + PHY_C20_HDMI_RATE_MASK; + else + vdr->hdmi_rate = 0; +} + +static void intel_c20_program_vdr_params(struct intel_encoder *encoder, + const struct intel_c20pll_vdr_state *vdr, + u8 owned_lane_mask) +{ + struct intel_display *display = to_intel_display(encoder); + + drm_WARN_ON(display->drm, vdr->custom_width & ~PHY_C20_CUSTOM_WIDTH_MASK); + intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_WIDTH, + PHY_C20_CUSTOM_WIDTH_MASK, vdr->custom_width, + MB_WRITE_COMMITTED); + + drm_WARN_ON(display->drm, vdr->serdes_rate & ~PHY_C20_SERDES_RATE_MASK); + intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE, + PHY_C20_SERDES_RATE_MASK, vdr->serdes_rate, + MB_WRITE_COMMITTED); + + if (vdr->serdes_rate & PHY_C20_IS_DP) + return; + + drm_WARN_ON(display->drm, vdr->hdmi_rate & ~PHY_C20_HDMI_RATE_MASK); + intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C20_VDR_HDMI_RATE, + PHY_C20_HDMI_RATE_MASK, vdr->hdmi_rate, + MB_WRITE_COMMITTED); +} + static const struct intel_c20pll_state * intel_c20_pll_find_table(const struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) @@ -2395,19 +2464,26 @@ static int intel_c20pll_calc_state_from_table(struct intel_crtc_state *crtc_stat static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { + bool is_dp = intel_crtc_has_dp_encoder(crtc_state); int err = -ENOENT; crtc_state->dpll_hw_state.cx0pll.use_c10 = false; /* try computed C20 HDMI tables before using consolidated tables */ - if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) + if (!is_dp) /* TODO: Update SSC state for HDMI as well */ err = intel_c20_compute_hdmi_tmds_pll(crtc_state); if (err) err = intel_c20pll_calc_state_from_table(crtc_state, encoder); - return err; + if (err) + return err; + + intel_c20_calc_vdr_params(&crtc_state->dpll_hw_state.cx0pll.c20.vdr, + is_dp, crtc_state->port_clock); + + return 0; } int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, @@ -2481,8 +2557,8 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, wakeref = intel_cx0_phy_transaction_begin(encoder); - /* 1. Read current context selection */ - cntx = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & PHY_C20_CONTEXT_TOGGLE; + /* 1. Read VDR params and current context selection */ + intel_c20_readout_vdr_params(encoder, &pll_state->vdr, &cntx); /* Read Tx configuration */ for (i = 0; i < ARRAY_SIZE(pll_state->tx); i++) { @@ -2657,11 +2733,9 @@ static int intel_get_c20_custom_width(u32 clock, bool dp) static void intel_c20_pll_program(struct intel_display *display, struct intel_encoder *encoder, - const struct intel_c20pll_state *pll_state, - bool is_dp, int port_clock) + const struct intel_c20pll_state *pll_state) { u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder); - u8 serdes; bool cntx; int i; @@ -2730,30 +2804,11 @@ static void intel_c20_pll_program(struct intel_display *display, } } - /* 4. Program custom width to match the link protocol */ - intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_WIDTH, - PHY_C20_CUSTOM_WIDTH_MASK, - PHY_C20_CUSTOM_WIDTH(intel_get_c20_custom_width(port_clock, is_dp)), - MB_WRITE_COMMITTED); - - /* 5. For DP or 6. For HDMI */ - serdes = 0; - if (is_dp) - serdes = PHY_C20_IS_DP | - PHY_C20_DP_RATE(intel_c20_get_dp_rate(port_clock)); - else if (intel_hdmi_is_frl(port_clock)) - serdes = PHY_C20_IS_HDMI_FRL; - - intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE, - PHY_C20_IS_DP | PHY_C20_DP_RATE_MASK | PHY_C20_IS_HDMI_FRL, - serdes, - MB_WRITE_COMMITTED); - - if (!is_dp) - intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C20_VDR_HDMI_RATE, - PHY_C20_HDMI_RATE_MASK, - intel_c20_get_hdmi_rate(port_clock), - MB_WRITE_COMMITTED); + /* + * 4. Program custom width to match the link protocol. + * 5. For DP or 6. For HDMI + */ + intel_c20_program_vdr_params(encoder, &pll_state->vdr, owned_lane_mask); /* * 7. Write Vendor specific registers to toggle context setting to load @@ -3077,7 +3132,7 @@ static void __intel_cx0pll_enable(struct intel_encoder *encoder, if (intel_encoder_is_c10phy(encoder)) intel_c10_pll_program(display, encoder, &pll_state->c10); else - intel_c20_pll_program(display, encoder, &pll_state->c20, is_dp, port_clock); + intel_c20_pll_program(display, encoder, &pll_state->c20); /* * 6. Program the enabled and disabled owned PHY lane diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index 6183da90b28d..a0238a3e7288 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -255,6 +255,11 @@ struct intel_c20pll_state { u16 mplla[10]; u16 mpllb[11]; }; + struct intel_c20pll_vdr_state { + u8 custom_width; + u8 serdes_rate; + u8 hdmi_rate; + } vdr; }; struct intel_cx0pll_state { From 7c3342213a8b73f3100e3462074f5ded4fd9d675 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:36 +0200 Subject: [PATCH 0018/1610] drm/i915/cx0: Move definition of Cx0 PHY functions earlier Move the definitions of the intel_c10pll_calc_port_clock() intel_c20_get_dp_rate() intel_c20_get_hdmi_rate() is_hdmi_frl() is_dp2() intel_get_c20_custom_width() functions earlier to avoid the forward declarations. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-7-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 203 +++++++++---------- 1 file changed, 98 insertions(+), 105 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index fd0409565c68..9515157ee6b3 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2126,7 +2126,31 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, } static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder, - const struct intel_c10pll_state *pll_state); + const struct intel_c10pll_state *pll_state) +{ + unsigned int frac_quot = 0, frac_rem = 0, frac_den = 1; + unsigned int multiplier, tx_clk_div, hdmi_div, refclk = 38400; + int tmpclk = 0; + + if (pll_state->pll[0] & C10_PLL0_FRACEN) { + frac_quot = pll_state->pll[12] << 8 | pll_state->pll[11]; + frac_rem = pll_state->pll[14] << 8 | pll_state->pll[13]; + frac_den = pll_state->pll[10] << 8 | pll_state->pll[9]; + } + + multiplier = (REG_FIELD_GET8(C10_PLL3_MULTIPLIERH_MASK, pll_state->pll[3]) << 8 | + pll_state->pll[2]) / 2 + 16; + + tx_clk_div = REG_FIELD_GET8(C10_PLL15_TXCLKDIV_MASK, pll_state->pll[15]); + hdmi_div = REG_FIELD_GET8(C10_PLL15_HDMIDIV_MASK, pll_state->pll[15]); + + tmpclk = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, (multiplier << 16) + frac_quot) + + DIV_ROUND_CLOSEST(refclk * frac_rem, frac_den), + 10 << (tx_clk_div + 16)); + tmpclk *= (hdmi_div ? 2 : 1); + + return tmpclk; +} static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *cx0pll_state) @@ -2357,9 +2381,79 @@ intel_c20_pll_tables_get(const struct intel_crtc_state *crtc_state, return NULL; } -static u8 intel_c20_get_dp_rate(u32 clock); -static u8 intel_c20_get_hdmi_rate(u32 clock); -static int intel_get_c20_custom_width(u32 clock, bool dp); +static u8 intel_c20_get_dp_rate(u32 clock) +{ + switch (clock) { + case 162000: /* 1.62 Gbps DP1.4 */ + return 0; + case 270000: /* 2.7 Gbps DP1.4 */ + return 1; + case 540000: /* 5.4 Gbps DP 1.4 */ + return 2; + case 810000: /* 8.1 Gbps DP1.4 */ + return 3; + case 216000: /* 2.16 Gbps eDP */ + return 4; + case 243000: /* 2.43 Gbps eDP */ + return 5; + case 324000: /* 3.24 Gbps eDP */ + return 6; + case 432000: /* 4.32 Gbps eDP */ + return 7; + case 1000000: /* 10 Gbps DP2.0 */ + return 8; + case 1350000: /* 13.5 Gbps DP2.0 */ + return 9; + case 2000000: /* 20 Gbps DP2.0 */ + return 10; + case 648000: /* 6.48 Gbps eDP*/ + return 11; + case 675000: /* 6.75 Gbps eDP*/ + return 12; + default: + MISSING_CASE(clock); + return 0; + } +} + +static u8 intel_c20_get_hdmi_rate(u32 clock) +{ + if (clock >= 25175 && clock <= 600000) + return 0; + + switch (clock) { + case 300000: /* 3 Gbps */ + case 600000: /* 6 Gbps */ + case 1200000: /* 12 Gbps */ + return 1; + case 800000: /* 8 Gbps */ + return 2; + case 1000000: /* 10 Gbps */ + return 3; + default: + MISSING_CASE(clock); + return 0; + } +} + +static bool is_dp2(u32 clock) +{ + /* DP2.0 clock rates */ + if (clock == 1000000 || clock == 1350000 || clock == 2000000) + return true; + + return false; +} + +static int intel_get_c20_custom_width(u32 clock, bool dp) +{ + if (dp && is_dp2(clock)) + return 2; + else if (intel_hdmi_is_frl(clock)) + return 1; + else + return 0; +} static void intel_c20_calc_vdr_params(struct intel_c20pll_vdr_state *vdr, bool is_dp, int port_clock) @@ -2648,70 +2742,6 @@ void intel_cx0pll_dump_hw_state(struct intel_display *display, intel_c20pll_dump_hw_state(display, &hw_state->c20); } -static u8 intel_c20_get_dp_rate(u32 clock) -{ - switch (clock) { - case 162000: /* 1.62 Gbps DP1.4 */ - return 0; - case 270000: /* 2.7 Gbps DP1.4 */ - return 1; - case 540000: /* 5.4 Gbps DP 1.4 */ - return 2; - case 810000: /* 8.1 Gbps DP1.4 */ - return 3; - case 216000: /* 2.16 Gbps eDP */ - return 4; - case 243000: /* 2.43 Gbps eDP */ - return 5; - case 324000: /* 3.24 Gbps eDP */ - return 6; - case 432000: /* 4.32 Gbps eDP */ - return 7; - case 1000000: /* 10 Gbps DP2.0 */ - return 8; - case 1350000: /* 13.5 Gbps DP2.0 */ - return 9; - case 2000000: /* 20 Gbps DP2.0 */ - return 10; - case 648000: /* 6.48 Gbps eDP*/ - return 11; - case 675000: /* 6.75 Gbps eDP*/ - return 12; - default: - MISSING_CASE(clock); - return 0; - } -} - -static u8 intel_c20_get_hdmi_rate(u32 clock) -{ - if (clock >= 25175 && clock <= 600000) - return 0; - - switch (clock) { - case 300000: /* 3 Gbps */ - case 600000: /* 6 Gbps */ - case 1200000: /* 12 Gbps */ - return 1; - case 800000: /* 8 Gbps */ - return 2; - case 1000000: /* 10 Gbps */ - return 3; - default: - MISSING_CASE(clock); - return 0; - } -} - -static bool is_dp2(u32 clock) -{ - /* DP2.0 clock rates */ - if (clock == 1000000 || clock == 1350000 || clock == 2000000) - return true; - - return false; -} - static bool intel_c20_protocol_switch_valid(struct intel_encoder *encoder) { struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); @@ -2721,16 +2751,6 @@ static bool intel_c20_protocol_switch_valid(struct intel_encoder *encoder) return intel_tc_port_in_legacy_mode(intel_dig_port); } -static int intel_get_c20_custom_width(u32 clock, bool dp) -{ - if (dp && is_dp2(clock)) - return 2; - else if (intel_hdmi_is_frl(clock)) - return 1; - else - return 0; -} - static void intel_c20_pll_program(struct intel_display *display, struct intel_encoder *encoder, const struct intel_c20pll_state *pll_state) @@ -2819,33 +2839,6 @@ static void intel_c20_pll_program(struct intel_display *display, MB_WRITE_COMMITTED); } -static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder, - const struct intel_c10pll_state *pll_state) -{ - unsigned int frac_quot = 0, frac_rem = 0, frac_den = 1; - unsigned int multiplier, tx_clk_div, hdmi_div, refclk = 38400; - int tmpclk = 0; - - if (pll_state->pll[0] & C10_PLL0_FRACEN) { - frac_quot = pll_state->pll[12] << 8 | pll_state->pll[11]; - frac_rem = pll_state->pll[14] << 8 | pll_state->pll[13]; - frac_den = pll_state->pll[10] << 8 | pll_state->pll[9]; - } - - multiplier = (REG_FIELD_GET8(C10_PLL3_MULTIPLIERH_MASK, pll_state->pll[3]) << 8 | - pll_state->pll[2]) / 2 + 16; - - tx_clk_div = REG_FIELD_GET8(C10_PLL15_TXCLKDIV_MASK, pll_state->pll[15]); - hdmi_div = REG_FIELD_GET8(C10_PLL15_HDMIDIV_MASK, pll_state->pll[15]); - - tmpclk = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, (multiplier << 16) + frac_quot) + - DIV_ROUND_CLOSEST(refclk * frac_rem, frac_den), - 10 << (tx_clk_div + 16)); - tmpclk *= (hdmi_div ? 2 : 1); - - return tmpclk; -} - static void intel_program_port_clock_ctl(struct intel_encoder *encoder, const struct intel_cx0pll_state *pll_state, bool is_dp, int port_clock, From 4f8b1e08c28945427a46b98144c20c22d0578885 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:37 +0200 Subject: [PATCH 0019/1610] drm/i915/cx0: Add macro to get DDI port width from a register value A follow-up change will need to retrieve the DDI port field from the register value, add a macro for this. Make things symmetric with setting the field in the register. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-8-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_display_regs.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h index 9d71e26a4fa2..c14d3caa73a7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_regs.h +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h @@ -2349,8 +2349,13 @@ enum skl_power_gate { #define DDI_BUF_CTL_TC_PHY_OWNERSHIP REG_BIT(6) #define DDI_A_4_LANES REG_BIT(4) #define DDI_PORT_WIDTH_MASK REG_GENMASK(3, 1) +#define DDI_PORT_WIDTH_ENCODE(width) ((width) == 3 ? 4 : (width) - 1) +#define DDI_PORT_WIDTH_DECODE(regval) ((regval) == 4 ? 3 : (regval) + 1) #define DDI_PORT_WIDTH(width) REG_FIELD_PREP(DDI_PORT_WIDTH_MASK, \ - ((width) == 3 ? 4 : (width) - 1)) + DDI_PORT_WIDTH_ENCODE(width)) +#define DDI_PORT_WIDTH_GET(regval) DDI_PORT_WIDTH_DECODE(REG_FIELD_GET(DDI_PORT_WIDTH_MASK, \ + (regval))) + #define DDI_PORT_WIDTH_SHIFT 1 #define DDI_INIT_DISPLAY_DETECTED REG_BIT(0) From 230d4c748113d83931a5b57c844fb71faf9eebe3 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:38 +0200 Subject: [PATCH 0020/1610] drm/i915/cx0: Track the Cx0 PHY enabled lane count in the PLL state The Cx0 PLL enable programming requires the enabled lane count. The PLL manager framework doesn't pass the CRTC state to the PLL's enable hook, so prepare here for the conversion to use the PLL manager, by tracking the enabled lane count in the PLL state as well. This has the advantage, that the enabled lane count can be verified against the PHY/PLL's enabled TX lanes. This also allows dropping the lane count param from the __intel_cx0pll_enable() function, since it can retrieve this now from the PLL state. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-9-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 55 ++++++++++++++++--- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 1 + 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 9515157ee6b3..2ab93d02fdf1 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -11,6 +11,7 @@ #include "intel_alpm.h" #include "intel_cx0_phy.h" #include "intel_cx0_phy_regs.h" +#include "intel_display_regs.h" #include "intel_ddi.h" #include "intel_ddi_buf_trans.h" #include "intel_de.h" @@ -2078,7 +2079,7 @@ static void intel_c10pll_update_pll(struct intel_encoder *encoder, */ static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder, const struct intel_c10pll_state * const *tables, - bool is_dp, int port_clock, + bool is_dp, int port_clock, int lane_count, struct intel_cx0pll_state *pll_state) { int i; @@ -2088,7 +2089,9 @@ static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder, pll_state->c10 = *tables[i]; intel_cx0pll_update_ssc(encoder, pll_state, is_dp); intel_c10pll_update_pll(encoder, pll_state); + pll_state->use_c10 = true; + pll_state->lane_count = lane_count; return 0; } @@ -2109,7 +2112,7 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, err = intel_c10pll_calc_state_from_table(encoder, tables, intel_crtc_has_dp_encoder(crtc_state), - crtc_state->port_clock, + crtc_state->port_clock, crtc_state->lane_count, &crtc_state->dpll_hw_state.cx0pll); if (err == 0 || !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) @@ -2121,6 +2124,7 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, intel_c10pll_update_pll(encoder, &crtc_state->dpll_hw_state.cx0pll); crtc_state->dpll_hw_state.cx0pll.use_c10 = true; + crtc_state->dpll_hw_state.cx0pll.lane_count = crtc_state->lane_count; return 0; } @@ -2152,6 +2156,37 @@ static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder, return tmpclk; } +static int readout_enabled_lane_count(struct intel_encoder *encoder) +{ + struct intel_display *display = to_intel_display(encoder); + u8 enabled_tx_lane_count = 0; + int max_tx_lane_count; + int tx_lane; + + /* + * TODO: also check inactive TX lanes in all PHY lanes owned by the + * display. For now checking only those PHY lane(s) which are owned + * based on the active TX lane count (i.e. + * 1,2 active TX lanes -> PHY lane#0 + * 3,4 active TX lanes -> PHY lane#0 and PHY lane#1). + */ + max_tx_lane_count = DDI_PORT_WIDTH_GET(intel_de_read(display, DDI_BUF_CTL(encoder->port))); + if (!drm_WARN_ON(display->drm, max_tx_lane_count == 0)) + max_tx_lane_count = roundup_pow_of_two(max_tx_lane_count); + + for (tx_lane = 0; tx_lane < max_tx_lane_count; tx_lane++) { + u8 phy_lane_mask = tx_lane < 2 ? INTEL_CX0_LANE0 : INTEL_CX0_LANE1; + int tx = tx_lane % 2 + 1; + u8 val; + + val = intel_cx0_read(encoder, phy_lane_mask, PHY_CX0_TX_CONTROL(tx, 2)); + if (!(val & CONTROL2_DISABLE_SINGLE_TX)) + enabled_tx_lane_count++; + } + + return enabled_tx_lane_count; +} + static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *cx0pll_state) { @@ -2170,6 +2205,8 @@ static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, */ intel_c10_msgbus_access_begin(encoder, lane); + cx0pll_state->lane_count = readout_enabled_lane_count(encoder); + for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++) pll_state->pll[i] = intel_cx0_read(encoder, lane, PHY_C10_VDR_PLL(i)); @@ -2562,6 +2599,7 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, int err = -ENOENT; crtc_state->dpll_hw_state.cx0pll.use_c10 = false; + crtc_state->dpll_hw_state.cx0pll.lane_count = crtc_state->lane_count; /* try computed C20 HDMI tables before using consolidated tables */ if (!is_dp) @@ -2651,6 +2689,8 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, wakeref = intel_cx0_phy_transaction_begin(encoder); + cx0pll_state->lane_count = readout_enabled_lane_count(encoder); + /* 1. Read VDR params and current context selection */ intel_c20_readout_vdr_params(encoder, &pll_state->vdr, &cntx); @@ -3089,7 +3129,7 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask) static void __intel_cx0pll_enable(struct intel_encoder *encoder, const struct intel_cx0pll_state *pll_state, - bool is_dp, int port_clock, int lane_count) + bool is_dp, int port_clock) { struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); @@ -3131,7 +3171,7 @@ static void __intel_cx0pll_enable(struct intel_encoder *encoder, * 6. Program the enabled and disabled owned PHY lane * transmitters over message bus */ - intel_cx0_program_phy_lane(encoder, lane_count, lane_reversal); + intel_cx0_program_phy_lane(encoder, pll_state->lane_count, lane_reversal); /* * 7. Follow the Display Voltage Frequency Switching - Sequence @@ -3174,7 +3214,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder, { __intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll, intel_crtc_has_dp_encoder(crtc_state), - crtc_state->port_clock, crtc_state->lane_count); + crtc_state->port_clock); } int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder) @@ -3700,6 +3740,7 @@ void intel_cx0_pll_power_save_wa(struct intel_display *display) for_each_intel_encoder(display->drm, encoder) { struct intel_cx0pll_state pll_state = {}; int port_clock = 162000; + int lane_count = 4; if (!intel_encoder_is_dig_port(encoder)) continue; @@ -3712,7 +3753,7 @@ void intel_cx0_pll_power_save_wa(struct intel_display *display) if (intel_c10pll_calc_state_from_table(encoder, mtl_c10_edp_tables, - true, port_clock, + true, port_clock, lane_count, &pll_state) < 0) { drm_WARN_ON(display->drm, "Unable to calc C10 state from the tables\n"); @@ -3723,7 +3764,7 @@ void intel_cx0_pll_power_save_wa(struct intel_display *display) "[ENCODER:%d:%s] Applying power saving workaround on disabled PLL\n", encoder->base.base.id, encoder->base.name); - __intel_cx0pll_enable(encoder, &pll_state, true, port_clock, 4); + __intel_cx0pll_enable(encoder, &pll_state, true, port_clock); intel_cx0pll_disable(encoder); } } diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index a0238a3e7288..a7946ff13cb6 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -267,6 +267,7 @@ struct intel_cx0pll_state { struct intel_c10pll_state c10; struct intel_c20pll_state c20; }; + int lane_count; bool ssc_enabled; bool use_c10; bool tbt_mode; From 5df82b17928b8f14d7167a5e199b4cb58bfe39e1 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:39 +0200 Subject: [PATCH 0021/1610] drm/i915/cx0: Sanitize C10 PHY PLL SSC register setup Define the C10 PLL SSC register range via macros, so the HW/SW state of these register can be verified by a follow-up change, reusing these macros. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-10-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 2ab93d02fdf1..f190762e4871 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2059,6 +2059,9 @@ static void intel_cx0pll_update_ssc(struct intel_encoder *encoder, } } +#define C10_PLL_SSC_REG_START_IDX 4 +#define C10_PLL_SSC_REG_COUNT 5 + static void intel_c10pll_update_pll(struct intel_encoder *encoder, struct intel_cx0pll_state *pll_state) { @@ -2068,8 +2071,11 @@ static void intel_c10pll_update_pll(struct intel_encoder *encoder, if (pll_state->ssc_enabled) return; - drm_WARN_ON(display->drm, ARRAY_SIZE(pll_state->c10.pll) < 9); - for (i = 4; i < 9; i++) + drm_WARN_ON(display->drm, ARRAY_SIZE(pll_state->c10.pll) < + C10_PLL_SSC_REG_START_IDX + C10_PLL_SSC_REG_COUNT); + for (i = C10_PLL_SSC_REG_START_IDX; + i < C10_PLL_SSC_REG_START_IDX + C10_PLL_SSC_REG_COUNT; + i++) pll_state->c10.pll[i] = 0; } From 8ad92b0733030841d5a728178f5c8a6f2c3e8f78 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:40 +0200 Subject: [PATCH 0022/1610] drm/i915/cx0: Read out the Cx0 PHY SSC enabled state Read out the C10, C20 PHY PLLs SSC enabled state, so the PLL HW/SW state verification can check this state as well. C10 PHY PLLs program some PLL registers zeroed out for the non-SSC case, while programming non-zero values to the same registers for the SSC case, so check that these PLL registers being zero or non-zero matches the PLL's overall SSC-enabled state (stored in the intel_c10pll_state::ssc_enabled flag). Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-11-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 25 ++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index f190762e4871..4562e47042d2 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2062,6 +2062,12 @@ static void intel_cx0pll_update_ssc(struct intel_encoder *encoder, #define C10_PLL_SSC_REG_START_IDX 4 #define C10_PLL_SSC_REG_COUNT 5 +static bool intel_c10pll_ssc_enabled(const struct intel_c10pll_state *pll_state) +{ + return memchr_inv(&pll_state->pll[C10_PLL_SSC_REG_START_IDX], + 0, sizeof(pll_state->pll[0]) * C10_PLL_SSC_REG_COUNT); +} + static void intel_c10pll_update_pll(struct intel_encoder *encoder, struct intel_cx0pll_state *pll_state) { @@ -2193,10 +2199,20 @@ static int readout_enabled_lane_count(struct intel_encoder *encoder) return enabled_tx_lane_count; } +static bool readout_ssc_state(struct intel_encoder *encoder, bool is_mpll_b) +{ + struct intel_display *display = to_intel_display(encoder); + + return intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port)) & + (is_mpll_b ? XELPDP_SSC_ENABLE_PLLB : XELPDP_SSC_ENABLE_PLLA); +} + static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *cx0pll_state) { struct intel_c10pll_state *pll_state = &cx0pll_state->c10; + struct intel_display *display = to_intel_display(encoder); + enum phy phy = intel_encoder_to_phy(encoder); u8 lane = INTEL_CX0_LANE0; intel_wakeref_t wakeref; int i; @@ -2222,6 +2238,13 @@ static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, intel_cx0_phy_transaction_end(encoder, wakeref); pll_state->clock = intel_c10pll_calc_port_clock(encoder, pll_state); + + cx0pll_state->ssc_enabled = readout_ssc_state(encoder, true); + drm_WARN(display->drm, + cx0pll_state->ssc_enabled != intel_c10pll_ssc_enabled(pll_state), + "PHY %c: SSC enabled state (%s), doesn't match PLL configuration (%s)\n", + phy_name(phy), str_yes_no(cx0pll_state->ssc_enabled), + intel_c10pll_ssc_enabled(pll_state) ? "SSC-enabled" : "SSC-disabled"); } static void intel_c10_pll_program(struct intel_display *display, @@ -2753,6 +2776,8 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, pll_state->clock = intel_c20pll_calc_port_clock(encoder, pll_state); intel_cx0_phy_transaction_end(encoder, wakeref); + + cx0pll_state->ssc_enabled = readout_ssc_state(encoder, intel_c20phy_use_mpllb(pll_state)); } static void intel_c20pll_dump_hw_state(struct intel_display *display, From 90fd33c2626008b8c5e6c30c44b480c21ea41c2d Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:41 +0200 Subject: [PATCH 0023/1610] drm/i915/cx0: Determine Cx0 PLL DP mode from PLL state The Cx0 PLL enable programming needs to know if the PLL is in DP or HDMI mode. The PLL manager framework doesn't pass the CRTC state to the PLL's enable hook, so prepare here for the conversion to use the PLL manager for Cx0 PHY PLLs by determining the DP/HDMI mode from the PLL state. For C10 PHYs use the fact that the HDMI divider value in the PLL registers are set if and only if the PLL is in HDMI mode. For C20 PHYs use the DP mode flag programmed to the VDR SERDES register, which is set if and only if the PLL is in DP mode. Assert that the above PLL/VDR SERDES register values match the DP/HDMI mode being configured already during state computation. This also allows dropping the is_dp param from the __intel_cx0pll_enable() function, since it can retrieve this now from the PLL state. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-12-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 43 ++++++++++++++++---- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 4562e47042d2..29dfbd60c7ce 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2085,6 +2085,24 @@ static void intel_c10pll_update_pll(struct intel_encoder *encoder, pll_state->c10.pll[i] = 0; } +static bool c10pll_state_is_dp(const struct intel_c10pll_state *pll_state) +{ + return !REG_FIELD_GET8(C10_PLL15_HDMIDIV_MASK, pll_state->pll[15]); +} + +static bool c20pll_state_is_dp(const struct intel_c20pll_state *pll_state) +{ + return pll_state->vdr.serdes_rate & PHY_C20_IS_DP; +} + +static bool cx0pll_state_is_dp(const struct intel_cx0pll_state *pll_state) +{ + if (pll_state->use_c10) + return c10pll_state_is_dp(&pll_state->c10); + + return c20pll_state_is_dp(&pll_state->c20); +} + /* * TODO: Convert the following to align with intel_c20pll_find_table() and * intel_c20pll_calc_state_from_table(). @@ -2094,6 +2112,7 @@ static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder, bool is_dp, int port_clock, int lane_count, struct intel_cx0pll_state *pll_state) { + struct intel_display *display = to_intel_display(encoder); int i; for (i = 0; tables[i]; i++) { @@ -2105,6 +2124,8 @@ static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder, pll_state->use_c10 = true; pll_state->lane_count = lane_count; + drm_WARN_ON(display->drm, is_dp != c10pll_state_is_dp(&pll_state->c10)); + return 0; } } @@ -2115,6 +2136,8 @@ static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder, static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { + struct intel_display *display = to_intel_display(encoder); + bool is_dp = intel_crtc_has_dp_encoder(crtc_state); const struct intel_c10pll_state * const *tables; int err; @@ -2122,8 +2145,7 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, if (!tables) return -EINVAL; - err = intel_c10pll_calc_state_from_table(encoder, tables, - intel_crtc_has_dp_encoder(crtc_state), + err = intel_c10pll_calc_state_from_table(encoder, tables, is_dp, crtc_state->port_clock, crtc_state->lane_count, &crtc_state->dpll_hw_state.cx0pll); @@ -2138,6 +2160,9 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, crtc_state->dpll_hw_state.cx0pll.use_c10 = true; crtc_state->dpll_hw_state.cx0pll.lane_count = crtc_state->lane_count; + drm_WARN_ON(display->drm, + is_dp != c10pll_state_is_dp(&crtc_state->dpll_hw_state.cx0pll.c10)); + return 0; } @@ -2624,6 +2649,7 @@ static int intel_c20pll_calc_state_from_table(struct intel_crtc_state *crtc_stat static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { + struct intel_display *display = to_intel_display(encoder); bool is_dp = intel_crtc_has_dp_encoder(crtc_state); int err = -ENOENT; @@ -2644,6 +2670,9 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, intel_c20_calc_vdr_params(&crtc_state->dpll_hw_state.cx0pll.c20.vdr, is_dp, crtc_state->port_clock); + drm_WARN_ON(display->drm, + is_dp != c20pll_state_is_dp(&crtc_state->dpll_hw_state.cx0pll.c20)); + return 0; } @@ -2912,10 +2941,11 @@ static void intel_c20_pll_program(struct intel_display *display, static void intel_program_port_clock_ctl(struct intel_encoder *encoder, const struct intel_cx0pll_state *pll_state, - bool is_dp, int port_clock, + int port_clock, bool lane_reversal) { struct intel_display *display = to_intel_display(encoder); + bool is_dp = cx0pll_state_is_dp(pll_state); u32 val = 0; intel_de_rmw(display, XELPDP_PORT_BUF_CTL1(display, encoder->port), @@ -3160,7 +3190,7 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask) static void __intel_cx0pll_enable(struct intel_encoder *encoder, const struct intel_cx0pll_state *pll_state, - bool is_dp, int port_clock) + int port_clock) { struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); @@ -3174,7 +3204,7 @@ static void __intel_cx0pll_enable(struct intel_encoder *encoder, * 1. Program PORT_CLOCK_CTL REGISTER to configure * clock muxes, gating and SSC */ - intel_program_port_clock_ctl(encoder, pll_state, is_dp, port_clock, lane_reversal); + intel_program_port_clock_ctl(encoder, pll_state, port_clock, lane_reversal); /* 2. Bring PHY out of reset. */ intel_cx0_phy_lane_reset(encoder, lane_reversal); @@ -3244,7 +3274,6 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { __intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll, - intel_crtc_has_dp_encoder(crtc_state), crtc_state->port_clock); } @@ -3795,7 +3824,7 @@ void intel_cx0_pll_power_save_wa(struct intel_display *display) "[ENCODER:%d:%s] Applying power saving workaround on disabled PLL\n", encoder->base.base.id, encoder->base.name); - __intel_cx0pll_enable(encoder, &pll_state, true, port_clock); + __intel_cx0pll_enable(encoder, &pll_state, port_clock); intel_cx0pll_disable(encoder); } } From 538187f17acd4bf94dfc98cdd8630559324fad43 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:42 +0200 Subject: [PATCH 0024/1610] drm/i915/cx0: Determine Cx0 PLL port clock from PLL state The port clock is tracked in the PLL state, so there is no need to pass it separately to __intel_cx0pll_enable(). Drop the port clock function param accordingly. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-13-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 29dfbd60c7ce..0ad9fae230c9 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -3188,10 +3188,10 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask) return val; } -static void __intel_cx0pll_enable(struct intel_encoder *encoder, - const struct intel_cx0pll_state *pll_state, - int port_clock) +static void intel_cx0pll_enable(struct intel_encoder *encoder, + const struct intel_cx0pll_state *pll_state) { + int port_clock = pll_state->use_c10 ? pll_state->c10.clock : pll_state->c20.clock; struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); @@ -3270,13 +3270,6 @@ static void __intel_cx0pll_enable(struct intel_encoder *encoder, intel_cx0_phy_transaction_end(encoder, wakeref); } -static void intel_cx0pll_enable(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) -{ - __intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll, - crtc_state->port_clock); -} - int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); @@ -3403,7 +3396,7 @@ void intel_mtl_pll_enable(struct intel_encoder *encoder, if (intel_tc_port_in_tbt_alt_mode(dig_port)) intel_mtl_tbt_pll_enable(encoder, crtc_state); else - intel_cx0pll_enable(encoder, crtc_state); + intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll); } /* @@ -3824,7 +3817,7 @@ void intel_cx0_pll_power_save_wa(struct intel_display *display) "[ENCODER:%d:%s] Applying power saving workaround on disabled PLL\n", encoder->base.base.id, encoder->base.name); - __intel_cx0pll_enable(encoder, &pll_state, port_clock); + intel_cx0pll_enable(encoder, &pll_state); intel_cx0pll_disable(encoder); } } From 36a3efb32ed2eb3986be4bb02e2f298d0ff055e8 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:43 +0200 Subject: [PATCH 0025/1610] drm/i915/cx0: Zero Cx0 PLL state before compute and HW readout Ensure Cx0 pll state is initialized to zero before any computation or HW readouts, to prevent leaving some parameter in the state uninitialized in the actual compute/HW readout functions later. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-14-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 0ad9fae230c9..df3daa81a698 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2679,6 +2679,8 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { + memset(&crtc_state->dpll_hw_state, 0, sizeof(crtc_state->dpll_hw_state)); + if (intel_encoder_is_c10phy(encoder)) return intel_c10pll_calc_state(crtc_state, encoder); return intel_c20pll_calc_state(crtc_state, encoder); @@ -3612,7 +3614,7 @@ static void intel_c10pll_state_verify(const struct intel_crtc_state *state, void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *pll_state) { - pll_state->use_c10 = false; + memset(pll_state, 0, sizeof(*pll_state)); pll_state->tbt_mode = intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)); if (pll_state->tbt_mode) From fb1dc1eab618f24ead88e2ea7ac057679eac4faf Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:44 +0200 Subject: [PATCH 0026/1610] drm/i915/cx0: Print additional Cx0 PLL HW state Print all the Cx0 PLL state in the PLL state dumper. v2: Use BUILD_BUG_ON() instead of WARN_ON() (Jani) Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-15-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index df3daa81a698..763546fe152b 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2306,8 +2306,8 @@ static void intel_c10pll_dump_hw_state(struct intel_display *display, unsigned int multiplier, tx_clk_div; fracen = hw_state->pll[0] & C10_PLL0_FRACEN; - drm_dbg_kms(display->drm, "c10pll_hw_state: fracen: %s, ", - str_yes_no(fracen)); + drm_dbg_kms(display->drm, "c10pll_hw_state: clock: %d, fracen: %s, ", + hw_state->clock, str_yes_no(fracen)); if (fracen) { frac_quot = hw_state->pll[12] << 8 | hw_state->pll[11]; @@ -2816,7 +2816,7 @@ static void intel_c20pll_dump_hw_state(struct intel_display *display, { int i; - drm_dbg_kms(display->drm, "c20pll_hw_state:\n"); + drm_dbg_kms(display->drm, "c20pll_hw_state clock: %d:\n", hw_state->clock); drm_dbg_kms(display->drm, "tx[0] = 0x%.4x, tx[1] = 0x%.4x, tx[2] = 0x%.4x\n", hw_state->tx[0], hw_state->tx[1], hw_state->tx[2]); @@ -2832,12 +2832,24 @@ static void intel_c20pll_dump_hw_state(struct intel_display *display, for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++) drm_dbg_kms(display->drm, "mplla[%d] = 0x%.4x\n", i, hw_state->mplla[i]); + + /* For full coverage, also print the additional PLL B entry. */ + BUILD_BUG_ON(ARRAY_SIZE(hw_state->mplla) + 1 != ARRAY_SIZE(hw_state->mpllb)); + drm_dbg_kms(display->drm, "mpllb[%d] = 0x%.4x\n", i, hw_state->mpllb[i]); } + + drm_dbg_kms(display->drm, "vdr: custom width: 0x%02x, serdes rate: 0x%02x, hdmi rate: 0x%02x\n", + hw_state->vdr.custom_width, hw_state->vdr.serdes_rate, hw_state->vdr.hdmi_rate); } void intel_cx0pll_dump_hw_state(struct intel_display *display, const struct intel_cx0pll_state *hw_state) { + drm_dbg_kms(display->drm, + "cx0pll_hw_state: lane_count: %d, ssc_enabled: %s, use_c10: %s, tbt_mode: %s\n", + hw_state->lane_count, str_yes_no(hw_state->ssc_enabled), + str_yes_no(hw_state->use_c10), str_yes_no(hw_state->tbt_mode)); + if (hw_state->use_c10) intel_c10pll_dump_hw_state(display, &hw_state->c10); else From ac3423721117a6ad2e643ba74770e118124eff27 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:45 +0200 Subject: [PATCH 0027/1610] drm/i915/cx0: Remove state verification When pll's are moved to dpll framework we no longer need Cx0 specific state verification as we can rely on dpll state verification instead. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-16-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 114 ------------------ drivers/gpu/drm/i915/display/intel_cx0_phy.h | 2 - .../drm/i915/display/intel_modeset_verify.c | 1 - 3 files changed, 117 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 763546fe152b..31db79f0636b 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -3594,35 +3594,6 @@ intel_mtl_port_pll_type(struct intel_encoder *encoder, return ICL_PORT_DPLL_DEFAULT; } -static void intel_c10pll_state_verify(const struct intel_crtc_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder, - struct intel_c10pll_state *mpllb_hw_state) -{ - struct intel_display *display = to_intel_display(state); - const struct intel_c10pll_state *mpllb_sw_state = &state->dpll_hw_state.cx0pll.c10; - int i; - - for (i = 0; i < ARRAY_SIZE(mpllb_sw_state->pll); i++) { - u8 expected = mpllb_sw_state->pll[i]; - - INTEL_DISPLAY_STATE_WARN(display, mpllb_hw_state->pll[i] != expected, - "[CRTC:%d:%s] mismatch in C10MPLLB: Register[%d] (expected 0x%02x, found 0x%02x)", - crtc->base.base.id, crtc->base.name, i, - expected, mpllb_hw_state->pll[i]); - } - - INTEL_DISPLAY_STATE_WARN(display, mpllb_hw_state->tx != mpllb_sw_state->tx, - "[CRTC:%d:%s] mismatch in C10MPLLB: Register TX0 (expected 0x%02x, found 0x%02x)", - crtc->base.base.id, crtc->base.name, - mpllb_sw_state->tx, mpllb_hw_state->tx); - - INTEL_DISPLAY_STATE_WARN(display, mpllb_hw_state->cmn != mpllb_sw_state->cmn, - "[CRTC:%d:%s] mismatch in C10MPLLB: Register CMN0 (expected 0x%02x, found 0x%02x)", - crtc->base.base.id, crtc->base.name, - mpllb_sw_state->cmn, mpllb_hw_state->cmn); -} - void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *pll_state) { @@ -3699,91 +3670,6 @@ int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder, return intel_c20pll_calc_port_clock(encoder, &pll_state->c20); } -static void intel_c20pll_state_verify(const struct intel_crtc_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder, - struct intel_c20pll_state *mpll_hw_state) -{ - struct intel_display *display = to_intel_display(state); - const struct intel_c20pll_state *mpll_sw_state = &state->dpll_hw_state.cx0pll.c20; - bool sw_use_mpllb = intel_c20phy_use_mpllb(mpll_sw_state); - bool hw_use_mpllb = intel_c20phy_use_mpllb(mpll_hw_state); - int clock = intel_c20pll_calc_port_clock(encoder, mpll_sw_state); - int i; - - INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->clock != clock, - "[CRTC:%d:%s] mismatch in C20: Register CLOCK (expected %d, found %d)", - crtc->base.base.id, crtc->base.name, - mpll_sw_state->clock, mpll_hw_state->clock); - - INTEL_DISPLAY_STATE_WARN(display, sw_use_mpllb != hw_use_mpllb, - "[CRTC:%d:%s] mismatch in C20: Register MPLLB selection (expected %d, found %d)", - crtc->base.base.id, crtc->base.name, - sw_use_mpllb, hw_use_mpllb); - - if (hw_use_mpllb) { - for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mpllb); i++) { - INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->mpllb[i] != mpll_sw_state->mpllb[i], - "[CRTC:%d:%s] mismatch in C20MPLLB: Register[%d] (expected 0x%04x, found 0x%04x)", - crtc->base.base.id, crtc->base.name, i, - mpll_sw_state->mpllb[i], mpll_hw_state->mpllb[i]); - } - } else { - for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mplla); i++) { - INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->mplla[i] != mpll_sw_state->mplla[i], - "[CRTC:%d:%s] mismatch in C20MPLLA: Register[%d] (expected 0x%04x, found 0x%04x)", - crtc->base.base.id, crtc->base.name, i, - mpll_sw_state->mplla[i], mpll_hw_state->mplla[i]); - } - } - - for (i = 0; i < ARRAY_SIZE(mpll_sw_state->tx); i++) { - INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->tx[i] != mpll_sw_state->tx[i], - "[CRTC:%d:%s] mismatch in C20: Register TX[%i] (expected 0x%04x, found 0x%04x)", - crtc->base.base.id, crtc->base.name, i, - mpll_sw_state->tx[i], mpll_hw_state->tx[i]); - } - - for (i = 0; i < ARRAY_SIZE(mpll_sw_state->cmn); i++) { - INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->cmn[i] != mpll_sw_state->cmn[i], - "[CRTC:%d:%s] mismatch in C20: Register CMN[%i] (expected 0x%04x, found 0x%04x)", - crtc->base.base.id, crtc->base.name, i, - mpll_sw_state->cmn[i], mpll_hw_state->cmn[i]); - } -} - -void intel_cx0pll_state_verify(struct intel_atomic_state *state, - struct intel_crtc *crtc) -{ - struct intel_display *display = to_intel_display(state); - const struct intel_crtc_state *new_crtc_state = - intel_atomic_get_new_crtc_state(state, crtc); - struct intel_encoder *encoder; - struct intel_cx0pll_state mpll_hw_state = {}; - - if (!IS_DISPLAY_VER(display, 14, 30)) - return; - - if (!new_crtc_state->hw.active) - return; - - /* intel_get_crtc_new_encoder() only works for modeset/fastset commits */ - if (!intel_crtc_needs_modeset(new_crtc_state) && - !intel_crtc_needs_fastset(new_crtc_state)) - return; - - encoder = intel_get_crtc_new_encoder(state, new_crtc_state); - intel_cx0pll_readout_hw_state(encoder, &mpll_hw_state); - - if (mpll_hw_state.tbt_mode) - return; - - if (intel_encoder_is_c10phy(encoder)) - intel_c10pll_state_verify(new_crtc_state, crtc, encoder, &mpll_hw_state.c10); - else - intel_c20pll_state_verify(new_crtc_state, crtc, encoder, &mpll_hw_state.c20); -} - /* * WA 14022081154 * The dedicated display PHYs reset to a power state that blocks S0ix, increasing idle diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index 84d334b865f7..0b98892ee8ac 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -40,8 +40,6 @@ int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder, void intel_cx0pll_dump_hw_state(struct intel_display *display, const struct intel_cx0pll_state *hw_state); -void intel_cx0pll_state_verify(struct intel_atomic_state *state, - struct intel_crtc *crtc); bool intel_cx0pll_compare_hw_state(const struct intel_cx0pll_state *a, const struct intel_cx0pll_state *b); void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c index b361a77cd235..12a00121c274 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c @@ -246,7 +246,6 @@ void intel_modeset_verify_crtc(struct intel_atomic_state *state, verify_crtc_state(state, crtc); intel_dpll_state_verify(state, crtc); intel_mpllb_state_verify(state, crtc); - intel_cx0pll_state_verify(state, crtc); intel_lt_phy_pll_state_verify(state, crtc); } From b5c0256a587eb50920ade41dd1b086039ec6bcfd Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:46 +0200 Subject: [PATCH 0028/1610] drm/i915/cx0: Add PLL information for MTL+ Start bringing MTL+ platforms as part of PLL framework. The work is started by adding PLL information and related function hooks. BSpec: 55726 v2: Revise commit message and add BSpec ID (Suraj) Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-17-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 8c345e1bdd94..23f22c495ec7 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4305,6 +4305,25 @@ static const struct intel_dpll_mgr adlp_pll_mgr = { .compare_hw_state = icl_compare_hw_state, }; +static const struct intel_dpll_funcs mtl_pll_funcs = { +}; + +static const struct dpll_info mtl_plls[] = { + { .name = "DPLL 0", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_DPLL0, }, + { .name = "DPLL 1", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_DPLL1, }, + /* TODO: Add TBT PLL */ + { .name = "TC PLL 1", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, }, + { .name = "TC PLL 2", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, }, + { .name = "TC PLL 3", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL3, }, + { .name = "TC PLL 4", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL4, }, + {} +}; + +__maybe_unused +static const struct intel_dpll_mgr mtl_pll_mgr = { + .dpll_info = mtl_plls, +}; + /** * intel_dpll_init - Initialize DPLLs * @display: intel_display device From d174cfb51dce71778822a8ab2dde772dad947409 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:47 +0200 Subject: [PATCH 0029/1610] drm/i915/cx0: Update C10/C20 state calculation Update several functions in intel_cx0_phy.c to make PLL state management more explicit. Changes include * add 'const' qualifiers to intel_crtc_state parameter for cx0 state calculation functions * refactor C10/C20 PLL state calculations helpers to take explicit hardware state pointers instead of directly modifying 'crtc_state->dpll_hw_state' Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-18-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 68 ++++++++++---------- drivers/gpu/drm/i915/display/intel_cx0_phy.h | 5 +- drivers/gpu/drm/i915/display/intel_dpll.c | 2 +- 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 31db79f0636b..de71805a065c 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2029,7 +2029,7 @@ static const struct intel_c20pll_state * const mtl_c20_hdmi_tables[] = { }; static const struct intel_c10pll_state * const * -intel_c10pll_tables_get(struct intel_crtc_state *crtc_state, +intel_c10pll_tables_get(const struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { if (intel_crtc_has_dp_encoder(crtc_state)) { @@ -2133,8 +2133,9 @@ static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder, return -EINVAL; } -static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +static int intel_c10pll_calc_state(const struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder, + struct intel_dpll_hw_state *hw_state) { struct intel_display *display = to_intel_display(encoder); bool is_dp = intel_crtc_has_dp_encoder(crtc_state); @@ -2147,21 +2148,20 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, err = intel_c10pll_calc_state_from_table(encoder, tables, is_dp, crtc_state->port_clock, crtc_state->lane_count, - &crtc_state->dpll_hw_state.cx0pll); + &hw_state->cx0pll); if (err == 0 || !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) return err; /* For HDMI PLLs try SNPS PHY algorithm, if there are no precomputed tables */ - intel_snps_hdmi_pll_compute_c10pll(&crtc_state->dpll_hw_state.cx0pll.c10, + intel_snps_hdmi_pll_compute_c10pll(&hw_state->cx0pll.c10, crtc_state->port_clock); - intel_c10pll_update_pll(encoder, - &crtc_state->dpll_hw_state.cx0pll); - crtc_state->dpll_hw_state.cx0pll.use_c10 = true; - crtc_state->dpll_hw_state.cx0pll.lane_count = crtc_state->lane_count; + intel_c10pll_update_pll(encoder, &hw_state->cx0pll); - drm_WARN_ON(display->drm, - is_dp != c10pll_state_is_dp(&crtc_state->dpll_hw_state.cx0pll.c10)); + hw_state->cx0pll.use_c10 = true; + hw_state->cx0pll.lane_count = crtc_state->lane_count; + + drm_WARN_ON(display->drm, is_dp != c10pll_state_is_dp(&hw_state->cx0pll.c10)); return 0; } @@ -2350,7 +2350,7 @@ static bool is_arrowlake_s_by_host_bridge(void) return pdev && IS_ARROWLAKE_S_BY_HOST_BRIDGE_ID(host_bridge_pci_dev_id); } -static u16 intel_c20_hdmi_tmds_tx_cgf_1(struct intel_crtc_state *crtc_state) +static u16 intel_c20_hdmi_tmds_tx_cgf_1(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); u16 tx_misc; @@ -2374,9 +2374,9 @@ static u16 intel_c20_hdmi_tmds_tx_cgf_1(struct intel_crtc_state *crtc_state) C20_PHY_TX_DCC_BYPASS | C20_PHY_TX_TERM_CTL(tx_term_ctrl)); } -static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state) +static int intel_c20_compute_hdmi_tmds_pll(const struct intel_crtc_state *crtc_state, + struct intel_c20pll_state *pll_state) { - struct intel_c20pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c20; u64 datarate; u64 mpll_tx_clk_div; u64 vco_freq_shift; @@ -2629,8 +2629,9 @@ intel_c20_pll_find_table(const struct intel_crtc_state *crtc_state, return NULL; } -static int intel_c20pll_calc_state_from_table(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +static int intel_c20pll_calc_state_from_table(const struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder, + struct intel_cx0pll_state *pll_state) { const struct intel_c20pll_state *table; @@ -2638,52 +2639,53 @@ static int intel_c20pll_calc_state_from_table(struct intel_crtc_state *crtc_stat if (!table) return -EINVAL; - crtc_state->dpll_hw_state.cx0pll.c20 = *table; + pll_state->c20 = *table; - intel_cx0pll_update_ssc(encoder, &crtc_state->dpll_hw_state.cx0pll, - intel_crtc_has_dp_encoder(crtc_state)); + intel_cx0pll_update_ssc(encoder, pll_state, intel_crtc_has_dp_encoder(crtc_state)); return 0; } -static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +static int intel_c20pll_calc_state(const struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder, + struct intel_dpll_hw_state *hw_state) { struct intel_display *display = to_intel_display(encoder); bool is_dp = intel_crtc_has_dp_encoder(crtc_state); int err = -ENOENT; - crtc_state->dpll_hw_state.cx0pll.use_c10 = false; - crtc_state->dpll_hw_state.cx0pll.lane_count = crtc_state->lane_count; + hw_state->cx0pll.use_c10 = false; + hw_state->cx0pll.lane_count = crtc_state->lane_count; /* try computed C20 HDMI tables before using consolidated tables */ if (!is_dp) /* TODO: Update SSC state for HDMI as well */ - err = intel_c20_compute_hdmi_tmds_pll(crtc_state); + err = intel_c20_compute_hdmi_tmds_pll(crtc_state, &hw_state->cx0pll.c20); if (err) - err = intel_c20pll_calc_state_from_table(crtc_state, encoder); + err = intel_c20pll_calc_state_from_table(crtc_state, encoder, + &hw_state->cx0pll); if (err) return err; - intel_c20_calc_vdr_params(&crtc_state->dpll_hw_state.cx0pll.c20.vdr, + intel_c20_calc_vdr_params(&hw_state->cx0pll.c20.vdr, is_dp, crtc_state->port_clock); - drm_WARN_ON(display->drm, - is_dp != c20pll_state_is_dp(&crtc_state->dpll_hw_state.cx0pll.c20)); + drm_WARN_ON(display->drm, is_dp != c20pll_state_is_dp(&hw_state->cx0pll.c20)); return 0; } -int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +int intel_cx0pll_calc_state(const struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder, + struct intel_dpll_hw_state *hw_state) { - memset(&crtc_state->dpll_hw_state, 0, sizeof(crtc_state->dpll_hw_state)); + memset(hw_state, 0, sizeof(*hw_state)); if (intel_encoder_is_c10phy(encoder)) - return intel_c10pll_calc_state(crtc_state, encoder); - return intel_c20pll_calc_state(crtc_state, encoder); + return intel_c10pll_calc_state(crtc_state, encoder, hw_state); + return intel_c20pll_calc_state(crtc_state, encoder, hw_state); } static bool intel_c20phy_use_mpllb(const struct intel_c20pll_state *state) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index 0b98892ee8ac..d52e864f5e19 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -19,6 +19,7 @@ struct intel_crtc; struct intel_crtc_state; struct intel_cx0pll_state; struct intel_display; +struct intel_dpll_hw_state; struct intel_encoder; struct intel_hdmi; @@ -32,7 +33,9 @@ enum icl_port_dpll_id intel_mtl_port_pll_type(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); -int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder); +int intel_cx0pll_calc_state(const struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder, + struct intel_dpll_hw_state *hw_state); void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *pll_state); int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 4f1db8493a2e..342d46b7b1af 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1221,7 +1221,7 @@ static int mtl_crtc_compute_clock(struct intel_atomic_state *state, intel_get_crtc_new_encoder(state, crtc_state); int ret; - ret = intel_cx0pll_calc_state(crtc_state, encoder); + ret = intel_cx0pll_calc_state(crtc_state, encoder, &crtc_state->dpll_hw_state); if (ret) return ret; From 28d5533f2787c67fbfdb29018c8ef56ba964147f Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:48 +0200 Subject: [PATCH 0030/1610] drm/i915/cx0: Compute plls for MTL+ platform To bring MTL+ platform aligned call and calculate PLL state from dpll framework. v2: Rename mtl_compute_c10phy_dpll() to mtl_compute_non_tc_phy_dpll(). The state is computed either for a C10 or on the PTL port B eDP over TypeC PHY case for a C20 PHY PLL. Hence refer to this case as "non_tc_phy" instead of "c10phy". Rename mtl_compute_c20phy_dplls() to mtl_compute_tc_phy_dplls() for symmetry with mtl_compute_non_tc_phy_dpll(). v3: Reword commit message (Suraj) Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-19-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 23f22c495ec7..20f940110faa 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4319,9 +4319,78 @@ static const struct dpll_info mtl_plls[] = { {} }; +/* + * Compute the state for either a C10 PHY PLL, or in the case of the PTL port B, + * eDP on TypeC PHY case for a C20 PHY PLL. + */ +static int mtl_compute_non_tc_phy_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + struct icl_port_dpll *port_dpll = + &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; + int ret; + + ret = intel_cx0pll_calc_state(crtc_state, encoder, &port_dpll->hw_state); + if (ret) + return ret; + + /* this is mainly for the fastset check */ + icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_DEFAULT); + + crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, + &port_dpll->hw_state.cx0pll); + + return 0; +} + +static int mtl_compute_tc_phy_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + struct icl_port_dpll *port_dpll; + int ret; + + /* TODO: Add state calculation for TBT PLL */ + + port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY]; + ret = intel_cx0pll_calc_state(crtc_state, encoder, &port_dpll->hw_state); + if (ret) + return ret; + + /* this is mainly for the fastset check */ + if (old_crtc_state->intel_dpll && + old_crtc_state->intel_dpll->info->id == DPLL_ID_ICL_TBTPLL) + icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_DEFAULT); + else + icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_MG_PHY); + + crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, + &port_dpll->hw_state.cx0pll); + + return 0; +} + +static int mtl_compute_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + if (intel_encoder_is_tc(encoder)) + return mtl_compute_tc_phy_dplls(state, crtc, encoder); + else + return mtl_compute_non_tc_phy_dpll(state, crtc, encoder); +} + __maybe_unused static const struct intel_dpll_mgr mtl_pll_mgr = { .dpll_info = mtl_plls, + .compute_dplls = mtl_compute_dplls, }; /** From ca1eda5cd476ca5c948e697af528694071f0f92a Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:49 +0200 Subject: [PATCH 0031/1610] drm/i915/cx0: Add MTL+ .get_dplls hook Add .get_dplls function pointer for MTL+ platforms to support dpll framework. Reuse the ICL function pointer. v2: Getting configuration either for a C10 or on the PTL port B eDP on TypeC PHY case for a C20 PHY PLL. Hence refer to this case as "non_tc_phy" instead of "c10phy". v3: Fix comment to "eDP over TypeC" (Suraj) Fix pll id as separate variable (Suraj) Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-20-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 57 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 1 + 2 files changed, 58 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 20f940110faa..313cb244d5d6 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -203,6 +203,22 @@ enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port) return tc_port - TC_PORT_1 + DPLL_ID_ICL_MGPLL1; } +enum intel_dpll_id mtl_port_to_pll_id(struct intel_display *display, enum port port) +{ + if (port >= PORT_TC1) + return icl_tc_port_to_pll_id(intel_port_to_tc(display, port)); + + switch (port) { + case PORT_A: + return DPLL_ID_ICL_DPLL0; + case PORT_B: + return DPLL_ID_ICL_DPLL1; + default: + MISSING_CASE(port); + return DPLL_ID_ICL_DPLL0; + } +} + static i915_reg_t intel_combo_pll_enable_reg(struct intel_display *display, struct intel_dpll *pll) @@ -3490,6 +3506,36 @@ err_unreference_tbt_pll: return ret; } +/* + * Get the PLL for either a port using a C10 PHY PLL, or in the + * PTL port B eDP over TypeC PHY case, the PLL for a port using + * a C20 PHY PLL. + */ +static int mtl_get_non_tc_phy_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + struct intel_display *display = to_intel_display(crtc); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + struct icl_port_dpll *port_dpll = + &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; + enum intel_dpll_id pll_id = mtl_port_to_pll_id(display, encoder->port); + + port_dpll->pll = intel_find_dpll(state, crtc, + &port_dpll->hw_state, + BIT(pll_id)); + if (!port_dpll->pll) + return -EINVAL; + + intel_reference_dpll(state, crtc, + port_dpll->pll, &port_dpll->hw_state); + + icl_update_active_dpll(state, crtc, encoder); + + return 0; +} + static int icl_compute_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder) @@ -4387,10 +4433,21 @@ static int mtl_compute_dplls(struct intel_atomic_state *state, return mtl_compute_non_tc_phy_dpll(state, crtc, encoder); } +static int mtl_get_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + if (intel_encoder_is_tc(encoder)) + return icl_get_tc_phy_dplls(state, crtc, encoder); + else + return mtl_get_non_tc_phy_dpll(state, crtc, encoder); +} + __maybe_unused static const struct intel_dpll_mgr mtl_pll_mgr = { .dpll_info = mtl_plls, .compute_dplls = mtl_compute_dplls, + .get_dplls = mtl_get_dplls, }; /** diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index a7946ff13cb6..322af5c55d7c 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -450,6 +450,7 @@ bool intel_dpll_compare_hw_state(struct intel_display *display, const struct intel_dpll_hw_state *a, const struct intel_dpll_hw_state *b); enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port); +enum intel_dpll_id mtl_port_to_pll_id(struct intel_display *display, enum port port); bool intel_dpll_is_combophy(enum intel_dpll_id id); void intel_dpll_state_verify(struct intel_atomic_state *state, From 051964d94adc7b2f16921c1fc1969f7910d7129c Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:50 +0200 Subject: [PATCH 0032/1610] drm/i915/cx0: Add MTL+ .put_dplls hook Add .put_dplls function pointer to support MTL+ platforms on dpll framework. Reuse ICL function pointer. Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-21-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 313cb244d5d6..c45f18201ee8 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4448,6 +4448,7 @@ static const struct intel_dpll_mgr mtl_pll_mgr = { .dpll_info = mtl_plls, .compute_dplls = mtl_compute_dplls, .get_dplls = mtl_get_dplls, + .put_dplls = icl_put_dplls, }; /** From 4fcefdf990cb14a3586e622ded7a18c287cf51e4 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Tue, 18 Nov 2025 15:28:30 +0200 Subject: [PATCH 0033/1610] drm/i915/cx0: Add MTL+ .update_active_dpll hook Add .update_active_dpll function pointer to support dpll framework. Reuse ICL function pointer. v2: Add check for !HAS_LT_PHY (Suraj) v3: Remove the incorrect !HAS_LT_PHY condition and check for existing dpll_mgr Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal # v1 Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251118132830.2584422-1-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 4 ++-- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 002ccd47856d..39d87bc91571 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3667,8 +3667,8 @@ void intel_ddi_update_active_dpll(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); struct intel_crtc *pipe_crtc; - /* FIXME: Add MTL pll_mgr */ - if (DISPLAY_VER(display) >= 14 || !intel_encoder_is_tc(encoder)) + /* FIXME: Add NVL+ and DG2 pll_mgr */ + if (!intel_encoder_is_tc(encoder) || !display->dpll.mgr) return; for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc, diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index c45f18201ee8..e6dd6f1123d6 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4449,6 +4449,7 @@ static const struct intel_dpll_mgr mtl_pll_mgr = { .compute_dplls = mtl_compute_dplls, .get_dplls = mtl_get_dplls, .put_dplls = icl_put_dplls, + .update_active_dpll = icl_update_active_dpll, }; /** From dc3fdd4ade8763aac3546835909b70c298b8e8f4 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:52 +0200 Subject: [PATCH 0034/1610] drm/i915/cx0: Add MTL+ .update_dpll_ref_clks hook Add .update_dpll_ref_clks function pointer to MTL+ platforms to support dpll framework. Reuse ICL function pointer. Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-23-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index e6dd6f1123d6..32e52babf265 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4450,6 +4450,7 @@ static const struct intel_dpll_mgr mtl_pll_mgr = { .get_dplls = mtl_get_dplls, .put_dplls = icl_put_dplls, .update_active_dpll = icl_update_active_dpll, + .update_ref_clks = icl_update_dpll_ref_clks, }; /** From 2e129889622c391d4d1204a0da16e278d585124b Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:53 +0200 Subject: [PATCH 0035/1610] drm/i915/cx0: Add MTL+ .dump_hw_state hook Add .dump_hw_state function pointer for MTL+ platforms to support dpll framework. While at it, switch to use drm_printer structure to print hw state information. v2: Keep debug messages on one line if they not necessarily needed to split into two or more lines (Suraj) Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-24-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 70 +++++++++---------- drivers/gpu/drm/i915/display/intel_cx0_phy.h | 3 +- drivers/gpu/drm/i915/display/intel_display.c | 5 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 7 ++ 4 files changed, 45 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index de71805a065c..a88169b76cfa 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2297,7 +2297,7 @@ static void intel_c10_pll_program(struct intel_display *display, intel_c10_msgbus_access_commit(encoder, INTEL_CX0_LANE0, true); } -static void intel_c10pll_dump_hw_state(struct intel_display *display, +static void intel_c10pll_dump_hw_state(struct drm_printer *p, const struct intel_c10pll_state *hw_state) { bool fracen; @@ -2306,33 +2306,32 @@ static void intel_c10pll_dump_hw_state(struct intel_display *display, unsigned int multiplier, tx_clk_div; fracen = hw_state->pll[0] & C10_PLL0_FRACEN; - drm_dbg_kms(display->drm, "c10pll_hw_state: clock: %d, fracen: %s, ", - hw_state->clock, str_yes_no(fracen)); + drm_printf(p, "c10pll_hw_state: clock: %d, fracen: %s, ", + hw_state->clock, str_yes_no(fracen)); if (fracen) { frac_quot = hw_state->pll[12] << 8 | hw_state->pll[11]; frac_rem = hw_state->pll[14] << 8 | hw_state->pll[13]; frac_den = hw_state->pll[10] << 8 | hw_state->pll[9]; - drm_dbg_kms(display->drm, "quot: %u, rem: %u, den: %u,\n", - frac_quot, frac_rem, frac_den); + drm_printf(p, "quot: %u, rem: %u, den: %u,\n", + frac_quot, frac_rem, frac_den); } multiplier = (REG_FIELD_GET8(C10_PLL3_MULTIPLIERH_MASK, hw_state->pll[3]) << 8 | hw_state->pll[2]) / 2 + 16; tx_clk_div = REG_FIELD_GET8(C10_PLL15_TXCLKDIV_MASK, hw_state->pll[15]); - drm_dbg_kms(display->drm, - "multiplier: %u, tx_clk_div: %u.\n", multiplier, tx_clk_div); + drm_printf(p, + "multiplier: %u, tx_clk_div: %u.\n", multiplier, tx_clk_div); - drm_dbg_kms(display->drm, "c10pll_rawhw_state:"); - drm_dbg_kms(display->drm, "tx: 0x%x, cmn: 0x%x\n", hw_state->tx, - hw_state->cmn); + drm_printf(p, "c10pll_rawhw_state:"); + drm_printf(p, "tx: 0x%x, cmn: 0x%x\n", hw_state->tx, hw_state->cmn); BUILD_BUG_ON(ARRAY_SIZE(hw_state->pll) % 4); for (i = 0; i < ARRAY_SIZE(hw_state->pll); i = i + 4) - drm_dbg_kms(display->drm, - "pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x\n", - i, hw_state->pll[i], i + 1, hw_state->pll[i + 1], - i + 2, hw_state->pll[i + 2], i + 3, hw_state->pll[i + 3]); + drm_printf(p, + "pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x\n", + i, hw_state->pll[i], i + 1, hw_state->pll[i + 1], + i + 2, hw_state->pll[i + 2], i + 3, hw_state->pll[i + 3]); } /* @@ -2813,49 +2812,48 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, cx0pll_state->ssc_enabled = readout_ssc_state(encoder, intel_c20phy_use_mpllb(pll_state)); } -static void intel_c20pll_dump_hw_state(struct intel_display *display, +static void intel_c20pll_dump_hw_state(struct drm_printer *p, const struct intel_c20pll_state *hw_state) { int i; - drm_dbg_kms(display->drm, "c20pll_hw_state clock: %d:\n", hw_state->clock); - drm_dbg_kms(display->drm, - "tx[0] = 0x%.4x, tx[1] = 0x%.4x, tx[2] = 0x%.4x\n", - hw_state->tx[0], hw_state->tx[1], hw_state->tx[2]); - drm_dbg_kms(display->drm, - "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 0x%.4x, cmn[3] = 0x%.4x\n", - hw_state->cmn[0], hw_state->cmn[1], hw_state->cmn[2], hw_state->cmn[3]); + drm_printf(p, "c20pll_hw_state: clock: %d\n", hw_state->clock); + drm_printf(p, + "tx[0] = 0x%.4x, tx[1] = 0x%.4x, tx[2] = 0x%.4x\n", + hw_state->tx[0], hw_state->tx[1], hw_state->tx[2]); + drm_printf(p, + "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 0x%.4x, cmn[3] = 0x%.4x\n", + hw_state->cmn[0], hw_state->cmn[1], hw_state->cmn[2], hw_state->cmn[3]); if (intel_c20phy_use_mpllb(hw_state)) { for (i = 0; i < ARRAY_SIZE(hw_state->mpllb); i++) - drm_dbg_kms(display->drm, "mpllb[%d] = 0x%.4x\n", i, - hw_state->mpllb[i]); + drm_printf(p, "mpllb[%d] = 0x%.4x\n", i, hw_state->mpllb[i]); } else { for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++) - drm_dbg_kms(display->drm, "mplla[%d] = 0x%.4x\n", i, - hw_state->mplla[i]); + drm_printf(p, "mplla[%d] = 0x%.4x\n", i, hw_state->mplla[i]); /* For full coverage, also print the additional PLL B entry. */ BUILD_BUG_ON(ARRAY_SIZE(hw_state->mplla) + 1 != ARRAY_SIZE(hw_state->mpllb)); - drm_dbg_kms(display->drm, "mpllb[%d] = 0x%.4x\n", i, hw_state->mpllb[i]); + drm_printf(p, "mpllb[%d] = 0x%.4x\n", i, hw_state->mpllb[i]); } - drm_dbg_kms(display->drm, "vdr: custom width: 0x%02x, serdes rate: 0x%02x, hdmi rate: 0x%02x\n", - hw_state->vdr.custom_width, hw_state->vdr.serdes_rate, hw_state->vdr.hdmi_rate); + drm_printf(p, + "vdr: custom width: 0x%02x, serdes rate: 0x%02x, hdmi rate: 0x%02x\n", + hw_state->vdr.custom_width, hw_state->vdr.serdes_rate, hw_state->vdr.hdmi_rate); } -void intel_cx0pll_dump_hw_state(struct intel_display *display, +void intel_cx0pll_dump_hw_state(struct drm_printer *p, const struct intel_cx0pll_state *hw_state) { - drm_dbg_kms(display->drm, - "cx0pll_hw_state: lane_count: %d, ssc_enabled: %s, use_c10: %s, tbt_mode: %s\n", - hw_state->lane_count, str_yes_no(hw_state->ssc_enabled), - str_yes_no(hw_state->use_c10), str_yes_no(hw_state->tbt_mode)); + drm_printf(p, + "cx0pll_hw_state: lane_count: %d, ssc_enabled: %s, use_c10: %s, tbt_mode: %s\n", + hw_state->lane_count, str_yes_no(hw_state->ssc_enabled), + str_yes_no(hw_state->use_c10), str_yes_no(hw_state->tbt_mode)); if (hw_state->use_c10) - intel_c10pll_dump_hw_state(display, &hw_state->c10); + intel_c10pll_dump_hw_state(p, &hw_state->c10); else - intel_c20pll_dump_hw_state(display, &hw_state->c20); + intel_c20pll_dump_hw_state(p, &hw_state->c20); } static bool intel_c20_protocol_switch_valid(struct intel_encoder *encoder) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index d52e864f5e19..acfbaced22f5 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -11,6 +11,7 @@ #define MB_WRITE_COMMITTED true #define MB_WRITE_UNCOMMITTED false +struct drm_printer; enum icl_port_dpll_id; struct intel_atomic_state; struct intel_c10pll_state; @@ -41,7 +42,7 @@ void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder, const struct intel_cx0pll_state *pll_state); -void intel_cx0pll_dump_hw_state(struct intel_display *display, +void intel_cx0pll_dump_hw_state(struct drm_printer *p, const struct intel_cx0pll_state *hw_state); bool intel_cx0pll_compare_hw_state(const struct intel_cx0pll_state *a, const struct intel_cx0pll_state *b); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 069967114bd9..e7bb8ec0d6bb 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4984,15 +4984,14 @@ pipe_config_cx0pll_mismatch(struct drm_printer *p, bool fastset, const struct intel_cx0pll_state *a, const struct intel_cx0pll_state *b) { - struct intel_display *display = to_intel_display(crtc); char *chipname = a->use_c10 ? "C10" : "C20"; pipe_config_mismatch(p, fastset, crtc, name, chipname); drm_printf(p, "expected:\n"); - intel_cx0pll_dump_hw_state(display, a); + intel_cx0pll_dump_hw_state(p, a); drm_printf(p, "found:\n"); - intel_cx0pll_dump_hw_state(display, b); + intel_cx0pll_dump_hw_state(p, b); } static bool allow_vblank_delay_fastset(const struct intel_crtc_state *old_crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 32e52babf265..aee8f1a5848a 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4443,6 +4443,12 @@ static int mtl_get_dplls(struct intel_atomic_state *state, return mtl_get_non_tc_phy_dpll(state, crtc, encoder); } +static void mtl_dump_hw_state(struct drm_printer *p, + const struct intel_dpll_hw_state *dpll_hw_state) +{ + intel_cx0pll_dump_hw_state(p, &dpll_hw_state->cx0pll); +} + __maybe_unused static const struct intel_dpll_mgr mtl_pll_mgr = { .dpll_info = mtl_plls, @@ -4451,6 +4457,7 @@ static const struct intel_dpll_mgr mtl_pll_mgr = { .put_dplls = icl_put_dplls, .update_active_dpll = icl_update_active_dpll, .update_ref_clks = icl_update_dpll_ref_clks, + .dump_hw_state = mtl_dump_hw_state, }; /** From 9b5f839e14a52c67492830b718d4ac8dddf04688 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:54 +0200 Subject: [PATCH 0036/1610] drm/i915/cx0: Add .compare_hw_state hook Add .compare_hw_state function pointer for MTL+ platforms to support dpll framework. Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-25-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index aee8f1a5848a..c0ba269dc714 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4449,6 +4449,15 @@ static void mtl_dump_hw_state(struct drm_printer *p, intel_cx0pll_dump_hw_state(p, &dpll_hw_state->cx0pll); } +static bool mtl_compare_hw_state(const struct intel_dpll_hw_state *_a, + const struct intel_dpll_hw_state *_b) +{ + const struct intel_cx0pll_state *a = &_a->cx0pll; + const struct intel_cx0pll_state *b = &_b->cx0pll; + + return intel_cx0pll_compare_hw_state(a, b); +} + __maybe_unused static const struct intel_dpll_mgr mtl_pll_mgr = { .dpll_info = mtl_plls, @@ -4458,6 +4467,7 @@ static const struct intel_dpll_mgr mtl_pll_mgr = { .update_active_dpll = icl_update_active_dpll, .update_ref_clks = icl_update_dpll_ref_clks, .dump_hw_state = mtl_dump_hw_state, + .compare_hw_state = mtl_compare_hw_state, }; /** From 685f36534968467a37ee7319673633b82dcebe09 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:55 +0200 Subject: [PATCH 0037/1610] drm/i915/cx0: Add MTL+ .get_hw_state hook Add .get_hw_state hook to MTL+ platforms for dpll framework. Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-26-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 9 ++++-- drivers/gpu/drm/i915/display/intel_cx0_phy.h | 2 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 29 +++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index a88169b76cfa..bde461878647 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -3594,19 +3594,24 @@ intel_mtl_port_pll_type(struct intel_encoder *encoder, return ICL_PORT_DPLL_DEFAULT; } -void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, +bool intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *pll_state) { memset(pll_state, 0, sizeof(*pll_state)); pll_state->tbt_mode = intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)); if (pll_state->tbt_mode) - return; + return true; + + if (!intel_cx0_pll_is_enabled(encoder)) + return false; if (intel_encoder_is_c10phy(encoder)) intel_c10pll_readout_hw_state(encoder, pll_state); else intel_c20pll_readout_hw_state(encoder, pll_state); + + return true; } static bool mtl_compare_hw_state_c10(const struct intel_c10pll_state *a, diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index acfbaced22f5..37b53faa5e78 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -37,7 +37,7 @@ intel_mtl_port_pll_type(struct intel_encoder *encoder, int intel_cx0pll_calc_state(const struct intel_crtc_state *crtc_state, struct intel_encoder *encoder, struct intel_dpll_hw_state *hw_state); -void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, +bool intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *pll_state); int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder, const struct intel_cx0pll_state *pll_state); diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index c0ba269dc714..beaf270294ca 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4351,7 +4351,36 @@ static const struct intel_dpll_mgr adlp_pll_mgr = { .compare_hw_state = icl_compare_hw_state, }; +static struct intel_encoder *get_intel_encoder(struct intel_display *display, + const struct intel_dpll *pll) +{ + struct intel_encoder *encoder; + enum intel_dpll_id mtl_id; + + for_each_intel_encoder(display->drm, encoder) { + mtl_id = mtl_port_to_pll_id(display, encoder->port); + + if (mtl_id == pll->info->id) + return encoder; + } + + return NULL; +} + +static bool mtl_pll_get_hw_state(struct intel_display *display, + struct intel_dpll *pll, + struct intel_dpll_hw_state *dpll_hw_state) +{ + struct intel_encoder *encoder = get_intel_encoder(display, pll); + + if (!encoder) + return false; + + return intel_cx0pll_readout_hw_state(encoder, &dpll_hw_state->cx0pll); +} + static const struct intel_dpll_funcs mtl_pll_funcs = { + .get_hw_state = mtl_pll_get_hw_state, }; static const struct dpll_info mtl_plls[] = { From 57cf9d5e45a88a4d3543dfd32c78f9bedca1b110 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:56 +0200 Subject: [PATCH 0038/1610] drm/i915/cx0: Add MTL+ .get_freq hook Add .get_freq hook to support dpll framework for MTL+ platforms. Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-27-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index beaf270294ca..85b3fee2d9b6 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4379,8 +4379,21 @@ static bool mtl_pll_get_hw_state(struct intel_display *display, return intel_cx0pll_readout_hw_state(encoder, &dpll_hw_state->cx0pll); } +static int mtl_pll_get_freq(struct intel_display *display, + const struct intel_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) +{ + struct intel_encoder *encoder = get_intel_encoder(display, pll); + + if (drm_WARN_ON(display->drm, !encoder)) + return -EINVAL; + + return intel_cx0pll_calc_port_clock(encoder, &dpll_hw_state->cx0pll); +} + static const struct intel_dpll_funcs mtl_pll_funcs = { .get_hw_state = mtl_pll_get_hw_state, + .get_freq = mtl_pll_get_freq, }; static const struct dpll_info mtl_plls[] = { From f3b04e27f7e5cf2af91d73112d9f81296ddad156 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:57 +0200 Subject: [PATCH 0039/1610] drm/i915/cx0: Add MTL+ .crtc_get_dpll hook Add .crtc_get_dpll function pointer to support MTL+ platforms. Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-28-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 342d46b7b1af..2da65bb20f1c 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1720,6 +1720,7 @@ static const struct intel_dpll_global_funcs xe3plpd_dpll_funcs = { static const struct intel_dpll_global_funcs mtl_dpll_funcs = { .crtc_compute_clock = mtl_crtc_compute_clock, + .crtc_get_dpll = hsw_crtc_get_dpll, }; static const struct intel_dpll_global_funcs dg2_dpll_funcs = { From b800af732c6b844c8fe6465edf39c437f4a760e3 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:58 +0200 Subject: [PATCH 0040/1610] drm/i915/cx0: PLL verify debug state print Print out hw and sw pll states for better debugging support. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-29-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 85b3fee2d9b6..463677014199 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4882,11 +4882,18 @@ verify_single_dpll_state(struct intel_display *display, "%s: pll enabled crtcs mismatch (expected 0x%x in 0x%x)\n", pll->info->name, pipe_mask, pll->state.pipe_mask); - INTEL_DISPLAY_STATE_WARN(display, - pll->on && memcmp(&pll->state.hw_state, &dpll_hw_state, - sizeof(dpll_hw_state)), - "%s: pll hw state mismatch\n", - pll->info->name); + if (INTEL_DISPLAY_STATE_WARN(display, + pll->on && memcmp(&pll->state.hw_state, &dpll_hw_state, + sizeof(dpll_hw_state)), + "%s: pll hw state mismatch\n", + pll->info->name)) { + struct drm_printer p = drm_dbg_printer(display->drm, DRM_UT_KMS, NULL); + + drm_printf(&p, "PLL %s HW state:\n", pll->info->name); + intel_dpll_dump_hw_state(display, &p, &dpll_hw_state); + drm_printf(&p, "PLL %s SW state:\n", pll->info->name); + intel_dpll_dump_hw_state(display, &p, &pll->state.hw_state); + } } static bool has_alt_port_dpll(const struct intel_dpll *old_pll, From e32518d012ed9abd97b33832fc82fafdab40c12d Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:59 +0200 Subject: [PATCH 0041/1610] drm/i915/cx0: Add MTL+ .enable_clock/.disable clock hooks on DDI To enable pll clock on DDI move part of the pll enabling sequence into a ddi clock enabling function. Simililarly, do the same for pll disabling sequence. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-30-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 34 +++++++++++++------ drivers/gpu/drm/i915/display/intel_cx0_phy.h | 11 +++++- drivers/gpu/drm/i915/display/intel_ddi.c | 6 ++-- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 25 ++++++++++++++ drivers/gpu/drm/i915/display/intel_lt_phy.c | 4 +-- 5 files changed, 64 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index bde461878647..79be234780ba 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -3280,7 +3280,6 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder, * Frequency Change. We handle this step in bxt_set_cdclk(). */ - /* TODO: enable TBT-ALT mode */ intel_cx0_phy_transaction_end(encoder, wakeref); } @@ -3346,8 +3345,7 @@ static int intel_mtl_tbt_clock_select(struct intel_display *display, } } -void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) +void intel_mtl_tbt_pll_enable_clock(struct intel_encoder *encoder, int port_clock) { struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); @@ -3361,7 +3359,7 @@ void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder, mask = XELPDP_DDI_CLOCK_SELECT_MASK(display); val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, - intel_mtl_tbt_clock_select(display, crtc_state->port_clock)); + intel_mtl_tbt_clock_select(display, port_clock)); mask |= XELPDP_FORWARD_CLOCK_UNGATE; val |= XELPDP_FORWARD_CLOCK_UNGATE; @@ -3399,18 +3397,26 @@ void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder, * clock frequency. */ intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), - crtc_state->port_clock); + port_clock); } void intel_mtl_pll_enable(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) + struct intel_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) +{ + intel_cx0pll_enable(encoder, &dpll_hw_state->cx0pll); +} + +void intel_mtl_pll_enable_clock(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) { struct intel_digital_port *dig_port = enc_to_dig_port(encoder); if (intel_tc_port_in_tbt_alt_mode(dig_port)) - intel_mtl_tbt_pll_enable(encoder, crtc_state); + intel_mtl_tbt_pll_enable_clock(encoder, crtc_state->port_clock); else - intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll); + /* TODO: remove when PLL mgr is in place. */ + intel_mtl_pll_enable(encoder, NULL, &crtc_state->dpll_hw_state); } /* @@ -3525,7 +3531,7 @@ static bool intel_cx0_pll_is_enabled(struct intel_encoder *encoder) intel_cx0_get_pclk_pll_request(lane); } -void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder) +void intel_mtl_tbt_pll_disable_clock(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); @@ -3564,13 +3570,19 @@ void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder) } void intel_mtl_pll_disable(struct intel_encoder *encoder) +{ + intel_cx0pll_disable(encoder); +} + +void intel_mtl_pll_disable_clock(struct intel_encoder *encoder) { struct intel_digital_port *dig_port = enc_to_dig_port(encoder); if (intel_tc_port_in_tbt_alt_mode(dig_port)) - intel_mtl_tbt_pll_disable(encoder); + intel_mtl_tbt_pll_disable_clock(encoder); else - intel_cx0pll_disable(encoder); + /* TODO: remove when PLL mgr is in place. */ + intel_mtl_pll_disable(encoder); } enum icl_port_dpll_id diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index 37b53faa5e78..3745d7081ac7 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -20,6 +20,7 @@ struct intel_crtc; struct intel_crtc_state; struct intel_cx0pll_state; struct intel_display; +struct intel_dpll; struct intel_dpll_hw_state; struct intel_encoder; struct intel_hdmi; @@ -28,11 +29,19 @@ void intel_clear_response_ready_flag(struct intel_encoder *encoder, int lane); bool intel_encoder_is_c10phy(struct intel_encoder *encoder); void intel_mtl_pll_enable(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state); + struct intel_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state); void intel_mtl_pll_disable(struct intel_encoder *encoder); enum icl_port_dpll_id intel_mtl_port_pll_type(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); +void intel_mtl_pll_enable_clock(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state); +void intel_mtl_pll_disable_clock(struct intel_encoder *encoder); +void intel_mtl_pll_disable_clock(struct intel_encoder *encoder); +void intel_mtl_tbt_pll_enable_clock(struct intel_encoder *encoder, + int port_clock); +void intel_mtl_tbt_pll_disable_clock(struct intel_encoder *encoder); int intel_cx0pll_calc_state(const struct intel_crtc_state *crtc_state, struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 39d87bc91571..7f8e1ebb27b9 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -89,6 +89,8 @@ #include "skl_scaler.h" #include "skl_universal_plane.h" +struct intel_dpll; + static const u8 index_to_dp_signal_levels[] = { [0] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0, [1] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1, @@ -5252,8 +5254,8 @@ void intel_ddi_init(struct intel_display *display, encoder->port_pll_type = intel_mtl_port_pll_type; encoder->get_config = xe3plpd_ddi_get_config; } else if (DISPLAY_VER(display) >= 14) { - encoder->enable_clock = intel_mtl_pll_enable; - encoder->disable_clock = intel_mtl_pll_disable; + encoder->enable_clock = intel_mtl_pll_enable_clock; + encoder->disable_clock = intel_mtl_pll_disable_clock; encoder->port_pll_type = intel_mtl_port_pll_type; encoder->get_config = mtl_ddi_get_config; } else if (display->platform.dg2) { diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 463677014199..ecb7e3761a5b 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4391,7 +4391,32 @@ static int mtl_pll_get_freq(struct intel_display *display, return intel_cx0pll_calc_port_clock(encoder, &dpll_hw_state->cx0pll); } +static void mtl_pll_enable(struct intel_display *display, + struct intel_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) +{ + struct intel_encoder *encoder = get_intel_encoder(display, pll); + + if (drm_WARN_ON(display->drm, !encoder)) + return; + + intel_mtl_pll_enable(encoder, pll, dpll_hw_state); +} + +static void mtl_pll_disable(struct intel_display *display, + struct intel_dpll *pll) +{ + struct intel_encoder *encoder = get_intel_encoder(display, pll); + + if (drm_WARN_ON(display->drm, !encoder)) + return; + + intel_mtl_pll_disable(encoder); +} + static const struct intel_dpll_funcs mtl_pll_funcs = { + .enable = mtl_pll_enable, + .disable = mtl_pll_disable, .get_hw_state = mtl_pll_get_hw_state, .get_freq = mtl_pll_get_freq, }; diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy.c b/drivers/gpu/drm/i915/display/intel_lt_phy.c index a67eb4f7f897..aaf5a2433690 100644 --- a/drivers/gpu/drm/i915/display/intel_lt_phy.c +++ b/drivers/gpu/drm/i915/display/intel_lt_phy.c @@ -2310,7 +2310,7 @@ void intel_xe3plpd_pll_enable(struct intel_encoder *encoder, struct intel_digital_port *dig_port = enc_to_dig_port(encoder); if (intel_tc_port_in_tbt_alt_mode(dig_port)) - intel_mtl_tbt_pll_enable(encoder, crtc_state); + intel_mtl_tbt_pll_enable_clock(encoder, crtc_state->port_clock); else intel_lt_phy_pll_enable(encoder, crtc_state); } @@ -2320,7 +2320,7 @@ void intel_xe3plpd_pll_disable(struct intel_encoder *encoder) struct intel_digital_port *dig_port = enc_to_dig_port(encoder); if (intel_tc_port_in_tbt_alt_mode(dig_port)) - intel_mtl_tbt_pll_disable(encoder); + intel_mtl_tbt_pll_disable_clock(encoder); else intel_lt_phy_pll_disable(encoder); From 6b566d066c823a9ad1ec5a7043955349a71ce42b Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:46:00 +0200 Subject: [PATCH 0042/1610] drm/i915/cx0: Get encoder configuration for C10 and C20 PHY PLLs For DDI initialization get encoder configuration for C10 and C20 chips. v2: Get configuration either for a C10 or on the PTL port B eDP on TypeC PHY case for a C20 PHY PLL. Hence refer to this case as "non_tc_phy" instead of "c10phy". Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-31-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 81 ++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 7f8e1ebb27b9..e7abc3dee017 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4270,6 +4270,77 @@ static void mtl_ddi_get_config(struct intel_encoder *encoder, intel_ddi_get_config(encoder, crtc_state); } +static bool icl_ddi_tc_pll_is_tbt(const struct intel_dpll *pll) +{ + return pll->info->id == DPLL_ID_ICL_TBTPLL; +} + +static void mtl_ddi_cx0_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + enum icl_port_dpll_id port_dpll_id, + enum intel_dpll_id pll_id) +{ + struct intel_display *display = to_intel_display(encoder); + struct icl_port_dpll *port_dpll; + struct intel_dpll *pll; + bool pll_active; + + port_dpll = &crtc_state->icl_port_dplls[port_dpll_id]; + pll = intel_get_dpll_by_id(display, pll_id); + + if (drm_WARN_ON(display->drm, !pll)) + return; + + port_dpll->pll = pll; + pll_active = intel_dpll_get_hw_state(display, pll, &port_dpll->hw_state); + drm_WARN_ON(display->drm, !pll_active); + + icl_set_active_port_dpll(crtc_state, port_dpll_id); + + if (icl_ddi_tc_pll_is_tbt(crtc_state->intel_dpll)) + crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder); + else + crtc_state->port_clock = intel_dpll_get_freq(display, crtc_state->intel_dpll, + &crtc_state->dpll_hw_state); + + intel_ddi_get_config(encoder, crtc_state); +} + +/* + * Get the configuration for either a port using a C10 PHY PLL, or in the case of + * the PTL port B eDP on TypeC PHY case the configuration of a port using a C20 + * PHY PLL. + */ +static void mtl_ddi_non_tc_phy_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(encoder); + + /* TODO: Remove when the PLL manager is in place. */ + mtl_ddi_get_config(encoder, crtc_state); + return; + + mtl_ddi_cx0_get_config(encoder, crtc_state, ICL_PORT_DPLL_DEFAULT, + mtl_port_to_pll_id(display, encoder->port)); +} + +static void mtl_ddi_tc_phy_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(encoder); + + /* TODO: Remove when the PLL manager is in place. */ + mtl_ddi_get_config(encoder, crtc_state); + return; + + if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder))) + mtl_ddi_cx0_get_config(encoder, crtc_state, ICL_PORT_DPLL_DEFAULT, + DPLL_ID_ICL_TBTPLL); + else + mtl_ddi_cx0_get_config(encoder, crtc_state, ICL_PORT_DPLL_MG_PHY, + mtl_port_to_pll_id(display, encoder->port)); +} + static void dg2_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state) { @@ -4307,11 +4378,6 @@ static void icl_ddi_combo_get_config(struct intel_encoder *encoder, intel_ddi_get_config(encoder, crtc_state); } -static bool icl_ddi_tc_pll_is_tbt(const struct intel_dpll *pll) -{ - return pll->info->id == DPLL_ID_ICL_TBTPLL; -} - static enum icl_port_dpll_id icl_ddi_tc_port_pll_type(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) @@ -5257,7 +5323,10 @@ void intel_ddi_init(struct intel_display *display, encoder->enable_clock = intel_mtl_pll_enable_clock; encoder->disable_clock = intel_mtl_pll_disable_clock; encoder->port_pll_type = intel_mtl_port_pll_type; - encoder->get_config = mtl_ddi_get_config; + if (intel_encoder_is_tc(encoder)) + encoder->get_config = mtl_ddi_tc_phy_get_config; + else + encoder->get_config = mtl_ddi_non_tc_phy_get_config; } else if (display->platform.dg2) { encoder->enable_clock = intel_mpllb_enable; encoder->disable_clock = intel_mpllb_disable; From 2a6e417907593e908d164c743f812ad6413f3d7b Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:46:01 +0200 Subject: [PATCH 0043/1610] drm/i915/cx0: Add MTL+ Thunderbolt PLL hooks Add the PLL hooks for the TBT PLL on MTL+. These are simple stubs similarly to the TBT PLL on earlier platforms, since this PLL is always on from the display POV - so no PLL enable/disable programming is required as opposed to the non-TBT PLLs - and the clocks for different link rates are enabled/disabled at a different level, via the intel_encoder::enable_clock()/disable_clock() interface. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-32-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 18 +++++++++ drivers/gpu/drm/i915/display/intel_cx0_phy.h | 6 +++ drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 37 ++++++++++++++++++- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 79be234780ba..9d96e8940838 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -3283,6 +3283,24 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder, intel_cx0_phy_transaction_end(encoder, wakeref); } +void intel_mtl_tbt_pll_calc_state(struct intel_dpll_hw_state *hw_state) +{ + memset(hw_state, 0, sizeof(*hw_state)); + + hw_state->cx0pll.tbt_mode = true; +} + +bool intel_mtl_tbt_pll_readout_hw_state(struct intel_display *display, + struct intel_dpll *pll, + struct intel_dpll_hw_state *hw_state) +{ + memset(hw_state, 0, sizeof(*hw_state)); + + hw_state->cx0pll.tbt_mode = true; + + return true; +} + int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index 3745d7081ac7..9f10113e2d18 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -70,7 +70,13 @@ void intel_cx0_write(struct intel_encoder *encoder, int intel_cx0_wait_for_ack(struct intel_encoder *encoder, int command, int lane, u32 *val); void intel_cx0_bus_reset(struct intel_encoder *encoder, int lane); + +void intel_mtl_tbt_pll_calc_state(struct intel_dpll_hw_state *hw_state); +bool intel_mtl_tbt_pll_readout_hw_state(struct intel_display *display, + struct intel_dpll *pll, + struct intel_dpll_hw_state *hw_state); int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder); + void intel_cx0_pll_power_save_wa(struct intel_display *display); void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index ecb7e3761a5b..8fd3b06f393d 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4421,10 +4421,42 @@ static const struct intel_dpll_funcs mtl_pll_funcs = { .get_freq = mtl_pll_get_freq, }; +static void mtl_tbt_pll_enable(struct intel_display *display, + struct intel_dpll *pll, + const struct intel_dpll_hw_state *hw_state) +{ +} + +static void mtl_tbt_pll_disable(struct intel_display *display, + struct intel_dpll *pll) +{ +} + +static int mtl_tbt_pll_get_freq(struct intel_display *display, + const struct intel_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) +{ + /* + * The PLL outputs multiple frequencies at the same time, selection is + * made at DDI clock mux level. + */ + drm_WARN_ON(display->drm, 1); + + return 0; +} + +static const struct intel_dpll_funcs mtl_tbt_pll_funcs = { + .enable = mtl_tbt_pll_enable, + .disable = mtl_tbt_pll_disable, + .get_hw_state = intel_mtl_tbt_pll_readout_hw_state, + .get_freq = mtl_tbt_pll_get_freq, +}; + static const struct dpll_info mtl_plls[] = { { .name = "DPLL 0", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_DPLL0, }, { .name = "DPLL 1", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_DPLL1, }, - /* TODO: Add TBT PLL */ + { .name = "TBT PLL", .funcs = &mtl_tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, + .is_alt_port_dpll = true, .always_on = true }, { .name = "TC PLL 1", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, }, { .name = "TC PLL 2", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, }, { .name = "TC PLL 3", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL3, }, @@ -4470,7 +4502,8 @@ static int mtl_compute_tc_phy_dplls(struct intel_atomic_state *state, struct icl_port_dpll *port_dpll; int ret; - /* TODO: Add state calculation for TBT PLL */ + port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; + intel_mtl_tbt_pll_calc_state(&port_dpll->hw_state); port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY]; ret = intel_cx0pll_calc_state(crtc_state, encoder, &port_dpll->hw_state); From 1a7fad2aea74065dcd81821c681103813fd0772b Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Tue, 18 Nov 2025 15:28:59 +0200 Subject: [PATCH 0044/1610] drm/i915/cx0: Enable dpll framework for MTL+ MTL+ platforms are supported by dpll framework remove a separate check for hw comparison and rely solely on dpll framework hw comparison. Finally, all required hooks are now in place so initialize PLL manager for MTL+ platforms and remove the redirections to the legacy code paths from the following interfaces: * intel_encoder::clock_enable/disable() * intel_encoder::get_config() * intel_dpll_funcs::get_hw_state() * intel_ddi_update_active_dpll() * pipe_config_pll_mismatch() v2: Rebase on !HAS_LT_PHY check in intel_ddi_update_active_dpll() v3: Rebase on !display->dpll.mgr check in intel_ddi_update_active_dpll() Add check for NVL as the platform is not part of pll framework (Suraj) Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251118132859.2584452-1-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 10 ------- drivers/gpu/drm/i915/display/intel_ddi.c | 23 +-------------- drivers/gpu/drm/i915/display/intel_display.c | 29 ------------------- drivers/gpu/drm/i915/display/intel_dpll.c | 23 +-------------- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 7 +++-- 5 files changed, 6 insertions(+), 86 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 9d96e8940838..96ab7f3b5539 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -3432,9 +3432,6 @@ void intel_mtl_pll_enable_clock(struct intel_encoder *encoder, if (intel_tc_port_in_tbt_alt_mode(dig_port)) intel_mtl_tbt_pll_enable_clock(encoder, crtc_state->port_clock); - else - /* TODO: remove when PLL mgr is in place. */ - intel_mtl_pll_enable(encoder, NULL, &crtc_state->dpll_hw_state); } /* @@ -3598,9 +3595,6 @@ void intel_mtl_pll_disable_clock(struct intel_encoder *encoder) if (intel_tc_port_in_tbt_alt_mode(dig_port)) intel_mtl_tbt_pll_disable_clock(encoder); - else - /* TODO: remove when PLL mgr is in place. */ - intel_mtl_pll_disable(encoder); } enum icl_port_dpll_id @@ -3629,10 +3623,6 @@ bool intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, { memset(pll_state, 0, sizeof(*pll_state)); - pll_state->tbt_mode = intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)); - if (pll_state->tbt_mode) - return true; - if (!intel_cx0_pll_is_enabled(encoder)) return false; diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index e7abc3dee017..96fcad6dbb2f 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4257,19 +4257,6 @@ static void xe3plpd_ddi_get_config(struct intel_encoder *encoder, intel_ddi_get_config(encoder, crtc_state); } -static void mtl_ddi_get_config(struct intel_encoder *encoder, - struct intel_crtc_state *crtc_state) -{ - intel_cx0pll_readout_hw_state(encoder, &crtc_state->dpll_hw_state.cx0pll); - - if (crtc_state->dpll_hw_state.cx0pll.tbt_mode) - crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder); - else - crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->dpll_hw_state.cx0pll); - - intel_ddi_get_config(encoder, crtc_state); -} - static bool icl_ddi_tc_pll_is_tbt(const struct intel_dpll *pll) { return pll->info->id == DPLL_ID_ICL_TBTPLL; @@ -4316,10 +4303,6 @@ static void mtl_ddi_non_tc_phy_get_config(struct intel_encoder *encoder, { struct intel_display *display = to_intel_display(encoder); - /* TODO: Remove when the PLL manager is in place. */ - mtl_ddi_get_config(encoder, crtc_state); - return; - mtl_ddi_cx0_get_config(encoder, crtc_state, ICL_PORT_DPLL_DEFAULT, mtl_port_to_pll_id(display, encoder->port)); } @@ -4329,10 +4312,6 @@ static void mtl_ddi_tc_phy_get_config(struct intel_encoder *encoder, { struct intel_display *display = to_intel_display(encoder); - /* TODO: Remove when the PLL manager is in place. */ - mtl_ddi_get_config(encoder, crtc_state); - return; - if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder))) mtl_ddi_cx0_get_config(encoder, crtc_state, ICL_PORT_DPLL_DEFAULT, DPLL_ID_ICL_TBTPLL); @@ -5322,7 +5301,7 @@ void intel_ddi_init(struct intel_display *display, } else if (DISPLAY_VER(display) >= 14) { encoder->enable_clock = intel_mtl_pll_enable_clock; encoder->disable_clock = intel_mtl_pll_disable_clock; - encoder->port_pll_type = intel_mtl_port_pll_type; + encoder->port_pll_type = icl_ddi_tc_port_pll_type; if (intel_encoder_is_tc(encoder)) encoder->get_config = mtl_ddi_tc_phy_get_config; else diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e7bb8ec0d6bb..6c8a7f63111e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4977,23 +4977,6 @@ pipe_config_pll_mismatch(struct drm_printer *p, bool fastset, intel_dpll_dump_hw_state(display, p, b); } -static void -pipe_config_cx0pll_mismatch(struct drm_printer *p, bool fastset, - const struct intel_crtc *crtc, - const char *name, - const struct intel_cx0pll_state *a, - const struct intel_cx0pll_state *b) -{ - char *chipname = a->use_c10 ? "C10" : "C20"; - - pipe_config_mismatch(p, fastset, crtc, name, chipname); - - drm_printf(p, "expected:\n"); - intel_cx0pll_dump_hw_state(p, a); - drm_printf(p, "found:\n"); - intel_cx0pll_dump_hw_state(p, b); -} - static bool allow_vblank_delay_fastset(const struct intel_crtc_state *old_crtc_state) { struct intel_display *display = to_intel_display(old_crtc_state); @@ -5145,16 +5128,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, } \ } while (0) -#define PIPE_CONF_CHECK_PLL_CX0(name) do { \ - if (!intel_cx0pll_compare_hw_state(¤t_config->name, \ - &pipe_config->name)) { \ - pipe_config_cx0pll_mismatch(&p, fastset, crtc, __stringify(name), \ - ¤t_config->name, \ - &pipe_config->name); \ - ret = false; \ - } \ -} while (0) - #define PIPE_CONF_CHECK_PLL_LT(name) do { \ if (!intel_lt_phy_pll_compare_hw_state(¤t_config->name, \ &pipe_config->name)) { \ @@ -5394,8 +5367,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, /* FIXME convert MTL+ platforms over to dpll_mgr */ if (HAS_LT_PHY(display)) PIPE_CONF_CHECK_PLL_LT(dpll_hw_state.ltpll); - else if (DISPLAY_VER(display) >= 14) - PIPE_CONF_CHECK_PLL_CX0(dpll_hw_state.cx0pll); PIPE_CONF_CHECK_X(dsi_pll.ctrl); PIPE_CONF_CHECK_X(dsi_pll.div); diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 2da65bb20f1c..a4f372c9e6fc 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1212,27 +1212,6 @@ static int dg2_crtc_compute_clock(struct intel_atomic_state *state, return 0; } -static int mtl_crtc_compute_clock(struct intel_atomic_state *state, - struct intel_crtc *crtc) -{ - struct intel_crtc_state *crtc_state = - intel_atomic_get_new_crtc_state(state, crtc); - struct intel_encoder *encoder = - intel_get_crtc_new_encoder(state, crtc_state); - int ret; - - ret = intel_cx0pll_calc_state(crtc_state, encoder, &crtc_state->dpll_hw_state); - if (ret) - return ret; - - /* TODO: Do the readback via intel_dpll_compute() */ - crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->dpll_hw_state.cx0pll); - - crtc_state->hw.adjusted_mode.crtc_clock = intel_crtc_dotclock(crtc_state); - - return 0; -} - static int xe3plpd_crtc_compute_clock(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -1719,7 +1698,7 @@ static const struct intel_dpll_global_funcs xe3plpd_dpll_funcs = { }; static const struct intel_dpll_global_funcs mtl_dpll_funcs = { - .crtc_compute_clock = mtl_crtc_compute_clock, + .crtc_compute_clock = hsw_crtc_compute_clock, .crtc_get_dpll = hsw_crtc_get_dpll, }; diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 8fd3b06f393d..6d7d5394713d 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4558,7 +4558,6 @@ static bool mtl_compare_hw_state(const struct intel_dpll_hw_state *_a, return intel_cx0pll_compare_hw_state(a, b); } -__maybe_unused static const struct intel_dpll_mgr mtl_pll_mgr = { .dpll_info = mtl_plls, .compute_dplls = mtl_compute_dplls, @@ -4584,9 +4583,11 @@ void intel_dpll_init(struct intel_display *display) mutex_init(&display->dpll.lock); - if (DISPLAY_VER(display) >= 14 || display->platform.dg2) - /* No shared DPLLs on DG2; port PLLs are part of the PHY */ + if (DISPLAY_VER(display) >= 35 || display->platform.dg2) + /* No shared DPLLs on NVL or DG2; port PLLs are part of the PHY */ dpll_mgr = NULL; + else if (DISPLAY_VER(display) >= 14) + dpll_mgr = &mtl_pll_mgr; else if (display->platform.alderlake_p) dpll_mgr = &adlp_pll_mgr; else if (display->platform.alderlake_s) From 0a4c2ddc711a9a0d3d9566379b217f2ae42d6152 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 12:26:05 -0800 Subject: [PATCH 0045/1610] drm/xe/vm: Use for_each_tlb_inval() to calculate invalidation fences ops_execute() calculates the size of a fence array based on XE_MAX_GT_PER_TILE, while the code that actually fills in the fence array uses a for_each_tlb_inval() iterator. This works out okay today since both approaches come up with the same number of invalidation fences (2: primary GT invalidation + media GT invalidation), but could be problematic in the future if there isn't a 1:1 relationship between TLBs needing invalidation and potential GTs on the tile. Adjust the allocation code to use the same for_each_tlb_inval() counting logic as the code that fills the array to future-proof the code. Reviewed-by: Matthew Brost Link: https://patch.msgid.link/20251118202604.3715782-2-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_vm.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 7cac646bdf1c..f9989a7a710c 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -3104,19 +3104,19 @@ static struct dma_fence *ops_execute(struct xe_vm *vm, struct dma_fence *fence = NULL; struct dma_fence **fences = NULL; struct dma_fence_array *cf = NULL; - int number_tiles = 0, current_fence = 0, n_fence = 0, err; + int number_tiles = 0, current_fence = 0, n_fence = 0, err, i; u8 id; number_tiles = vm_ops_setup_tile_args(vm, vops); if (number_tiles == 0) return ERR_PTR(-ENODATA); - if (vops->flags & XE_VMA_OPS_FLAG_SKIP_TLB_WAIT) { - for_each_tile(tile, vm->xe, id) - ++n_fence; - } else { - for_each_tile(tile, vm->xe, id) - n_fence += (1 + XE_MAX_GT_PER_TILE); + for_each_tile(tile, vm->xe, id) { + ++n_fence; + + if (!(vops->flags & XE_VMA_OPS_FLAG_SKIP_TLB_WAIT)) + for_each_tlb_inval(i) + ++n_fence; } fences = kmalloc_array(n_fence, sizeof(*fences), GFP_KERNEL); @@ -3146,7 +3146,6 @@ static struct dma_fence *ops_execute(struct xe_vm *vm, for_each_tile(tile, vm->xe, id) { struct xe_exec_queue *q = vops->pt_update_ops[tile->id].q; - int i; fence = NULL; if (!vops->pt_update_ops[id].num_ops) From 5b23aa423a637358a4b98cd18a4da020ca8398bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 29 Oct 2025 22:42:13 +0200 Subject: [PATCH 0046/1610] drm/i915/dram: Use REG_GENMASK() & co. for the SKL+ DIMM regs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modernize the SKL/ICL DIMM registers with REG_GENMASK() & co. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20251029204215.12292-2-ville.syrjala@linux.intel.com Reviewed-by: Lucas De Marchi --- drivers/gpu/drm/i915/intel_mchbar_regs.h | 51 +++++++++++------------- drivers/gpu/drm/i915/soc/intel_dram.c | 12 +++--- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_mchbar_regs.h b/drivers/gpu/drm/i915/intel_mchbar_regs.h index dc2477179c3e..378dc7c69f7d 100644 --- a/drivers/gpu/drm/i915/intel_mchbar_regs.h +++ b/drivers/gpu/drm/i915/intel_mchbar_regs.h @@ -130,11 +130,11 @@ #define DG1_DRAM_T_RAS_MASK REG_GENMASK(8, 1) #define SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5000) -#define SKL_DRAM_DDR_TYPE_MASK (0x3 << 0) -#define SKL_DRAM_DDR_TYPE_DDR4 (0 << 0) -#define SKL_DRAM_DDR_TYPE_DDR3 (1 << 0) -#define SKL_DRAM_DDR_TYPE_LPDDR3 (2 << 0) -#define SKL_DRAM_DDR_TYPE_LPDDR4 (3 << 0) +#define SKL_DRAM_DDR_TYPE_MASK REG_GENMASK(1, 0) +#define SKL_DRAM_DDR_TYPE_DDR4 REG_FIELD_PREP(SKL_DRAM_DDR_TYPE_MASK, 0) +#define SKL_DRAM_DDR_TYPE_DDR3 REG_FIELD_PREP(SKL_DRAM_DDR_TYPE_MASK, 1) +#define SKL_DRAM_DDR_TYPE_LPDDR3 REG_FIELD_PREP(SKL_DRAM_DDR_TYPE_MASK, 2) +#define SKL_DRAM_DDR_TYPE_LPDDR4 REG_FIELD_PREP(SKL_DRAM_DDR_TYPE_MASK, 3) /* snb MCH registers for reading the DRAM channel configuration */ #define MAD_DIMM_C0 _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5004) @@ -161,29 +161,24 @@ #define SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x500C) #define SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5010) #define SKL_DRAM_S_SHIFT 16 -#define SKL_DRAM_SIZE_MASK 0x3F -#define SKL_DRAM_WIDTH_MASK (0x3 << 8) -#define SKL_DRAM_WIDTH_SHIFT 8 -#define SKL_DRAM_WIDTH_X8 (0x0 << 8) -#define SKL_DRAM_WIDTH_X16 (0x1 << 8) -#define SKL_DRAM_WIDTH_X32 (0x2 << 8) -#define SKL_DRAM_RANK_MASK (0x1 << 10) -#define SKL_DRAM_RANK_SHIFT 10 -#define SKL_DRAM_RANK_1 (0x0 << 10) -#define SKL_DRAM_RANK_2 (0x1 << 10) -#define SKL_DRAM_RANK_MASK (0x1 << 10) -#define ICL_DRAM_SIZE_MASK 0x7F -#define ICL_DRAM_WIDTH_MASK (0x3 << 7) -#define ICL_DRAM_WIDTH_SHIFT 7 -#define ICL_DRAM_WIDTH_X8 (0x0 << 7) -#define ICL_DRAM_WIDTH_X16 (0x1 << 7) -#define ICL_DRAM_WIDTH_X32 (0x2 << 7) -#define ICL_DRAM_RANK_MASK (0x3 << 9) -#define ICL_DRAM_RANK_SHIFT 9 -#define ICL_DRAM_RANK_1 (0x0 << 9) -#define ICL_DRAM_RANK_2 (0x1 << 9) -#define ICL_DRAM_RANK_3 (0x2 << 9) -#define ICL_DRAM_RANK_4 (0x3 << 9) +#define SKL_DRAM_SIZE_MASK REG_GENMASK(5, 0) +#define SKL_DRAM_WIDTH_MASK REG_GENMASK(9, 8) +#define SKL_DRAM_WIDTH_X8 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 0) +#define SKL_DRAM_WIDTH_X16 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 1) +#define SKL_DRAM_WIDTH_X32 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 2) +#define SKL_DRAM_RANK_MASK REG_GENMASK(10, 10) +#define SKL_DRAM_RANK_1 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 0) +#define SKL_DRAM_RANK_2 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 1) +#define ICL_DRAM_SIZE_MASK REG_GENMASK(6, 0) +#define ICL_DRAM_WIDTH_MASK REG_GENMASK(8, 7) +#define ICL_DRAM_WIDTH_X8 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 0) +#define ICL_DRAM_WIDTH_X16 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 1) +#define ICL_DRAM_WIDTH_X32 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 2) +#define ICL_DRAM_RANK_MASK REG_GENMASK(10, 9) +#define ICL_DRAM_RANK_1 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 0) +#define ICL_DRAM_RANK_2 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 1) +#define ICL_DRAM_RANK_3 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 2) +#define ICL_DRAM_RANK_4 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 3) #define SA_PERF_STATUS_0_0_0_MCHBAR_PC _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5918) #define DG1_QCLK_RATIO_MASK REG_GENMASK(9, 2) diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index 3e588762709a..4925d73d49e1 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -269,7 +269,7 @@ static int intel_dimm_num_devices(const struct dram_dimm_info *dimm) /* Returns total Gb for the whole DIMM */ static int skl_get_dimm_size(u16 val) { - return (val & SKL_DRAM_SIZE_MASK) * 8; + return REG_FIELD_GET(SKL_DRAM_SIZE_MASK, val) * 8; } static int skl_get_dimm_width(u16 val) @@ -281,7 +281,7 @@ static int skl_get_dimm_width(u16 val) case SKL_DRAM_WIDTH_X8: case SKL_DRAM_WIDTH_X16: case SKL_DRAM_WIDTH_X32: - val = (val & SKL_DRAM_WIDTH_MASK) >> SKL_DRAM_WIDTH_SHIFT; + val = REG_FIELD_GET(SKL_DRAM_WIDTH_MASK, val); return 8 << val; default: MISSING_CASE(val); @@ -294,7 +294,7 @@ static int skl_get_dimm_ranks(u16 val) if (skl_get_dimm_size(val) == 0) return 0; - val = (val & SKL_DRAM_RANK_MASK) >> SKL_DRAM_RANK_SHIFT; + val = REG_FIELD_GET(SKL_DRAM_RANK_MASK, val); return val + 1; } @@ -302,7 +302,7 @@ static int skl_get_dimm_ranks(u16 val) /* Returns total Gb for the whole DIMM */ static int icl_get_dimm_size(u16 val) { - return (val & ICL_DRAM_SIZE_MASK) * 8 / 2; + return REG_FIELD_GET(ICL_DRAM_SIZE_MASK, val) * 8 / 2; } static int icl_get_dimm_width(u16 val) @@ -314,7 +314,7 @@ static int icl_get_dimm_width(u16 val) case ICL_DRAM_WIDTH_X8: case ICL_DRAM_WIDTH_X16: case ICL_DRAM_WIDTH_X32: - val = (val & ICL_DRAM_WIDTH_MASK) >> ICL_DRAM_WIDTH_SHIFT; + val = REG_FIELD_GET(ICL_DRAM_WIDTH_MASK, val); return 8 << val; default: MISSING_CASE(val); @@ -327,7 +327,7 @@ static int icl_get_dimm_ranks(u16 val) if (icl_get_dimm_size(val) == 0) return 0; - val = (val & ICL_DRAM_RANK_MASK) >> ICL_DRAM_RANK_SHIFT; + val = REG_FIELD_GET(ICL_DRAM_RANK_MASK, val); return val + 1; } From 8c171a9b8c4cb10b1942d3094f94e27c65232cf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 29 Oct 2025 22:42:14 +0200 Subject: [PATCH 0047/1610] drm/i915/dram: Sort SKL+ DIMM register bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the customary big endian order when defining the SKL/ICL DIMM registers. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20251029204215.12292-3-ville.syrjala@linux.intel.com Reviewed-by: Lucas De Marchi --- drivers/gpu/drm/i915/intel_mchbar_regs.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_mchbar_regs.h b/drivers/gpu/drm/i915/intel_mchbar_regs.h index 378dc7c69f7d..a46a45b9d2e1 100644 --- a/drivers/gpu/drm/i915/intel_mchbar_regs.h +++ b/drivers/gpu/drm/i915/intel_mchbar_regs.h @@ -161,24 +161,24 @@ #define SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x500C) #define SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5010) #define SKL_DRAM_S_SHIFT 16 -#define SKL_DRAM_SIZE_MASK REG_GENMASK(5, 0) +#define SKL_DRAM_RANK_MASK REG_GENMASK(10, 10) +#define SKL_DRAM_RANK_1 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 0) +#define SKL_DRAM_RANK_2 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 1) #define SKL_DRAM_WIDTH_MASK REG_GENMASK(9, 8) #define SKL_DRAM_WIDTH_X8 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 0) #define SKL_DRAM_WIDTH_X16 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 1) #define SKL_DRAM_WIDTH_X32 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 2) -#define SKL_DRAM_RANK_MASK REG_GENMASK(10, 10) -#define SKL_DRAM_RANK_1 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 0) -#define SKL_DRAM_RANK_2 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 1) -#define ICL_DRAM_SIZE_MASK REG_GENMASK(6, 0) -#define ICL_DRAM_WIDTH_MASK REG_GENMASK(8, 7) -#define ICL_DRAM_WIDTH_X8 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 0) -#define ICL_DRAM_WIDTH_X16 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 1) -#define ICL_DRAM_WIDTH_X32 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 2) +#define SKL_DRAM_SIZE_MASK REG_GENMASK(5, 0) #define ICL_DRAM_RANK_MASK REG_GENMASK(10, 9) #define ICL_DRAM_RANK_1 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 0) #define ICL_DRAM_RANK_2 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 1) #define ICL_DRAM_RANK_3 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 2) #define ICL_DRAM_RANK_4 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 3) +#define ICL_DRAM_WIDTH_MASK REG_GENMASK(8, 7) +#define ICL_DRAM_WIDTH_X8 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 0) +#define ICL_DRAM_WIDTH_X16 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 1) +#define ICL_DRAM_WIDTH_X32 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 2) +#define ICL_DRAM_SIZE_MASK REG_GENMASK(6, 0) #define SA_PERF_STATUS_0_0_0_MCHBAR_PC _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5918) #define DG1_QCLK_RATIO_MASK REG_GENMASK(9, 2) From 7e2d78535432e44f908c6c44f73828cfd9c12aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 29 Oct 2025 22:42:15 +0200 Subject: [PATCH 0048/1610] drm/i915/dram: Fix ICL DIMM_S decoding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unfortunately the MAD_DIMM DIMM_S and DIMM_L bits on ICL are not idential, so we are currently decoding DIMM_S incorrectly. Fix the problem by defining the DIMM_S and DIMM_L bits separately. And for consistency do that same for SKL, even though there the bits do match between the two DIMMs. The result is rather repetitive in places, but I didn't feel like obfuscatign things with cpp macros/etc. Broken decoding on Dell XPS 13 7390 2-in-1: CH0 DIMM L size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no CH0 DIMM S size: 32 Gb, width: X32, ranks: 3, 16Gb+ DIMMs: no CH0 ranks: 2, 16Gb+ DIMMs: no CH1 DIMM L size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no CH1 DIMM S size: 32 Gb, width: X32, ranks: 3, 16Gb+ DIMMs: no CH1 ranks: 2, 16Gb+ DIMMs: no Memory configuration is symmetric? no Fixed decoding on Dell XPS 13 7390 2-in-1: CH0 DIMM L size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no CH0 DIMM S size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no CH0 ranks: 2, 16Gb+ DIMMs: no CH1 DIMM L size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no CH1 DIMM S size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no CH1 ranks: 2, 16Gb+ DIMMs: no Memory configuration is symmetric? yes Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20251029204215.12292-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/intel_mchbar_regs.h | 53 +++++--- drivers/gpu/drm/i915/soc/intel_dram.c | 166 +++++++++++++++++------ 2 files changed, 155 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_mchbar_regs.h b/drivers/gpu/drm/i915/intel_mchbar_regs.h index a46a45b9d2e1..614d4017b57b 100644 --- a/drivers/gpu/drm/i915/intel_mchbar_regs.h +++ b/drivers/gpu/drm/i915/intel_mchbar_regs.h @@ -160,25 +160,40 @@ #define SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x500C) #define SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5010) -#define SKL_DRAM_S_SHIFT 16 -#define SKL_DRAM_RANK_MASK REG_GENMASK(10, 10) -#define SKL_DRAM_RANK_1 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 0) -#define SKL_DRAM_RANK_2 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 1) -#define SKL_DRAM_WIDTH_MASK REG_GENMASK(9, 8) -#define SKL_DRAM_WIDTH_X8 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 0) -#define SKL_DRAM_WIDTH_X16 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 1) -#define SKL_DRAM_WIDTH_X32 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 2) -#define SKL_DRAM_SIZE_MASK REG_GENMASK(5, 0) -#define ICL_DRAM_RANK_MASK REG_GENMASK(10, 9) -#define ICL_DRAM_RANK_1 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 0) -#define ICL_DRAM_RANK_2 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 1) -#define ICL_DRAM_RANK_3 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 2) -#define ICL_DRAM_RANK_4 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 3) -#define ICL_DRAM_WIDTH_MASK REG_GENMASK(8, 7) -#define ICL_DRAM_WIDTH_X8 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 0) -#define ICL_DRAM_WIDTH_X16 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 1) -#define ICL_DRAM_WIDTH_X32 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 2) -#define ICL_DRAM_SIZE_MASK REG_GENMASK(6, 0) +#define SKL_DIMM_S_RANK_MASK REG_GENMASK(26, 26) +#define SKL_DIMM_S_RANK_1 REG_FIELD_PREP(SKL_DIMM_S_RANK_MASK, 0) +#define SKL_DIMM_S_RANK_2 REG_FIELD_PREP(SKL_DIMM_S_RANK_MASK, 1) +#define SKL_DIMM_S_WIDTH_MASK REG_GENMASK(25, 24) +#define SKL_DIMM_S_WIDTH_X8 REG_FIELD_PREP(SKL_DIMM_S_WIDTH_MASK, 0) +#define SKL_DIMM_S_WIDTH_X16 REG_FIELD_PREP(SKL_DIMM_S_WIDTH_MASK, 1) +#define SKL_DIMM_S_WIDTH_X32 REG_FIELD_PREP(SKL_DIMM_S_WIDTH_MASK, 2) +#define SKL_DIMM_S_SIZE_MASK REG_GENMASK(21, 16) +#define SKL_DIMM_L_RANK_MASK REG_GENMASK(10, 10) +#define SKL_DIMM_L_RANK_1 REG_FIELD_PREP(SKL_DIMM_L_RANK_MASK, 0) +#define SKL_DIMM_L_RANK_2 REG_FIELD_PREP(SKL_DIMM_L_RANK_MASK, 1) +#define SKL_DIMM_L_WIDTH_MASK REG_GENMASK(9, 8) +#define SKL_DIMM_L_WIDTH_X8 REG_FIELD_PREP(SKL_DIMM_L_WIDTH_MASK, 0) +#define SKL_DIMM_L_WIDTH_X16 REG_FIELD_PREP(SKL_DIMM_L_WIDTH_MASK, 1) +#define SKL_DIMM_L_WIDTH_X32 REG_FIELD_PREP(SKL_DIMM_L_WIDTH_MASK, 2) +#define SKL_DIMM_L_SIZE_MASK REG_GENMASK(5, 0) +#define ICL_DIMM_S_RANK_MASK REG_GENMASK(27, 26) +#define ICL_DIMM_S_RANK_1 REG_FIELD_PREP(ICL_DIMM_S_RANK_MASK, 0) +#define ICL_DIMM_S_RANK_2 REG_FIELD_PREP(ICL_DIMM_S_RANK_MASK, 1) +#define ICL_DIMM_S_WIDTH_MASK REG_GENMASK(25, 24) +#define ICL_DIMM_S_WIDTH_X8 REG_FIELD_PREP(ICL_DIMM_S_WIDTH_MASK, 0) +#define ICL_DIMM_S_WIDTH_X16 REG_FIELD_PREP(ICL_DIMM_S_WIDTH_MASK, 1) +#define ICL_DIMM_S_WIDTH_X32 REG_FIELD_PREP(ICL_DIMM_S_WIDTH_MASK, 2) +#define ICL_DIMM_S_SIZE_MASK REG_GENMASK(22, 16) +#define ICL_DIMM_L_RANK_MASK REG_GENMASK(10, 9) +#define ICL_DIMM_L_RANK_1 REG_FIELD_PREP(ICL_DIMM_L_RANK_MASK, 0) +#define ICL_DIMM_L_RANK_2 REG_FIELD_PREP(ICL_DIMM_L_RANK_MASK, 1) +#define ICL_DIMM_L_RANK_3 REG_FIELD_PREP(ICL_DIMM_L_RANK_MASK, 2) +#define ICL_DIMM_L_RANK_4 REG_FIELD_PREP(ICL_DIMM_L_RANK_MASK, 3) +#define ICL_DIMM_L_WIDTH_MASK REG_GENMASK(8, 7) +#define ICL_DIMM_L_WIDTH_X8 REG_FIELD_PREP(ICL_DIMM_L_WIDTH_MASK, 0) +#define ICL_DIMM_L_WIDTH_X16 REG_FIELD_PREP(ICL_DIMM_L_WIDTH_MASK, 1) +#define ICL_DIMM_L_WIDTH_X32 REG_FIELD_PREP(ICL_DIMM_L_WIDTH_MASK, 2) +#define ICL_DIMM_L_SIZE_MASK REG_GENMASK(6, 0) #define SA_PERF_STATUS_0_0_0_MCHBAR_PC _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5918) #define DG1_QCLK_RATIO_MASK REG_GENMASK(9, 2) diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index 4925d73d49e1..739cfe48f6db 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -267,69 +267,121 @@ static int intel_dimm_num_devices(const struct dram_dimm_info *dimm) } /* Returns total Gb for the whole DIMM */ -static int skl_get_dimm_size(u16 val) +static int skl_get_dimm_s_size(u32 val) { - return REG_FIELD_GET(SKL_DRAM_SIZE_MASK, val) * 8; + return REG_FIELD_GET(SKL_DIMM_S_SIZE_MASK, val) * 8; } -static int skl_get_dimm_width(u16 val) +static int skl_get_dimm_l_size(u32 val) { - if (skl_get_dimm_size(val) == 0) + return REG_FIELD_GET(SKL_DIMM_L_SIZE_MASK, val) * 8; +} + +static int skl_get_dimm_s_width(u32 val) +{ + if (skl_get_dimm_s_size(val) == 0) return 0; - switch (val & SKL_DRAM_WIDTH_MASK) { - case SKL_DRAM_WIDTH_X8: - case SKL_DRAM_WIDTH_X16: - case SKL_DRAM_WIDTH_X32: - val = REG_FIELD_GET(SKL_DRAM_WIDTH_MASK, val); - return 8 << val; + switch (val & SKL_DIMM_S_WIDTH_MASK) { + case SKL_DIMM_S_WIDTH_X8: + case SKL_DIMM_S_WIDTH_X16: + case SKL_DIMM_S_WIDTH_X32: + return 8 << REG_FIELD_GET(SKL_DIMM_S_WIDTH_MASK, val); default: MISSING_CASE(val); return 0; } } -static int skl_get_dimm_ranks(u16 val) +static int skl_get_dimm_l_width(u32 val) { - if (skl_get_dimm_size(val) == 0) + if (skl_get_dimm_l_size(val) == 0) return 0; - val = REG_FIELD_GET(SKL_DRAM_RANK_MASK, val); + switch (val & SKL_DIMM_L_WIDTH_MASK) { + case SKL_DIMM_L_WIDTH_X8: + case SKL_DIMM_L_WIDTH_X16: + case SKL_DIMM_L_WIDTH_X32: + return 8 << REG_FIELD_GET(SKL_DIMM_L_WIDTH_MASK, val); + default: + MISSING_CASE(val); + return 0; + } +} - return val + 1; +static int skl_get_dimm_s_ranks(u32 val) +{ + if (skl_get_dimm_s_size(val) == 0) + return 0; + + return REG_FIELD_GET(SKL_DIMM_S_RANK_MASK, val) + 1; +} + +static int skl_get_dimm_l_ranks(u32 val) +{ + if (skl_get_dimm_l_size(val) == 0) + return 0; + + return REG_FIELD_GET(SKL_DIMM_L_RANK_MASK, val) + 1; } /* Returns total Gb for the whole DIMM */ -static int icl_get_dimm_size(u16 val) +static int icl_get_dimm_s_size(u32 val) { - return REG_FIELD_GET(ICL_DRAM_SIZE_MASK, val) * 8 / 2; + return REG_FIELD_GET(ICL_DIMM_S_SIZE_MASK, val) * 8 / 2; } -static int icl_get_dimm_width(u16 val) +static int icl_get_dimm_l_size(u32 val) { - if (icl_get_dimm_size(val) == 0) + return REG_FIELD_GET(ICL_DIMM_L_SIZE_MASK, val) * 8 / 2; +} + +static int icl_get_dimm_s_width(u32 val) +{ + if (icl_get_dimm_s_size(val) == 0) return 0; - switch (val & ICL_DRAM_WIDTH_MASK) { - case ICL_DRAM_WIDTH_X8: - case ICL_DRAM_WIDTH_X16: - case ICL_DRAM_WIDTH_X32: - val = REG_FIELD_GET(ICL_DRAM_WIDTH_MASK, val); - return 8 << val; + switch (val & ICL_DIMM_S_WIDTH_MASK) { + case ICL_DIMM_S_WIDTH_X8: + case ICL_DIMM_S_WIDTH_X16: + case ICL_DIMM_S_WIDTH_X32: + return 8 << REG_FIELD_GET(ICL_DIMM_S_WIDTH_MASK, val); default: MISSING_CASE(val); return 0; } } -static int icl_get_dimm_ranks(u16 val) +static int icl_get_dimm_l_width(u32 val) { - if (icl_get_dimm_size(val) == 0) + if (icl_get_dimm_l_size(val) == 0) return 0; - val = REG_FIELD_GET(ICL_DRAM_RANK_MASK, val); + switch (val & ICL_DIMM_L_WIDTH_MASK) { + case ICL_DIMM_L_WIDTH_X8: + case ICL_DIMM_L_WIDTH_X16: + case ICL_DIMM_L_WIDTH_X32: + return 8 << REG_FIELD_GET(ICL_DIMM_L_WIDTH_MASK, val); + default: + MISSING_CASE(val); + return 0; + } +} - return val + 1; +static int icl_get_dimm_s_ranks(u32 val) +{ + if (icl_get_dimm_s_size(val) == 0) + return 0; + + return REG_FIELD_GET(ICL_DIMM_S_RANK_MASK, val) + 1; +} + +static int icl_get_dimm_l_ranks(u32 val) +{ + if (icl_get_dimm_l_size(val) == 0) + return 0; + + return REG_FIELD_GET(ICL_DIMM_L_RANK_MASK, val) + 1; } static bool @@ -340,35 +392,59 @@ skl_is_16gb_dimm(const struct dram_dimm_info *dimm) } static void -skl_dram_get_dimm_info(struct drm_i915_private *i915, - struct dram_dimm_info *dimm, - int channel, char dimm_name, u16 val) +skl_dram_print_dimm_info(struct drm_i915_private *i915, + struct dram_dimm_info *dimm, + int channel, char dimm_name) { - if (GRAPHICS_VER(i915) >= 11) { - dimm->size = icl_get_dimm_size(val); - dimm->width = icl_get_dimm_width(val); - dimm->ranks = icl_get_dimm_ranks(val); - } else { - dimm->size = skl_get_dimm_size(val); - dimm->width = skl_get_dimm_width(val); - dimm->ranks = skl_get_dimm_ranks(val); - } - drm_dbg_kms(&i915->drm, "CH%u DIMM %c size: %u Gb, width: X%u, ranks: %u, 16Gb+ DIMMs: %s\n", channel, dimm_name, dimm->size, dimm->width, dimm->ranks, str_yes_no(skl_is_16gb_dimm(dimm))); } +static void +skl_dram_get_dimm_l_info(struct drm_i915_private *i915, + struct dram_dimm_info *dimm, + int channel, u32 val) +{ + if (GRAPHICS_VER(i915) >= 11) { + dimm->size = icl_get_dimm_l_size(val); + dimm->width = icl_get_dimm_l_width(val); + dimm->ranks = icl_get_dimm_l_ranks(val); + } else { + dimm->size = skl_get_dimm_l_size(val); + dimm->width = skl_get_dimm_l_width(val); + dimm->ranks = skl_get_dimm_l_ranks(val); + } + + skl_dram_print_dimm_info(i915, dimm, channel, 'L'); +} + +static void +skl_dram_get_dimm_s_info(struct drm_i915_private *i915, + struct dram_dimm_info *dimm, + int channel, u32 val) +{ + if (GRAPHICS_VER(i915) >= 11) { + dimm->size = icl_get_dimm_s_size(val); + dimm->width = icl_get_dimm_s_width(val); + dimm->ranks = icl_get_dimm_s_ranks(val); + } else { + dimm->size = skl_get_dimm_s_size(val); + dimm->width = skl_get_dimm_s_width(val); + dimm->ranks = skl_get_dimm_s_ranks(val); + } + + skl_dram_print_dimm_info(i915, dimm, channel, 'S'); +} + static int skl_dram_get_channel_info(struct drm_i915_private *i915, struct dram_channel_info *ch, int channel, u32 val) { - skl_dram_get_dimm_info(i915, &ch->dimm_l, - channel, 'L', val & 0xffff); - skl_dram_get_dimm_info(i915, &ch->dimm_s, - channel, 'S', val >> 16); + skl_dram_get_dimm_l_info(i915, &ch->dimm_l, channel, val); + skl_dram_get_dimm_s_info(i915, &ch->dimm_s, channel, val); if (ch->dimm_l.size == 0 && ch->dimm_s.size == 0) { drm_dbg_kms(&i915->drm, "CH%u not populated\n", channel); From b9241d0ed9cefc7f9b9bb65533494d7776964d79 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:08 +0200 Subject: [PATCH 0049/1610] drm/{i915, xe}/display: duplicate gen2 irq/error init/reset in display irq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Duplicate gen2_irq_reset(), gen2_assert_iir_is_zero(), gen2_irq_init(), gen2_error_reset(), and gen2_error_init() in intel_display_irq.c. This allows us to drop the duplicates from xe, and prepares for future cleanups. Although duplication is undesirable in general, in this case the local duplicates lead to a cleaner end result. There's a slight wrinkle in gen2_assert_iir_is_zero(). We need to use non-device based logging until we pass in struct intel_display in a separate change. v2: - Keep xe compat stuff due to series reorder and rebase - Keep the WARN as regular WARN - Rename the functions in the same go Suggested-by: Ville Syrjala Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/296d74731cce57ab7534c57969d3146294adda57.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../gpu/drm/i915/display/intel_display_irq.c | 82 +++++++++++++++++-- drivers/gpu/drm/xe/display/ext/i915_irq.c | 67 --------------- 2 files changed, 73 insertions(+), 76 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index 43b27deb4a26..acfaff13c3ba 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -33,6 +33,72 @@ #include "intel_psr_regs.h" #include "intel_uncore.h" +static void irq_reset(struct intel_uncore *uncore, struct i915_irq_regs regs) +{ + intel_uncore_write(uncore, regs.imr, 0xffffffff); + intel_uncore_posting_read(uncore, regs.imr); + + intel_uncore_write(uncore, regs.ier, 0); + + /* IIR can theoretically queue up two events. Be paranoid. */ + intel_uncore_write(uncore, regs.iir, 0xffffffff); + intel_uncore_posting_read(uncore, regs.iir); + intel_uncore_write(uncore, regs.iir, 0xffffffff); + intel_uncore_posting_read(uncore, regs.iir); +} + +/* + * We should clear IMR at preinstall/uninstall, and just check at postinstall. + */ +static void assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg) +{ + u32 val = intel_uncore_read(uncore, reg); + + if (val == 0) + return; + + WARN(1, + "Interrupt register 0x%x is not zero: 0x%08x\n", + i915_mmio_reg_offset(reg), val); + intel_uncore_write(uncore, reg, 0xffffffff); + intel_uncore_posting_read(uncore, reg); + intel_uncore_write(uncore, reg, 0xffffffff); + intel_uncore_posting_read(uncore, reg); +} + +static void irq_init(struct intel_uncore *uncore, struct i915_irq_regs regs, + u32 imr_val, u32 ier_val) +{ + assert_iir_is_zero(uncore, regs.iir); + + intel_uncore_write(uncore, regs.ier, ier_val); + intel_uncore_write(uncore, regs.imr, imr_val); + intel_uncore_posting_read(uncore, regs.imr); +} + +static void error_reset(struct intel_uncore *uncore, struct i915_error_regs regs) +{ + intel_uncore_write(uncore, regs.emr, 0xffffffff); + intel_uncore_posting_read(uncore, regs.emr); + + intel_uncore_write(uncore, regs.eir, 0xffffffff); + intel_uncore_posting_read(uncore, regs.eir); + intel_uncore_write(uncore, regs.eir, 0xffffffff); + intel_uncore_posting_read(uncore, regs.eir); +} + +static void error_init(struct intel_uncore *uncore, struct i915_error_regs regs, + u32 emr_val) +{ + intel_uncore_write(uncore, regs.eir, 0xffffffff); + intel_uncore_posting_read(uncore, regs.eir); + intel_uncore_write(uncore, regs.eir, 0xffffffff); + intel_uncore_posting_read(uncore, regs.eir); + + intel_uncore_write(uncore, regs.emr, emr_val); + intel_uncore_posting_read(uncore, regs.emr); +} + static void intel_display_irq_regs_init(struct intel_display *display, struct i915_irq_regs regs, u32 imr_val, u32 ier_val) @@ -41,7 +107,7 @@ intel_display_irq_regs_init(struct intel_display *display, struct i915_irq_regs intel_dmc_wl_get(display, regs.ier); intel_dmc_wl_get(display, regs.iir); - gen2_irq_init(to_intel_uncore(display->drm), regs, imr_val, ier_val); + irq_init(to_intel_uncore(display->drm), regs, imr_val, ier_val); intel_dmc_wl_put(display, regs.iir); intel_dmc_wl_put(display, regs.ier); @@ -55,7 +121,7 @@ intel_display_irq_regs_reset(struct intel_display *display, struct i915_irq_regs intel_dmc_wl_get(display, regs.ier); intel_dmc_wl_get(display, regs.iir); - gen2_irq_reset(to_intel_uncore(display->drm), regs); + irq_reset(to_intel_uncore(display->drm), regs); intel_dmc_wl_put(display, regs.iir); intel_dmc_wl_put(display, regs.ier); @@ -67,7 +133,7 @@ intel_display_irq_regs_assert_irr_is_zero(struct intel_display *display, i915_re { intel_dmc_wl_get(display, reg); - gen2_assert_iir_is_zero(to_intel_uncore(display->drm), reg); + assert_iir_is_zero(to_intel_uncore(display->drm), reg); intel_dmc_wl_put(display, reg); } @@ -1918,8 +1984,7 @@ static void _vlv_display_irq_reset(struct intel_display *display) else intel_de_write(display, DPINVGTT, DPINVGTT_STATUS_MASK_VLV); - gen2_error_reset(to_intel_uncore(display->drm), - VLV_ERROR_REGS); + error_reset(to_intel_uncore(display->drm), VLV_ERROR_REGS); i915_hotplug_interrupt_update_locked(display, 0xffffffff, 0); intel_de_rmw(display, PORT_HOTPLUG_STAT(display), 0, 0); @@ -2014,8 +2079,7 @@ static void _vlv_display_irq_postinstall(struct intel_display *display) DPINVGTT_STATUS_MASK_VLV | DPINVGTT_EN_MASK_VLV); - gen2_error_init(to_intel_uncore(display->drm), - VLV_ERROR_REGS, ~vlv_error_mask()); + error_init(to_intel_uncore(display->drm), VLV_ERROR_REGS, ~vlv_error_mask()); pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS; @@ -2054,7 +2118,7 @@ static void ibx_display_irq_reset(struct intel_display *display) if (HAS_PCH_NOP(display)) return; - gen2_irq_reset(to_intel_uncore(display->drm), SDE_IRQ_REGS); + irq_reset(to_intel_uncore(display->drm), SDE_IRQ_REGS); if (HAS_PCH_CPT(display) || HAS_PCH_LPT(display)) intel_de_write(display, SERR_INT, 0xffffffff); @@ -2064,7 +2128,7 @@ void ilk_display_irq_reset(struct intel_display *display) { struct intel_uncore *uncore = to_intel_uncore(display->drm); - gen2_irq_reset(uncore, DE_IRQ_REGS); + irq_reset(uncore, DE_IRQ_REGS); display->irq.ilk_de_imr_mask = ~0u; if (DISPLAY_VER(display) == 7) diff --git a/drivers/gpu/drm/xe/display/ext/i915_irq.c b/drivers/gpu/drm/xe/display/ext/i915_irq.c index 3c6bca66ddab..1011c1c754d0 100644 --- a/drivers/gpu/drm/xe/display/ext/i915_irq.c +++ b/drivers/gpu/drm/xe/display/ext/i915_irq.c @@ -7,73 +7,6 @@ #include "i915_reg.h" #include "intel_uncore.h" -void gen2_irq_reset(struct intel_uncore *uncore, struct i915_irq_regs regs) -{ - intel_uncore_write(uncore, regs.imr, 0xffffffff); - intel_uncore_posting_read(uncore, regs.imr); - - intel_uncore_write(uncore, regs.ier, 0); - - /* IIR can theoretically queue up two events. Be paranoid. */ - intel_uncore_write(uncore, regs.iir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.iir); - intel_uncore_write(uncore, regs.iir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.iir); -} - -/* - * We should clear IMR at preinstall/uninstall, and just check at postinstall. - */ -void gen2_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg) -{ - struct xe_device *xe = container_of(uncore, struct xe_device, uncore); - u32 val = intel_uncore_read(uncore, reg); - - if (val == 0) - return; - - drm_WARN(&xe->drm, 1, - "Interrupt register 0x%x is not zero: 0x%08x\n", - i915_mmio_reg_offset(reg), val); - intel_uncore_write(uncore, reg, 0xffffffff); - intel_uncore_posting_read(uncore, reg); - intel_uncore_write(uncore, reg, 0xffffffff); - intel_uncore_posting_read(uncore, reg); -} - -void gen2_irq_init(struct intel_uncore *uncore, struct i915_irq_regs regs, - u32 imr_val, u32 ier_val) -{ - gen2_assert_iir_is_zero(uncore, regs.iir); - - intel_uncore_write(uncore, regs.ier, ier_val); - intel_uncore_write(uncore, regs.imr, imr_val); - intel_uncore_posting_read(uncore, regs.imr); -} - -void gen2_error_reset(struct intel_uncore *uncore, struct i915_error_regs regs) -{ - intel_uncore_write(uncore, regs.emr, 0xffffffff); - intel_uncore_posting_read(uncore, regs.emr); - - intel_uncore_write(uncore, regs.eir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.eir); - intel_uncore_write(uncore, regs.eir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.eir); -} - -void gen2_error_init(struct intel_uncore *uncore, struct i915_error_regs regs, - u32 emr_val) -{ - intel_uncore_write(uncore, regs.eir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.eir); - intel_uncore_write(uncore, regs.eir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.eir); - - intel_uncore_write(uncore, regs.emr, emr_val); - intel_uncore_posting_read(uncore, regs.emr); -} - bool intel_irqs_enabled(struct xe_device *xe) { return atomic_read(&xe->irq.enabled); From a651be53c42ae1cd44d51a7e7913edbbee976c99 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:09 +0200 Subject: [PATCH 0050/1610] drm/i915/display: convert the display irq interfaces to struct intel_display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the irq/error init/reset interfaces from struct intel_uncore to struct intel_display, and drop the dependency on intel_uncore.h. Since the intel_de_*() calls handle the DMC wakelock internally, we can drop the wrappers handling wakelocks completely. v2: Drop the wakelock wrappers (Ville) Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/710e03906da91244208839b357fe9171e37441ba.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../gpu/drm/i915/display/intel_display_irq.c | 184 +++++++----------- 1 file changed, 68 insertions(+), 116 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index acfaff13c3ba..2a92ca6c2f82 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -19,7 +19,6 @@ #include "intel_display_trace.h" #include "intel_display_types.h" #include "intel_dmc.h" -#include "intel_dmc_wl.h" #include "intel_dp_aux.h" #include "intel_dsb.h" #include "intel_fdi_regs.h" @@ -31,111 +30,71 @@ #include "intel_pmdemand.h" #include "intel_psr.h" #include "intel_psr_regs.h" -#include "intel_uncore.h" -static void irq_reset(struct intel_uncore *uncore, struct i915_irq_regs regs) +static void irq_reset(struct intel_display *display, struct i915_irq_regs regs) { - intel_uncore_write(uncore, regs.imr, 0xffffffff); - intel_uncore_posting_read(uncore, regs.imr); + intel_de_write(display, regs.imr, 0xffffffff); + intel_de_posting_read(display, regs.imr); - intel_uncore_write(uncore, regs.ier, 0); + intel_de_write(display, regs.ier, 0); /* IIR can theoretically queue up two events. Be paranoid. */ - intel_uncore_write(uncore, regs.iir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.iir); - intel_uncore_write(uncore, regs.iir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.iir); + intel_de_write(display, regs.iir, 0xffffffff); + intel_de_posting_read(display, regs.iir); + intel_de_write(display, regs.iir, 0xffffffff); + intel_de_posting_read(display, regs.iir); } /* * We should clear IMR at preinstall/uninstall, and just check at postinstall. */ -static void assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg) +static void assert_iir_is_zero(struct intel_display *display, i915_reg_t reg) { - u32 val = intel_uncore_read(uncore, reg); + u32 val = intel_de_read(display, reg); if (val == 0) return; - WARN(1, + drm_WARN(display->drm, 1, "Interrupt register 0x%x is not zero: 0x%08x\n", i915_mmio_reg_offset(reg), val); - intel_uncore_write(uncore, reg, 0xffffffff); - intel_uncore_posting_read(uncore, reg); - intel_uncore_write(uncore, reg, 0xffffffff); - intel_uncore_posting_read(uncore, reg); + intel_de_write(display, reg, 0xffffffff); + intel_de_posting_read(display, reg); + intel_de_write(display, reg, 0xffffffff); + intel_de_posting_read(display, reg); } -static void irq_init(struct intel_uncore *uncore, struct i915_irq_regs regs, +static void irq_init(struct intel_display *display, struct i915_irq_regs regs, u32 imr_val, u32 ier_val) { - assert_iir_is_zero(uncore, regs.iir); + assert_iir_is_zero(display, regs.iir); - intel_uncore_write(uncore, regs.ier, ier_val); - intel_uncore_write(uncore, regs.imr, imr_val); - intel_uncore_posting_read(uncore, regs.imr); + intel_de_write(display, regs.ier, ier_val); + intel_de_write(display, regs.imr, imr_val); + intel_de_posting_read(display, regs.imr); } -static void error_reset(struct intel_uncore *uncore, struct i915_error_regs regs) +static void error_reset(struct intel_display *display, struct i915_error_regs regs) { - intel_uncore_write(uncore, regs.emr, 0xffffffff); - intel_uncore_posting_read(uncore, regs.emr); + intel_de_write(display, regs.emr, 0xffffffff); + intel_de_posting_read(display, regs.emr); - intel_uncore_write(uncore, regs.eir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.eir); - intel_uncore_write(uncore, regs.eir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.eir); + intel_de_write(display, regs.eir, 0xffffffff); + intel_de_posting_read(display, regs.eir); + intel_de_write(display, regs.eir, 0xffffffff); + intel_de_posting_read(display, regs.eir); } -static void error_init(struct intel_uncore *uncore, struct i915_error_regs regs, +static void error_init(struct intel_display *display, struct i915_error_regs regs, u32 emr_val) { - intel_uncore_write(uncore, regs.eir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.eir); - intel_uncore_write(uncore, regs.eir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.eir); + intel_de_write(display, regs.eir, 0xffffffff); + intel_de_posting_read(display, regs.eir); + intel_de_write(display, regs.eir, 0xffffffff); + intel_de_posting_read(display, regs.eir); - intel_uncore_write(uncore, regs.emr, emr_val); - intel_uncore_posting_read(uncore, regs.emr); -} - -static void -intel_display_irq_regs_init(struct intel_display *display, struct i915_irq_regs regs, - u32 imr_val, u32 ier_val) -{ - intel_dmc_wl_get(display, regs.imr); - intel_dmc_wl_get(display, regs.ier); - intel_dmc_wl_get(display, regs.iir); - - irq_init(to_intel_uncore(display->drm), regs, imr_val, ier_val); - - intel_dmc_wl_put(display, regs.iir); - intel_dmc_wl_put(display, regs.ier); - intel_dmc_wl_put(display, regs.imr); -} - -static void -intel_display_irq_regs_reset(struct intel_display *display, struct i915_irq_regs regs) -{ - intel_dmc_wl_get(display, regs.imr); - intel_dmc_wl_get(display, regs.ier); - intel_dmc_wl_get(display, regs.iir); - - irq_reset(to_intel_uncore(display->drm), regs); - - intel_dmc_wl_put(display, regs.iir); - intel_dmc_wl_put(display, regs.ier); - intel_dmc_wl_put(display, regs.imr); -} - -static void -intel_display_irq_regs_assert_irr_is_zero(struct intel_display *display, i915_reg_t reg) -{ - intel_dmc_wl_get(display, reg); - - assert_iir_is_zero(to_intel_uncore(display->drm), reg); - - intel_dmc_wl_put(display, reg); + intel_de_write(display, regs.emr, emr_val); + intel_de_posting_read(display, regs.emr); } struct pipe_fault_handler { @@ -1984,14 +1943,14 @@ static void _vlv_display_irq_reset(struct intel_display *display) else intel_de_write(display, DPINVGTT, DPINVGTT_STATUS_MASK_VLV); - error_reset(to_intel_uncore(display->drm), VLV_ERROR_REGS); + error_reset(display, VLV_ERROR_REGS); i915_hotplug_interrupt_update_locked(display, 0xffffffff, 0); intel_de_rmw(display, PORT_HOTPLUG_STAT(display), 0, 0); i9xx_pipestat_irq_reset(display); - intel_display_irq_regs_reset(display, VLV_IRQ_REGS); + irq_reset(display, VLV_IRQ_REGS); display->irq.vlv_imr_mask = ~0u; } @@ -2079,7 +2038,7 @@ static void _vlv_display_irq_postinstall(struct intel_display *display) DPINVGTT_STATUS_MASK_VLV | DPINVGTT_EN_MASK_VLV); - error_init(to_intel_uncore(display->drm), VLV_ERROR_REGS, ~vlv_error_mask()); + error_init(display, VLV_ERROR_REGS, ~vlv_error_mask()); pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS; @@ -2102,7 +2061,7 @@ static void _vlv_display_irq_postinstall(struct intel_display *display) display->irq.vlv_imr_mask = ~enable_mask; - intel_display_irq_regs_init(display, VLV_IRQ_REGS, display->irq.vlv_imr_mask, enable_mask); + irq_init(display, VLV_IRQ_REGS, display->irq.vlv_imr_mask, enable_mask); } void vlv_display_irq_postinstall(struct intel_display *display) @@ -2118,7 +2077,7 @@ static void ibx_display_irq_reset(struct intel_display *display) if (HAS_PCH_NOP(display)) return; - irq_reset(to_intel_uncore(display->drm), SDE_IRQ_REGS); + irq_reset(display, SDE_IRQ_REGS); if (HAS_PCH_CPT(display) || HAS_PCH_LPT(display)) intel_de_write(display, SERR_INT, 0xffffffff); @@ -2126,9 +2085,7 @@ static void ibx_display_irq_reset(struct intel_display *display) void ilk_display_irq_reset(struct intel_display *display) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); - - irq_reset(uncore, DE_IRQ_REGS); + irq_reset(display, DE_IRQ_REGS); display->irq.ilk_de_imr_mask = ~0u; if (DISPLAY_VER(display) == 7) @@ -2155,10 +2112,10 @@ void gen8_display_irq_reset(struct intel_display *display) for_each_pipe(display, pipe) if (intel_display_power_is_enabled(display, POWER_DOMAIN_PIPE(pipe))) - intel_display_irq_regs_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); + irq_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); - intel_display_irq_regs_reset(display, GEN8_DE_PORT_IRQ_REGS); - intel_display_irq_regs_reset(display, GEN8_DE_MISC_IRQ_REGS); + irq_reset(display, GEN8_DE_PORT_IRQ_REGS); + irq_reset(display, GEN8_DE_MISC_IRQ_REGS); if (HAS_PCH_SPLIT(display)) ibx_display_irq_reset(display); @@ -2200,18 +2157,18 @@ void gen11_display_irq_reset(struct intel_display *display) for_each_pipe(display, pipe) if (intel_display_power_is_enabled(display, POWER_DOMAIN_PIPE(pipe))) - intel_display_irq_regs_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); + irq_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); - intel_display_irq_regs_reset(display, GEN8_DE_PORT_IRQ_REGS); - intel_display_irq_regs_reset(display, GEN8_DE_MISC_IRQ_REGS); + irq_reset(display, GEN8_DE_PORT_IRQ_REGS); + irq_reset(display, GEN8_DE_MISC_IRQ_REGS); if (DISPLAY_VER(display) >= 14) - intel_display_irq_regs_reset(display, PICAINTERRUPT_IRQ_REGS); + irq_reset(display, PICAINTERRUPT_IRQ_REGS); else - intel_display_irq_regs_reset(display, GEN11_DE_HPD_IRQ_REGS); + irq_reset(display, GEN11_DE_HPD_IRQ_REGS); if (INTEL_PCH_TYPE(display) >= PCH_ICP) - intel_display_irq_regs_reset(display, SDE_IRQ_REGS); + irq_reset(display, SDE_IRQ_REGS); } void gen8_irq_power_well_post_enable(struct intel_display *display, @@ -2230,9 +2187,9 @@ void gen8_irq_power_well_post_enable(struct intel_display *display, } for_each_pipe_masked(display, pipe, pipe_mask) - intel_display_irq_regs_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe), - display->irq.de_pipe_imr_mask[pipe], - ~display->irq.de_pipe_imr_mask[pipe] | extra_ier); + irq_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe), + display->irq.de_pipe_imr_mask[pipe], + ~display->irq.de_pipe_imr_mask[pipe] | extra_ier); spin_unlock_irq(&display->irq.lock); } @@ -2251,7 +2208,7 @@ void gen8_irq_power_well_pre_disable(struct intel_display *display, } for_each_pipe_masked(display, pipe, pipe_mask) - intel_display_irq_regs_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); + irq_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); spin_unlock_irq(&display->irq.lock); @@ -2284,7 +2241,7 @@ static void ibx_irq_postinstall(struct intel_display *display) else mask = SDE_GMBUS_CPT; - intel_display_irq_regs_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff); + irq_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff); } void valleyview_enable_display_irqs(struct intel_display *display) @@ -2350,7 +2307,7 @@ void ilk_de_irq_postinstall(struct intel_display *display) } if (display->platform.haswell) { - intel_display_irq_regs_assert_irr_is_zero(display, EDP_PSR_IIR); + assert_iir_is_zero(display, EDP_PSR_IIR); display_mask |= DE_EDP_PSR_INT_HSW; } @@ -2361,8 +2318,8 @@ void ilk_de_irq_postinstall(struct intel_display *display) ibx_irq_postinstall(display); - intel_display_irq_regs_init(display, DE_IRQ_REGS, display->irq.ilk_de_imr_mask, - display_mask | extra_mask); + irq_init(display, DE_IRQ_REGS, display->irq.ilk_de_imr_mask, + display_mask | extra_mask); } static void mtp_irq_postinstall(struct intel_display *display); @@ -2438,11 +2395,10 @@ void gen8_de_irq_postinstall(struct intel_display *display) if (!intel_display_power_is_enabled(display, domain)) continue; - intel_display_irq_regs_assert_irr_is_zero(display, - TRANS_PSR_IIR(display, trans)); + assert_iir_is_zero(display, TRANS_PSR_IIR(display, trans)); } } else { - intel_display_irq_regs_assert_irr_is_zero(display, EDP_PSR_IIR); + assert_iir_is_zero(display, EDP_PSR_IIR); } for_each_pipe(display, pipe) { @@ -2450,23 +2406,20 @@ void gen8_de_irq_postinstall(struct intel_display *display) if (intel_display_power_is_enabled(display, POWER_DOMAIN_PIPE(pipe))) - intel_display_irq_regs_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe), - display->irq.de_pipe_imr_mask[pipe], - de_pipe_enables); + irq_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe), + display->irq.de_pipe_imr_mask[pipe], + de_pipe_enables); } - intel_display_irq_regs_init(display, GEN8_DE_PORT_IRQ_REGS, ~de_port_masked, - de_port_enables); - intel_display_irq_regs_init(display, GEN8_DE_MISC_IRQ_REGS, ~de_misc_masked, - de_misc_masked); + irq_init(display, GEN8_DE_PORT_IRQ_REGS, ~de_port_masked, de_port_enables); + irq_init(display, GEN8_DE_MISC_IRQ_REGS, ~de_misc_masked, de_misc_masked); if (IS_DISPLAY_VER(display, 11, 13)) { u32 de_hpd_masked = 0; u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK | GEN11_DE_TBT_HOTPLUG_MASK; - intel_display_irq_regs_init(display, GEN11_DE_HPD_IRQ_REGS, ~de_hpd_masked, - de_hpd_enables); + irq_init(display, GEN11_DE_HPD_IRQ_REGS, ~de_hpd_masked, de_hpd_enables); } } @@ -2477,17 +2430,16 @@ static void mtp_irq_postinstall(struct intel_display *display) u32 de_hpd_enables = de_hpd_mask | XELPDP_DP_ALT_HOTPLUG_MASK | XELPDP_TBT_HOTPLUG_MASK; - intel_display_irq_regs_init(display, PICAINTERRUPT_IRQ_REGS, ~de_hpd_mask, - de_hpd_enables); + irq_init(display, PICAINTERRUPT_IRQ_REGS, ~de_hpd_mask, de_hpd_enables); - intel_display_irq_regs_init(display, SDE_IRQ_REGS, ~sde_mask, 0xffffffff); + irq_init(display, SDE_IRQ_REGS, ~sde_mask, 0xffffffff); } static void icp_irq_postinstall(struct intel_display *display) { u32 mask = SDE_GMBUS_ICP; - intel_display_irq_regs_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff); + irq_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff); } void gen11_de_irq_postinstall(struct intel_display *display) From 3815e8f2ffe44396d10b100fbd38f511dfefbbc7 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:10 +0200 Subject: [PATCH 0051/1610] drm/{i915,xe}/display: move irq calls to parent interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an irq parent driver interface for the .enabled and .synchronize calls. This lets us drop the dependency on i915_drv.h and i915_irq.h in multiple places, and subsequently remove the compat i915_irq.h and i915_irq.c files along with the display/ext directory from xe altogether. Introduce new intel_parent.[ch] as the wrapper layer to chase the function pointers and convert between generic and more specific display types. v2: Keep static wrappers in intel_display_irq.c (Ville) v3: Full blown wrappers in intel_parent.[ch] (Ville) Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/dd62dd52ef10d9ecf77da3bdf6a70f71193d141c.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 1 + .../gpu/drm/i915/display/intel_display_irq.c | 37 ++++++------------- .../drm/i915/display/intel_display_power.c | 5 +-- .../i915/display/intel_display_power_well.c | 15 ++------ drivers/gpu/drm/i915/display/intel_gmbus.c | 6 +-- drivers/gpu/drm/i915/display/intel_hotplug.c | 6 +-- .../gpu/drm/i915/display/intel_lpe_audio.c | 1 - drivers/gpu/drm/i915/display/intel_parent.c | 33 +++++++++++++++++ drivers/gpu/drm/i915/display/intel_parent.h | 14 +++++++ drivers/gpu/drm/i915/display/intel_pipe_crc.c | 6 +-- drivers/gpu/drm/i915/i915_driver.c | 1 + drivers/gpu/drm/i915/i915_irq.c | 16 ++++++++ drivers/gpu/drm/i915/i915_irq.h | 2 + drivers/gpu/drm/xe/Makefile | 5 +-- .../gpu/drm/xe/compat-i915-headers/i915_irq.h | 6 --- drivers/gpu/drm/xe/display/ext/i915_irq.c | 18 --------- drivers/gpu/drm/xe/display/xe_display.c | 18 +++++++++ include/drm/intel/display_parent_interface.h | 8 ++++ 18 files changed, 119 insertions(+), 79 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_parent.c create mode 100644 drivers/gpu/drm/i915/display/intel_parent.h delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/i915_irq.h delete mode 100644 drivers/gpu/drm/xe/display/ext/i915_irq.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 49c86a0d44f9..477278aee831 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -292,6 +292,7 @@ i915-y += \ display/intel_modeset_verify.o \ display/intel_overlay.o \ display/intel_panic.o \ + display/intel_parent.o \ display/intel_pch.o \ display/intel_pch_display.o \ display/intel_pch_refclk.o \ diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index 2a92ca6c2f82..d2933ac3acb4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -6,8 +6,6 @@ #include #include -#include "i915_drv.h" -#include "i915_irq.h" #include "i915_reg.h" #include "icl_dsi_regs.h" #include "intel_crtc.h" @@ -25,6 +23,7 @@ #include "intel_fifo_underrun.h" #include "intel_gmbus.h" #include "intel_hotplug_irq.h" +#include "intel_parent.h" #include "intel_pipe_crc_regs.h" #include "intel_plane.h" #include "intel_pmdemand.h" @@ -160,7 +159,6 @@ intel_handle_vblank(struct intel_display *display, enum pipe pipe) void ilk_update_display_irq(struct intel_display *display, u32 interrupt_mask, u32 enabled_irq_mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 new_val; lockdep_assert_held(&display->irq.lock); @@ -171,7 +169,7 @@ void ilk_update_display_irq(struct intel_display *display, new_val |= (~enabled_irq_mask & interrupt_mask); if (new_val != display->irq.ilk_de_imr_mask && - !drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv))) { + !drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display))) { display->irq.ilk_de_imr_mask = new_val; intel_de_write(display, DEIMR, display->irq.ilk_de_imr_mask); intel_de_posting_read(display, DEIMR); @@ -197,7 +195,6 @@ void ilk_disable_display_irq(struct intel_display *display, u32 bits) void bdw_update_port_irq(struct intel_display *display, u32 interrupt_mask, u32 enabled_irq_mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 new_val; u32 old_val; @@ -205,7 +202,7 @@ void bdw_update_port_irq(struct intel_display *display, drm_WARN_ON(display->drm, enabled_irq_mask & ~interrupt_mask); - if (drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv))) + if (drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display))) return; old_val = intel_de_read(display, GEN8_DE_PORT_IMR); @@ -231,14 +228,13 @@ static void bdw_update_pipe_irq(struct intel_display *display, enum pipe pipe, u32 interrupt_mask, u32 enabled_irq_mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 new_val; lockdep_assert_held(&display->irq.lock); drm_WARN_ON(display->drm, enabled_irq_mask & ~interrupt_mask); - if (drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv))) + if (drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display))) return; new_val = display->irq.de_pipe_imr_mask[pipe]; @@ -274,7 +270,6 @@ void ibx_display_interrupt_update(struct intel_display *display, u32 interrupt_mask, u32 enabled_irq_mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 sdeimr = intel_de_read(display, SDEIMR); sdeimr &= ~interrupt_mask; @@ -284,7 +279,7 @@ void ibx_display_interrupt_update(struct intel_display *display, lockdep_assert_held(&display->irq.lock); - if (drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv))) + if (drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display))) return; intel_de_write(display, SDEIMR, sdeimr); @@ -348,7 +343,6 @@ out: void i915_enable_pipestat(struct intel_display *display, enum pipe pipe, u32 status_mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); i915_reg_t reg = PIPESTAT(display, pipe); u32 enable_mask; @@ -357,7 +351,7 @@ void i915_enable_pipestat(struct intel_display *display, pipe_name(pipe), status_mask); lockdep_assert_held(&display->irq.lock); - drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv)); + drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display)); if ((display->irq.pipestat_irq_mask[pipe] & status_mask) == status_mask) return; @@ -372,7 +366,6 @@ void i915_enable_pipestat(struct intel_display *display, void i915_disable_pipestat(struct intel_display *display, enum pipe pipe, u32 status_mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); i915_reg_t reg = PIPESTAT(display, pipe); u32 enable_mask; @@ -381,7 +374,7 @@ void i915_disable_pipestat(struct intel_display *display, pipe_name(pipe), status_mask); lockdep_assert_held(&display->irq.lock); - drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv)); + drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display)); if ((display->irq.pipestat_irq_mask[pipe] & status_mask) == 0) return; @@ -2174,14 +2167,13 @@ void gen11_display_irq_reset(struct intel_display *display) void gen8_irq_power_well_post_enable(struct intel_display *display, u8 pipe_mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN | gen8_de_pipe_flip_done_mask(display); enum pipe pipe; spin_lock_irq(&display->irq.lock); - if (!intel_irqs_enabled(dev_priv)) { + if (!intel_parent_irq_enabled(display)) { spin_unlock_irq(&display->irq.lock); return; } @@ -2197,12 +2189,11 @@ void gen8_irq_power_well_post_enable(struct intel_display *display, void gen8_irq_power_well_pre_disable(struct intel_display *display, u8 pipe_mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); enum pipe pipe; spin_lock_irq(&display->irq.lock); - if (!intel_irqs_enabled(dev_priv)) { + if (!intel_parent_irq_enabled(display)) { spin_unlock_irq(&display->irq.lock); return; } @@ -2213,7 +2204,7 @@ void gen8_irq_power_well_pre_disable(struct intel_display *display, spin_unlock_irq(&display->irq.lock); /* make sure we're done processing display irqs */ - intel_synchronize_irq(dev_priv); + intel_parent_irq_synchronize(display); } /* @@ -2246,8 +2237,6 @@ static void ibx_irq_postinstall(struct intel_display *display) void valleyview_enable_display_irqs(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - spin_lock_irq(&display->irq.lock); if (display->irq.vlv_display_irqs_enabled) @@ -2255,7 +2244,7 @@ void valleyview_enable_display_irqs(struct intel_display *display) display->irq.vlv_display_irqs_enabled = true; - if (intel_irqs_enabled(dev_priv)) { + if (intel_parent_irq_enabled(display)) { _vlv_display_irq_reset(display); _vlv_display_irq_postinstall(display); } @@ -2266,8 +2255,6 @@ out: void valleyview_disable_display_irqs(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - spin_lock_irq(&display->irq.lock); if (!display->irq.vlv_display_irqs_enabled) @@ -2275,7 +2262,7 @@ void valleyview_disable_display_irqs(struct intel_display *display) display->irq.vlv_display_irqs_enabled = false; - if (intel_irqs_enabled(dev_priv)) + if (intel_parent_irq_enabled(display)) _vlv_display_irq_reset(display); out: spin_unlock_irq(&display->irq.lock); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 2a4cc1dcc293..a383ef23391d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -11,7 +11,6 @@ #include "soc/intel_dram.h" #include "i915_drv.h" -#include "i915_irq.h" #include "i915_reg.h" #include "intel_backlight_regs.h" #include "intel_cdclk.h" @@ -27,6 +26,7 @@ #include "intel_display_utils.h" #include "intel_dmc.h" #include "intel_mchbar_regs.h" +#include "intel_parent.h" #include "intel_pch_refclk.h" #include "intel_pcode.h" #include "intel_pmdemand.h" @@ -1202,7 +1202,6 @@ static void hsw_assert_cdclk(struct intel_display *display) static void assert_can_disable_lcpll(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); struct intel_crtc *crtc; for_each_intel_crtc(display->drm, crtc) @@ -1247,7 +1246,7 @@ static void assert_can_disable_lcpll(struct intel_display *display) * gen-specific and since we only disable LCPLL after we fully disable * the interrupts, the check below should be enough. */ - INTEL_DISPLAY_STATE_WARN(display, intel_irqs_enabled(dev_priv), + INTEL_DISPLAY_STATE_WARN(display, intel_parent_irq_enabled(display), "IRQs enabled\n"); } diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index f4f7e73acc87..719f58e43269 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -7,8 +7,6 @@ #include -#include "i915_drv.h" -#include "i915_irq.h" #include "i915_reg.h" #include "intel_backlight_regs.h" #include "intel_combo_phy.h" @@ -28,6 +26,7 @@ #include "intel_dpio_phy.h" #include "intel_dpll.h" #include "intel_hotplug.h" +#include "intel_parent.h" #include "intel_pcode.h" #include "intel_pps.h" #include "intel_psr.h" @@ -628,8 +627,6 @@ static bool hsw_power_well_enabled(struct intel_display *display, static void assert_can_enable_dc9(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - drm_WARN_ONCE(display->drm, (intel_de_read(display, DC_STATE_EN) & DC_STATE_EN_DC9), "DC9 already programmed to be enabled.\n"); @@ -641,7 +638,7 @@ static void assert_can_enable_dc9(struct intel_display *display) intel_de_read(display, HSW_PWR_WELL_CTL2) & HSW_PWR_WELL_CTL_REQ(SKL_PW_CTL_IDX_PW_2), "Power well 2 on.\n"); - drm_WARN_ONCE(display->drm, intel_irqs_enabled(dev_priv), + drm_WARN_ONCE(display->drm, intel_parent_irq_enabled(display), "Interrupts not disabled yet.\n"); /* @@ -655,9 +652,7 @@ static void assert_can_enable_dc9(struct intel_display *display) static void assert_can_disable_dc9(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - - drm_WARN_ONCE(display->drm, intel_irqs_enabled(dev_priv), + drm_WARN_ONCE(display->drm, intel_parent_irq_enabled(display), "Interrupts not disabled yet.\n"); drm_WARN_ONCE(display->drm, intel_de_read(display, DC_STATE_EN) & @@ -1281,12 +1276,10 @@ static void vlv_display_power_well_init(struct intel_display *display) static void vlv_display_power_well_deinit(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - valleyview_disable_display_irqs(display); /* make sure we're done processing display irqs */ - intel_synchronize_irq(dev_priv); + intel_parent_irq_synchronize(display); vlv_pps_reset_all(display); diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index 795012d7c24c..acc85853b2a7 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -35,8 +35,6 @@ #include #include -#include "i915_drv.h" -#include "i915_irq.h" #include "i915_reg.h" #include "intel_de.h" #include "intel_display_regs.h" @@ -44,6 +42,7 @@ #include "intel_display_wa.h" #include "intel_gmbus.h" #include "intel_gmbus_regs.h" +#include "intel_parent.h" struct intel_gmbus { struct i2c_adapter adapter; @@ -391,12 +390,11 @@ intel_gpio_setup(struct intel_gmbus *bus, i915_reg_t gpio_reg) static bool has_gmbus_irq(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); /* * encoder->shutdown() may want to use GMBUS * after irqs have already been disabled. */ - return HAS_GMBUS_IRQ(display) && intel_irqs_enabled(i915); + return HAS_GMBUS_IRQ(display) && intel_parent_irq_enabled(display); } static int gmbus_wait(struct intel_display *display, u32 status, u32 irq_en) diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index 235706229ffb..7575a063f7be 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -27,8 +27,6 @@ #include #include -#include "i915_drv.h" -#include "i915_irq.h" #include "intel_connector.h" #include "intel_display_core.h" #include "intel_display_power.h" @@ -39,6 +37,7 @@ #include "intel_hdcp.h" #include "intel_hotplug.h" #include "intel_hotplug_irq.h" +#include "intel_parent.h" /** * DOC: Hotplug @@ -1177,13 +1176,12 @@ bool intel_hpd_schedule_detection(struct intel_display *display) static int i915_hpd_storm_ctl_show(struct seq_file *m, void *data) { struct intel_display *display = m->private; - struct drm_i915_private *dev_priv = to_i915(display->drm); struct intel_hotplug *hotplug = &display->hotplug; /* Synchronize with everything first in case there's been an HPD * storm, but we haven't finished handling it in the kernel yet */ - intel_synchronize_irq(dev_priv); + intel_parent_irq_synchronize(display); flush_work(&display->hotplug.dig_port_work); flush_delayed_work(&display->hotplug.hotplug_work); diff --git a/drivers/gpu/drm/i915/display/intel_lpe_audio.c b/drivers/gpu/drm/i915/display/intel_lpe_audio.c index 42284e9928f2..5b41abe1c64d 100644 --- a/drivers/gpu/drm/i915/display/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/display/intel_lpe_audio.c @@ -71,7 +71,6 @@ #include #include -#include "i915_irq.h" #include "intel_audio_regs.h" #include "intel_de.h" #include "intel_lpe_audio.h" diff --git a/drivers/gpu/drm/i915/display/intel_parent.c b/drivers/gpu/drm/i915/display/intel_parent.c new file mode 100644 index 000000000000..375713f6f411 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_parent.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +/* Copyright © 2025 Intel Corporation */ + +/* + * Convenience wrapper functions to call the parent interface functions: + * + * - display->parent->SUBSTRUCT->FUNCTION() + * - display->parent->FUNCTION() + * + * All functions here should be named accordingly: + * + * - intel_parent_SUBSTRUCT_FUNCTION() + * - intel_parent_FUNCTION() + * + * These functions may use display driver specific types for parameters and + * return values, translating them to and from the generic types used in the + * function pointer interface. + */ + +#include + +#include "intel_display_core.h" +#include "intel_parent.h" + +bool intel_parent_irq_enabled(struct intel_display *display) +{ + return display->parent->irq->enabled(display->drm); +} + +void intel_parent_irq_synchronize(struct intel_display *display) +{ + display->parent->irq->synchronize(display->drm); +} diff --git a/drivers/gpu/drm/i915/display/intel_parent.h b/drivers/gpu/drm/i915/display/intel_parent.h new file mode 100644 index 000000000000..3ade493f1008 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_parent.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2025 Intel Corporation */ + +#ifndef __INTEL_PARENT_H__ +#define __INTEL_PARENT_H__ + +#include + +struct intel_display; + +bool intel_parent_irq_enabled(struct intel_display *display); +void intel_parent_irq_synchronize(struct intel_display *display); + +#endif /* __INTEL_PARENT_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_pipe_crc.c b/drivers/gpu/drm/i915/display/intel_pipe_crc.c index 1f27643412f1..71cb0178c8b1 100644 --- a/drivers/gpu/drm/i915/display/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/display/intel_pipe_crc.c @@ -30,13 +30,12 @@ #include -#include "i915_drv.h" -#include "i915_irq.h" #include "intel_atomic.h" #include "intel_de.h" #include "intel_display_irq.h" #include "intel_display_regs.h" #include "intel_display_types.h" +#include "intel_parent.h" #include "intel_pipe_crc.h" #include "intel_pipe_crc_regs.h" @@ -658,7 +657,6 @@ void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc) void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(crtc); - struct drm_i915_private *dev_priv = to_i915(display->drm); struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc; enum pipe pipe = crtc->pipe; @@ -669,5 +667,5 @@ void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc) intel_de_write(display, PIPE_CRC_CTL(display, pipe), 0); intel_de_posting_read(display, PIPE_CRC_CTL(display, pipe)); - intel_synchronize_irq(dev_priv); + intel_parent_irq_synchronize(display); } diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index c97b76771917..07715aef62d3 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -741,6 +741,7 @@ static void i915_welcome_messages(struct drm_i915_private *dev_priv) static const struct intel_display_parent_interface parent = { .rpm = &i915_display_rpm_interface, + .irq = &i915_display_irq_interface, }; const struct intel_display_parent_interface *i915_driver_parent_interface(void) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 1898be4ddc8b..3fe978d4ea53 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -33,6 +33,7 @@ #include #include +#include #include "display/intel_display_irq.h" #include "display/intel_hotplug.h" @@ -1252,3 +1253,18 @@ void intel_synchronize_hardirq(struct drm_i915_private *i915) { synchronize_hardirq(to_pci_dev(i915->drm.dev)->irq); } + +static bool _intel_irq_enabled(struct drm_device *drm) +{ + return intel_irqs_enabled(to_i915(drm)); +} + +static void _intel_irq_synchronize(struct drm_device *drm) +{ + return intel_synchronize_irq(to_i915(drm)); +} + +const struct intel_display_irq_interface i915_display_irq_interface = { + .enabled = _intel_irq_enabled, + .synchronize = _intel_irq_synchronize, +}; diff --git a/drivers/gpu/drm/i915/i915_irq.h b/drivers/gpu/drm/i915/i915_irq.h index 58789b264575..5c87d6d41c74 100644 --- a/drivers/gpu/drm/i915/i915_irq.h +++ b/drivers/gpu/drm/i915/i915_irq.h @@ -51,4 +51,6 @@ void gen2_error_reset(struct intel_uncore *uncore, struct i915_error_regs regs); void gen2_error_init(struct intel_uncore *uncore, struct i915_error_regs regs, u32 emr_val); +extern const struct intel_display_irq_interface i915_display_irq_interface; + #endif /* __I915_IRQ_H__ */ diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index f8a3a1bfe42e..8967f874280e 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -187,7 +187,6 @@ endif # i915 Display compat #defines and #includes subdir-ccflags-$(CONFIG_DRM_XE_DISPLAY) += \ - -I$(src)/display/ext \ -I$(src)/compat-i915-headers \ -I$(srctree)/drivers/gpu/drm/i915/display/ \ -Ddrm_i915_private=xe_device @@ -204,7 +203,6 @@ $(obj)/i915-display/%.o: $(srctree)/drivers/gpu/drm/i915/display/%.c FORCE # Display code specific to xe xe-$(CONFIG_DRM_XE_DISPLAY) += \ - display/ext/i915_irq.o \ display/intel_bo.o \ display/intel_fb_bo.o \ display/intel_fbdev_fb.o \ @@ -300,10 +298,11 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_modeset_setup.o \ i915-display/intel_modeset_verify.o \ i915-display/intel_panel.o \ + i915-display/intel_parent.o \ + i915-display/intel_pch.o \ i915-display/intel_pfit.o \ i915-display/intel_plane.o \ i915-display/intel_pmdemand.o \ - i915-display/intel_pch.o \ i915-display/intel_pps.o \ i915-display/intel_psr.o \ i915-display/intel_qp_tables.o \ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_irq.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_irq.h deleted file mode 100644 index 61707a07f91f..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_irq.h +++ /dev/null @@ -1,6 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#include "../../i915/i915_irq.h" diff --git a/drivers/gpu/drm/xe/display/ext/i915_irq.c b/drivers/gpu/drm/xe/display/ext/i915_irq.c deleted file mode 100644 index 1011c1c754d0..000000000000 --- a/drivers/gpu/drm/xe/display/ext/i915_irq.c +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright © 2023 Intel Corporation - */ - -#include "i915_irq.h" -#include "i915_reg.h" -#include "intel_uncore.h" - -bool intel_irqs_enabled(struct xe_device *xe) -{ - return atomic_read(&xe->irq.enabled); -} - -void intel_synchronize_irq(struct xe_device *xe) -{ - synchronize_irq(to_pci_dev(xe->drm.dev)->irq); -} diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 8b0afa270216..e3320d9e6314 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -516,8 +516,26 @@ static void display_device_remove(struct drm_device *dev, void *arg) intel_display_device_remove(display); } +static bool irq_enabled(struct drm_device *drm) +{ + struct xe_device *xe = to_xe_device(drm); + + return atomic_read(&xe->irq.enabled); +} + +static void irq_synchronize(struct drm_device *drm) +{ + synchronize_irq(to_pci_dev(drm->dev)->irq); +} + +static const struct intel_display_irq_interface xe_display_irq_interface = { + .enabled = irq_enabled, + .synchronize = irq_synchronize, +}; + static const struct intel_display_parent_interface parent = { .rpm = &xe_display_rpm_interface, + .irq = &xe_display_irq_interface, }; /** diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index 26bedc360044..3a008a18eb65 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -25,6 +25,11 @@ struct intel_display_rpm_interface { void (*assert_unblock)(const struct drm_device *drm); }; +struct intel_display_irq_interface { + bool (*enabled)(struct drm_device *drm); + void (*synchronize)(struct drm_device *drm); +}; + /** * struct intel_display_parent_interface - services parent driver provides to display * @@ -40,6 +45,9 @@ struct intel_display_rpm_interface { struct intel_display_parent_interface { /** @rpm: Runtime PM functions */ const struct intel_display_rpm_interface *rpm; + + /** @irq: IRQ interface */ + const struct intel_display_irq_interface *irq; }; #endif From e8916738977e29a6f1e8edc593ee336f2bcf1b7d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:11 +0200 Subject: [PATCH 0052/1610] drm/i915: add .vgpu_active to parent interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add .vgpu_active() to display parent interface, removing more dependencies on struct drm_i915_private, i915_drv.h, and i915_vgpu.h. This also allows us to remove the xe compat i915_vgpu.h. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/a2d4043ebaaf8f69bb738d5d1332afd2847550ad.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_crtc.c | 6 ++---- drivers/gpu/drm/i915/display/intel_fbc.c | 5 ++--- drivers/gpu/drm/i915/display/intel_parent.c | 5 +++++ drivers/gpu/drm/i915/display/intel_parent.h | 2 ++ drivers/gpu/drm/i915/i915_driver.c | 6 ++++++ .../gpu/drm/xe/compat-i915-headers/i915_vgpu.h | 18 ------------------ include/drm/intel/display_parent_interface.h | 3 +++ 7 files changed, 20 insertions(+), 25 deletions(-) delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/i915_vgpu.h diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 9d2a23c96c61..153ff4b4b52c 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -13,8 +13,6 @@ #include #include -#include "i915_drv.h" -#include "i915_vgpu.h" #include "i9xx_plane.h" #include "icl_dsi.h" #include "intel_atomic.h" @@ -28,6 +26,7 @@ #include "intel_drrs.h" #include "intel_dsi.h" #include "intel_fifo_underrun.h" +#include "intel_parent.h" #include "intel_pipe_crc.h" #include "intel_plane.h" #include "intel_psr.h" @@ -671,7 +670,6 @@ void intel_pipe_update_end(struct intel_atomic_state *state, int scanline_end = intel_get_crtc_scanline(crtc); u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc); ktime_t end_vbl_time = ktime_get(); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); drm_WARN_ON(display->drm, new_crtc_state->use_dsb); @@ -737,7 +735,7 @@ void intel_pipe_update_end(struct intel_atomic_state *state, local_irq_enable(); - if (intel_vgpu_active(dev_priv)) + if (intel_parent_vgpu_active(display)) goto out; if (crtc->debug.start_vbl_count && diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 205c7266af43..cfadc69010a4 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -50,7 +50,6 @@ #include "gt/intel_gt_types.h" #include "i915_drv.h" -#include "i915_vgpu.h" #include "i915_vma.h" #include "i9xx_plane_regs.h" #include "intel_de.h" @@ -64,6 +63,7 @@ #include "intel_fbc.h" #include "intel_fbc_regs.h" #include "intel_frontbuffer.h" +#include "intel_parent.h" #define for_each_fbc_id(__display, __fbc_id) \ for ((__fbc_id) = INTEL_FBC_A; (__fbc_id) < I915_MAX_FBCS; (__fbc_id)++) \ @@ -1485,7 +1485,6 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, struct intel_plane *plane) { struct intel_display *display = to_intel_display(state->base.dev); - struct drm_i915_private *i915 = to_i915(display->drm); struct intel_plane_state *plane_state = intel_atomic_get_new_plane_state(state, plane); const struct drm_framebuffer *fb = plane_state->hw.fb; @@ -1501,7 +1500,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, return 0; } - if (intel_vgpu_active(i915)) { + if (intel_parent_vgpu_active(display)) { plane_state->no_fbc_reason = "VGPU active"; return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_parent.c b/drivers/gpu/drm/i915/display/intel_parent.c index 375713f6f411..3786fd42827d 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.c +++ b/drivers/gpu/drm/i915/display/intel_parent.c @@ -31,3 +31,8 @@ void intel_parent_irq_synchronize(struct intel_display *display) { display->parent->irq->synchronize(display->drm); } + +bool intel_parent_vgpu_active(struct intel_display *display) +{ + return display->parent->vgpu_active && display->parent->vgpu_active(display->drm); +} diff --git a/drivers/gpu/drm/i915/display/intel_parent.h b/drivers/gpu/drm/i915/display/intel_parent.h index 3ade493f1008..222c95836d35 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.h +++ b/drivers/gpu/drm/i915/display/intel_parent.h @@ -11,4 +11,6 @@ struct intel_display; bool intel_parent_irq_enabled(struct intel_display *display); void intel_parent_irq_synchronize(struct intel_display *display); +bool intel_parent_vgpu_active(struct intel_display *display); + #endif /* __INTEL_PARENT_H__ */ diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 07715aef62d3..f21f1919a225 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -739,9 +739,15 @@ static void i915_welcome_messages(struct drm_i915_private *dev_priv) "DRM_I915_DEBUG_RUNTIME_PM enabled\n"); } +static bool vgpu_active(struct drm_device *drm) +{ + return intel_vgpu_active(to_i915(drm)); +} + static const struct intel_display_parent_interface parent = { .rpm = &i915_display_rpm_interface, .irq = &i915_display_irq_interface, + .vgpu_active = vgpu_active, }; const struct intel_display_parent_interface *i915_driver_parent_interface(void) diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_vgpu.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_vgpu.h deleted file mode 100644 index 4931c7198f13..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_vgpu.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#ifndef _I915_VGPU_H_ -#define _I915_VGPU_H_ - -#include - -struct drm_i915_private; - -static inline bool intel_vgpu_active(struct drm_i915_private *i915) -{ - return false; -} - -#endif /* _I915_VGPU_H_ */ diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index 3a008a18eb65..f3834f36ce74 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -48,6 +48,9 @@ struct intel_display_parent_interface { /** @irq: IRQ interface */ const struct intel_display_irq_interface *irq; + + /** @vgpu_active: Is vGPU active? Optional. */ + bool (*vgpu_active)(struct drm_device *drm); }; #endif From 4799ff418f9a68361331fdc7fc01f66dc314adb9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:12 +0200 Subject: [PATCH 0053/1610] drm/i915: add .has_fenced_regions to parent interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add .has_fenced_regions() to display parent interface, removing more dependencies on struct drm_i915_private, i915_drv.h, and gt/intel_gt_types.h. This allows us to remove the xe compat gt/intel_gt_types.h. v2: s/fence_support_legacy/has_fenced_regions/ (Ville) Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/309f61a8742c3bf731c820b2f9e1024143db8598.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fbc.c | 8 ++------ drivers/gpu/drm/i915/display/intel_parent.c | 5 +++++ drivers/gpu/drm/i915/display/intel_parent.h | 2 ++ drivers/gpu/drm/i915/i915_driver.c | 6 ++++++ .../drm/xe/compat-i915-headers/gt/intel_gt_types.h | 11 ----------- include/drm/intel/display_parent_interface.h | 3 +++ 6 files changed, 18 insertions(+), 17 deletions(-) delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/gt/intel_gt_types.h diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index cfadc69010a4..d9cab25d414a 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -47,9 +47,6 @@ #include "gem/i915_gem_stolen.h" -#include "gt/intel_gt_types.h" - -#include "i915_drv.h" #include "i915_vma.h" #include "i9xx_plane_regs.h" #include "intel_de.h" @@ -64,6 +61,7 @@ #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)++) \ @@ -267,9 +265,7 @@ static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state *plane_s static bool intel_fbc_has_fences(struct intel_display *display) { - struct drm_i915_private __maybe_unused *i915 = to_i915(display->drm); - - return intel_gt_support_legacy_fencing(to_gt(i915)); + return intel_parent_has_fenced_regions(display); } static u32 i8xx_fbc_ctl(struct intel_fbc *fbc) diff --git a/drivers/gpu/drm/i915/display/intel_parent.c b/drivers/gpu/drm/i915/display/intel_parent.c index 3786fd42827d..535065e57213 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.c +++ b/drivers/gpu/drm/i915/display/intel_parent.c @@ -36,3 +36,8 @@ bool intel_parent_vgpu_active(struct intel_display *display) { return display->parent->vgpu_active && display->parent->vgpu_active(display->drm); } + +bool intel_parent_has_fenced_regions(struct intel_display *display) +{ + return display->parent->has_fenced_regions && display->parent->has_fenced_regions(display->drm); +} diff --git a/drivers/gpu/drm/i915/display/intel_parent.h b/drivers/gpu/drm/i915/display/intel_parent.h index 222c95836d35..04320d937777 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.h +++ b/drivers/gpu/drm/i915/display/intel_parent.h @@ -13,4 +13,6 @@ void intel_parent_irq_synchronize(struct intel_display *display); bool intel_parent_vgpu_active(struct intel_display *display); +bool intel_parent_has_fenced_regions(struct intel_display *display); + #endif /* __INTEL_PARENT_H__ */ diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index f21f1919a225..9ba46850da72 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -744,10 +744,16 @@ static bool vgpu_active(struct drm_device *drm) return intel_vgpu_active(to_i915(drm)); } +static bool has_fenced_regions(struct drm_device *drm) +{ + return intel_gt_support_legacy_fencing(to_gt(to_i915(drm))); +} + static const struct intel_display_parent_interface parent = { .rpm = &i915_display_rpm_interface, .irq = &i915_display_irq_interface, .vgpu_active = vgpu_active, + .has_fenced_regions = has_fenced_regions, }; const struct intel_display_parent_interface *i915_driver_parent_interface(void) diff --git a/drivers/gpu/drm/xe/compat-i915-headers/gt/intel_gt_types.h b/drivers/gpu/drm/xe/compat-i915-headers/gt/intel_gt_types.h deleted file mode 100644 index c15806d6c4f7..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/gt/intel_gt_types.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#ifndef __INTEL_GT_TYPES__ -#define __INTEL_GT_TYPES__ - -#define intel_gt_support_legacy_fencing(gt) 0 - -#endif diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index f3834f36ce74..927d964f2071 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -51,6 +51,9 @@ struct intel_display_parent_interface { /** @vgpu_active: Is vGPU active? Optional. */ bool (*vgpu_active)(struct drm_device *drm); + + /** @has_fenced_regions: Support legacy fencing? Optional. */ + bool (*has_fenced_regions)(struct drm_device *drm); }; #endif From 95c04f442941cb9829e791d0bef460317a17819c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:13 +0200 Subject: [PATCH 0054/1610] drm/i915/rps: store struct dma_fence in struct wait_rps_boost MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefer the more generic pointer rather than i915 specific data type. Also use dma_fence_put() for symmetry with the dma_fence_get() Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/950948ae6d3d5fbc4af3401ea77e609945b73a77.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_rps.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_rps.c b/drivers/gpu/drm/i915/display/intel_display_rps.c index 82ea1ec482e4..b6720f7c09d9 100644 --- a/drivers/gpu/drm/i915/display/intel_display_rps.c +++ b/drivers/gpu/drm/i915/display/intel_display_rps.c @@ -18,14 +18,14 @@ struct wait_rps_boost { struct wait_queue_entry wait; struct drm_crtc *crtc; - struct i915_request *request; + struct dma_fence *fence; }; static int do_rps_boost(struct wait_queue_entry *_wait, unsigned mode, int sync, void *key) { struct wait_rps_boost *wait = container_of(_wait, typeof(*wait), wait); - struct i915_request *rq = wait->request; + struct i915_request *rq = to_request(wait->fence); /* * If we missed the vblank, but the request is already running it @@ -34,7 +34,7 @@ static int do_rps_boost(struct wait_queue_entry *_wait, */ if (!i915_request_started(rq)) intel_rps_boost(rq); - i915_request_put(rq); + dma_fence_put(wait->fence); drm_crtc_vblank_put(wait->crtc); @@ -64,7 +64,7 @@ void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc, return; } - wait->request = to_request(dma_fence_get(fence)); + wait->fence = dma_fence_get(fence); wait->crtc = crtc; wait->wait.func = do_rps_boost; From 1314027632ae2d98ec7ba250495d1a6084caafc6 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:14 +0200 Subject: [PATCH 0055/1610] drm/i915/rps: call RPS functions via the parent interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add struct intel_display_rps_interface to the display parent interface, and call the RPS functions through it. The RPS interface is optional. v2: s/boost/boost_if_not_started/ and keep comment in caller (Ville) Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/6a6c4420d9f2d9a545ee6df4cad5fdc32a86636b.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../gpu/drm/i915/display/intel_display_rps.c | 27 ++++++++++------- drivers/gpu/drm/i915/display/intel_parent.c | 23 +++++++++++++++ drivers/gpu/drm/i915/display/intel_parent.h | 6 ++++ drivers/gpu/drm/i915/gt/intel_rps.c | 29 +++++++++++++++++++ drivers/gpu/drm/i915/gt/intel_rps.h | 2 ++ drivers/gpu/drm/i915/i915_driver.c | 2 ++ include/drm/intel/display_parent_interface.h | 10 +++++++ 7 files changed, 88 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_rps.c b/drivers/gpu/drm/i915/display/intel_display_rps.c index b6720f7c09d9..d639d9152bf5 100644 --- a/drivers/gpu/drm/i915/display/intel_display_rps.c +++ b/drivers/gpu/drm/i915/display/intel_display_rps.c @@ -3,16 +3,18 @@ * Copyright © 2023 Intel Corporation */ +#include + #include #include -#include "gt/intel_rps.h" -#include "i915_drv.h" #include "i915_reg.h" +#include "i915_request.h" #include "intel_display_core.h" #include "intel_display_irq.h" #include "intel_display_rps.h" #include "intel_display_types.h" +#include "intel_parent.h" struct wait_rps_boost { struct wait_queue_entry wait; @@ -25,15 +27,15 @@ static int do_rps_boost(struct wait_queue_entry *_wait, unsigned mode, int sync, void *key) { struct wait_rps_boost *wait = container_of(_wait, typeof(*wait), wait); - struct i915_request *rq = to_request(wait->fence); + struct intel_display *display = to_intel_display(wait->crtc->dev); /* * If we missed the vblank, but the request is already running it * is reasonable to assume that it will complete before the next - * vblank without our intervention, so leave RPS alone. + * vblank without our intervention, so leave RPS alone if not started. */ - if (!i915_request_started(rq)) - intel_rps_boost(rq); + intel_parent_rps_boost_if_not_started(display, wait->fence); + dma_fence_put(wait->fence); drm_crtc_vblank_put(wait->crtc); @@ -49,6 +51,9 @@ void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc, struct intel_display *display = to_intel_display(crtc->dev); struct wait_rps_boost *wait; + if (!intel_parent_rps_available(display)) + return; + if (!dma_fence_is_i915(fence)) return; @@ -77,12 +82,14 @@ void intel_display_rps_mark_interactive(struct intel_display *display, struct intel_atomic_state *state, bool interactive) { - struct drm_i915_private *i915 = to_i915(display->drm); + if (!intel_parent_rps_available(display)) + return; if (state->rps_interactive == interactive) return; - intel_rps_mark_interactive(&to_gt(i915)->rps, interactive); + intel_parent_rps_mark_interactive(display, interactive); + state->rps_interactive = interactive; } @@ -102,7 +109,5 @@ void ilk_display_rps_disable(struct intel_display *display) void ilk_display_rps_irq_handler(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - - gen5_rps_irq_handler(&to_gt(i915)->rps); + intel_parent_rps_ilk_irq_handler(display); } diff --git a/drivers/gpu/drm/i915/display/intel_parent.c b/drivers/gpu/drm/i915/display/intel_parent.c index 535065e57213..6c131196718e 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.c +++ b/drivers/gpu/drm/i915/display/intel_parent.c @@ -32,6 +32,29 @@ void intel_parent_irq_synchronize(struct intel_display *display) display->parent->irq->synchronize(display->drm); } +bool intel_parent_rps_available(struct intel_display *display) +{ + return display->parent->rps; +} + +void intel_parent_rps_boost_if_not_started(struct intel_display *display, struct dma_fence *fence) +{ + if (display->parent->rps) + display->parent->rps->boost_if_not_started(fence); +} + +void intel_parent_rps_mark_interactive(struct intel_display *display, bool interactive) +{ + if (display->parent->rps) + display->parent->rps->mark_interactive(display->drm, interactive); +} + +void intel_parent_rps_ilk_irq_handler(struct intel_display *display) +{ + if (display->parent->rps) + display->parent->rps->ilk_irq_handler(display->drm); +} + bool intel_parent_vgpu_active(struct intel_display *display) { return display->parent->vgpu_active && display->parent->vgpu_active(display->drm); diff --git a/drivers/gpu/drm/i915/display/intel_parent.h b/drivers/gpu/drm/i915/display/intel_parent.h index 04320d937777..12cfbea95aa1 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.h +++ b/drivers/gpu/drm/i915/display/intel_parent.h @@ -6,11 +6,17 @@ #include +struct dma_fence; struct intel_display; bool intel_parent_irq_enabled(struct intel_display *display); void intel_parent_irq_synchronize(struct intel_display *display); +bool intel_parent_rps_available(struct intel_display *display); +void intel_parent_rps_boost_if_not_started(struct intel_display *display, struct dma_fence *fence); +void intel_parent_rps_mark_interactive(struct intel_display *display, bool interactive); +void intel_parent_rps_ilk_irq_handler(struct intel_display *display); + bool intel_parent_vgpu_active(struct intel_display *display); bool intel_parent_has_fenced_regions(struct intel_display *display); diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index b01c837ab646..c42a1ee42b58 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -6,6 +6,7 @@ #include #include +#include #include "display/intel_display_rps.h" #include "display/vlv_clock.h" @@ -2914,6 +2915,34 @@ bool i915_gpu_turbo_disable(void) } EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable); +static void boost_if_not_started(struct dma_fence *fence) +{ + struct i915_request *rq = to_request(fence); + + if (!i915_request_started(rq)) + intel_rps_boost(rq); +} + +static void mark_interactive(struct drm_device *drm, bool interactive) +{ + struct drm_i915_private *i915 = to_i915(drm); + + intel_rps_mark_interactive(&to_gt(i915)->rps, interactive); +} + +static void ilk_irq_handler(struct drm_device *drm) +{ + struct drm_i915_private *i915 = to_i915(drm); + + gen5_rps_irq_handler(&to_gt(i915)->rps); +} + +const struct intel_display_rps_interface i915_display_rps_interface = { + .boost_if_not_started = boost_if_not_started, + .mark_interactive = mark_interactive, + .ilk_irq_handler = ilk_irq_handler, +}; + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftest_rps.c" #include "selftest_slpc.c" diff --git a/drivers/gpu/drm/i915/gt/intel_rps.h b/drivers/gpu/drm/i915/gt/intel_rps.h index 92fb01f5a452..5dbcebd7d4a5 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.h +++ b/drivers/gpu/drm/i915/gt/intel_rps.h @@ -128,4 +128,6 @@ static inline void intel_rps_clear_timer(struct intel_rps *rps) clear_bit(INTEL_RPS_TIMER, &rps->flags); } +extern const struct intel_display_rps_interface i915_display_rps_interface; + #endif /* INTEL_RPS_H */ diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 9ba46850da72..7e1dedabf0ee 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -81,6 +81,7 @@ #include "gt/intel_gt_pm.h" #include "gt/intel_gt_print.h" #include "gt/intel_rc6.h" +#include "gt/intel_rps.h" #include "pxp/intel_pxp.h" #include "pxp/intel_pxp_debugfs.h" @@ -752,6 +753,7 @@ static bool has_fenced_regions(struct drm_device *drm) static const struct intel_display_parent_interface parent = { .rpm = &i915_display_rpm_interface, .irq = &i915_display_irq_interface, + .rps = &i915_display_rps_interface, .vgpu_active = vgpu_active, .has_fenced_regions = has_fenced_regions, }; diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index 927d964f2071..0a6a26234fbe 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -6,6 +6,7 @@ #include +struct dma_fence; struct drm_device; struct ref_tracker; @@ -30,6 +31,12 @@ struct intel_display_irq_interface { void (*synchronize)(struct drm_device *drm); }; +struct intel_display_rps_interface { + void (*boost_if_not_started)(struct dma_fence *fence); + void (*mark_interactive)(struct drm_device *drm, bool interactive); + void (*ilk_irq_handler)(struct drm_device *drm); +}; + /** * struct intel_display_parent_interface - services parent driver provides to display * @@ -49,6 +56,9 @@ struct intel_display_parent_interface { /** @irq: IRQ interface */ const struct intel_display_irq_interface *irq; + /** @rpm: RPS interface. Optional. */ + const struct intel_display_rps_interface *rps; + /** @vgpu_active: Is vGPU active? Optional. */ bool (*vgpu_active)(struct drm_device *drm); From 69c9b1861e827a45021a0a10c1d0276a896dd0c2 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:15 +0200 Subject: [PATCH 0056/1610] drm/i915/rps: postpone i915 fence check to boost MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the RPS boost code independent of i915 request code by moving the dma_fence_is_i915() check to the RPS boost call. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/2653395523ee04c9ca3216f197f08c25a9f7716d.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_rps.c | 4 ---- drivers/gpu/drm/i915/gt/intel_rps.c | 7 ++++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_rps.c b/drivers/gpu/drm/i915/display/intel_display_rps.c index d639d9152bf5..e77811396474 100644 --- a/drivers/gpu/drm/i915/display/intel_display_rps.c +++ b/drivers/gpu/drm/i915/display/intel_display_rps.c @@ -9,7 +9,6 @@ #include #include "i915_reg.h" -#include "i915_request.h" #include "intel_display_core.h" #include "intel_display_irq.h" #include "intel_display_rps.h" @@ -54,9 +53,6 @@ void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc, if (!intel_parent_rps_available(display)) return; - if (!dma_fence_is_i915(fence)) - return; - if (DISPLAY_VER(display) < 6) return; diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index c42a1ee42b58..d233dc122bd7 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -2917,7 +2917,12 @@ EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable); static void boost_if_not_started(struct dma_fence *fence) { - struct i915_request *rq = to_request(fence); + struct i915_request *rq; + + if (!dma_fence_is_i915(fence)) + return; + + rq = to_request(fence); if (!i915_request_started(rq)) intel_rps_boost(rq); From 55fc11ce96e92dbae2aab1d692735f7a9b96fefd Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:16 +0200 Subject: [PATCH 0057/1610] drm/i915: add .fence_priority_display to parent interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add .fence_priority_display() to display parent interface, removing a display dependency on gem/i915_gem_object.h. This allows us to remove the xe compat gem/i915_gem_object.h. v2: Don't mix this with the rps interface (Ville) v3: Rebase Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/c7782862956e3aa59eaeb6dcf80906c1fc063ae1.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_parent.c | 6 ++++++ drivers/gpu/drm/i915/display/intel_parent.h | 2 ++ drivers/gpu/drm/i915/display/intel_plane.c | 5 ++--- drivers/gpu/drm/i915/i915_driver.c | 7 +++++++ .../xe/compat-i915-headers/gem/i915_gem_object.h | 13 ------------- include/drm/intel/display_parent_interface.h | 3 +++ 6 files changed, 20 insertions(+), 16 deletions(-) delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h diff --git a/drivers/gpu/drm/i915/display/intel_parent.c b/drivers/gpu/drm/i915/display/intel_parent.c index 6c131196718e..27c7ef34ce48 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.c +++ b/drivers/gpu/drm/i915/display/intel_parent.c @@ -64,3 +64,9 @@ bool intel_parent_has_fenced_regions(struct intel_display *display) { return display->parent->has_fenced_regions && display->parent->has_fenced_regions(display->drm); } + +void intel_parent_fence_priority_display(struct intel_display *display, struct dma_fence *fence) +{ + if (display->parent->fence_priority_display) + display->parent->fence_priority_display(fence); +} diff --git a/drivers/gpu/drm/i915/display/intel_parent.h b/drivers/gpu/drm/i915/display/intel_parent.h index 12cfbea95aa1..a8ca40b57ea9 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.h +++ b/drivers/gpu/drm/i915/display/intel_parent.h @@ -21,4 +21,6 @@ bool intel_parent_vgpu_active(struct intel_display *display); bool intel_parent_has_fenced_regions(struct intel_display *display); +void intel_parent_fence_priority_display(struct intel_display *display, struct dma_fence *fence); + #endif /* __INTEL_PARENT_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_plane.c b/drivers/gpu/drm/i915/display/intel_plane.c index 5105e3278bc4..a7fec5ba6ac0 100644 --- a/drivers/gpu/drm/i915/display/intel_plane.c +++ b/drivers/gpu/drm/i915/display/intel_plane.c @@ -45,7 +45,6 @@ #include #include -#include "gem/i915_gem_object.h" #include "i9xx_plane_regs.h" #include "intel_cdclk.h" #include "intel_cursor.h" @@ -56,6 +55,7 @@ #include "intel_fb_pin.h" #include "intel_fbdev.h" #include "intel_panic.h" +#include "intel_parent.h" #include "intel_plane.h" #include "intel_psr.h" #include "skl_scaler.h" @@ -1180,8 +1180,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane, goto unpin_fb; if (new_plane_state->uapi.fence) { - i915_gem_fence_wait_priority_display(new_plane_state->uapi.fence); - + intel_parent_fence_priority_display(display, new_plane_state->uapi.fence); intel_display_rps_boost_after_vblank(new_plane_state->hw.crtc, new_plane_state->uapi.fence); } diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 7e1dedabf0ee..7c60b6873934 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -750,12 +750,19 @@ static bool has_fenced_regions(struct drm_device *drm) return intel_gt_support_legacy_fencing(to_gt(to_i915(drm))); } +static void fence_priority_display(struct dma_fence *fence) +{ + if (dma_fence_is_i915(fence)) + i915_gem_fence_wait_priority_display(fence); +} + static const struct intel_display_parent_interface parent = { .rpm = &i915_display_rpm_interface, .irq = &i915_display_irq_interface, .rps = &i915_display_rps_interface, .vgpu_active = vgpu_active, .has_fenced_regions = has_fenced_regions, + .fence_priority_display = fence_priority_display, }; const struct intel_display_parent_interface *i915_driver_parent_interface(void) diff --git a/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h b/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h deleted file mode 100644 index 0548b2e0316f..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* Copyright © 2025 Intel Corporation */ - -#ifndef __I915_GEM_OBJECT_H__ -#define __I915_GEM_OBJECT_H__ - -struct dma_fence; - -static inline void i915_gem_fence_wait_priority_display(struct dma_fence *fence) -{ -} - -#endif diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index 0a6a26234fbe..4135d1e1a67e 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -64,6 +64,9 @@ struct intel_display_parent_interface { /** @has_fenced_regions: Support legacy fencing? Optional. */ bool (*has_fenced_regions)(struct drm_device *drm); + + /** @fence_priority_display: Set display priority. Optional. */ + void (*fence_priority_display)(struct dma_fence *fence); }; #endif From e4c8fde0bf2004fcd9c9dc8e3bc9bf6545a21a3e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:17 +0200 Subject: [PATCH 0058/1610] drm/xe/rps: build RPS as part of xe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce the conditional compilation in i915 by building intel_display_rps.c as part of the xe module. This doesn't actually enable RPS on xe, because there's no parent interface implementation on xe side, but it's a step in the right direction. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/93df0bb727fce14aa9a542dbd2c0826a0fa0a16f.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../gpu/drm/i915/display/intel_display_rps.h | 21 ------------------- drivers/gpu/drm/xe/Makefile | 1 + 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_rps.h b/drivers/gpu/drm/i915/display/intel_display_rps.h index 183d154f2c7c..96b1fd00ead4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_rps.h +++ b/drivers/gpu/drm/i915/display/intel_display_rps.h @@ -13,7 +13,6 @@ struct drm_crtc; struct intel_atomic_state; struct intel_display; -#ifdef I915 void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc, struct dma_fence *fence); void intel_display_rps_mark_interactive(struct intel_display *display, @@ -22,25 +21,5 @@ void intel_display_rps_mark_interactive(struct intel_display *display, void ilk_display_rps_enable(struct intel_display *display); void ilk_display_rps_disable(struct intel_display *display); void ilk_display_rps_irq_handler(struct intel_display *display); -#else -static inline void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc, - struct dma_fence *fence) -{ -} -static inline void intel_display_rps_mark_interactive(struct intel_display *display, - struct intel_atomic_state *state, - bool interactive) -{ -} -static inline void ilk_display_rps_enable(struct intel_display *display) -{ -} -static inline void ilk_display_rps_disable(struct intel_display *display) -{ -} -static inline void ilk_display_rps_irq_handler(struct intel_display *display) -{ -} -#endif #endif /* __INTEL_DISPLAY_RPS_H__ */ diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 8967f874280e..8b60fc72fe50 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -255,6 +255,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_display_power_map.o \ i915-display/intel_display_power_well.o \ i915-display/intel_display_rpm.o \ + i915-display/intel_display_rps.o \ i915-display/intel_display_trace.o \ i915-display/intel_display_utils.o \ i915-display/intel_display_wa.o \ From 074edfbdfba25493324807f749fbc86bf0af3a2d Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:40 -0800 Subject: [PATCH 0059/1610] drm/xe/forcewake: Add scope-based cleanup for forcewake Since forcewake uses a reference counting get/put model, there are many places where we need to be careful to drop the forcewake reference when bailing out of a function early on an error path. Add scope-based cleanup options that can be used in place of explicit get/put to help prevent mistakes in this area. Examples: CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); Obtain forcewake on the XE_FW_GT domain and hold it until the end of the current block. The wakeref will be dropped automatically when the current scope is exited by any means (return, break, reaching the end of the block, etc.). xe_with_force_wake(fw_ref, gt_to_fw(ss->gt), XE_FORCEWAKE_ALL) { ... } Hold all forcewake domains for the following block. As with the CLASS usage, forcewake will be dropped automatically when the block is exited by any means. Use of these cleanup helpers should allow us to remove some ugly goto-based error handling and help avoid mistakes in functions with lots of early error exits. An 'xe_force_wake_release_only' class is also added for cases where a forcewake reference is passed in from another function and the current function is responsible for releasing it in every flow and error path. v2: - Create a separate constructor that just wraps xe_force_wake_get for use in the class. This eliminates the need to update the signature of xe_force_wake_get(). (Michal) v3: - Wrap xe_with_force_wake's 'done' marker in __UNIQUE_ID. (Gustavo) - Add a note to xe_force_wake_get()'s kerneldoc explaining that scope-based cleanup is preferred when possible. (Gustavo) - Add an xe_force_wake_release_only class. (Gustavo) v4: - Add NULL check on fw in release_only variant. (Gustavo) Cc: Michal Wajdeczko Cc: Gustavo Sousa Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-30-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_force_wake.c | 7 ++++++ drivers/gpu/drm/xe/xe_force_wake.h | 40 ++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_force_wake.c b/drivers/gpu/drm/xe/xe_force_wake.c index c59a9b330697..76e054f314ee 100644 --- a/drivers/gpu/drm/xe/xe_force_wake.c +++ b/drivers/gpu/drm/xe/xe_force_wake.c @@ -166,6 +166,13 @@ static int domain_sleep_wait(struct xe_gt *gt, * xe_force_wake_ref_has_domain() function. Caller must call * xe_force_wake_put() function to decrease incremented refcounts. * + * When possible, scope-based forcewake (through CLASS(xe_force_wake, ...) or + * xe_with_force_wake()) should be used instead of direct calls to this + * function. Direct usage of get/put should only be used when the function + * has goto-based flows that can interfere with scope-based cleanup, or when + * the lifetime of the forcewake reference does not match a specific scope + * (e.g., forcewake obtained in one function and released in a different one). + * * Return: opaque reference to woken domains or zero if none of requested * domains were awake. */ diff --git a/drivers/gpu/drm/xe/xe_force_wake.h b/drivers/gpu/drm/xe/xe_force_wake.h index 0e3e84bfa51c..1e2198f6a007 100644 --- a/drivers/gpu/drm/xe/xe_force_wake.h +++ b/drivers/gpu/drm/xe/xe_force_wake.h @@ -61,4 +61,44 @@ xe_force_wake_ref_has_domain(unsigned int fw_ref, enum xe_force_wake_domains dom return fw_ref & domain; } +struct xe_force_wake_ref { + struct xe_force_wake *fw; + unsigned int domains; +}; + +static struct xe_force_wake_ref +xe_force_wake_constructor(struct xe_force_wake *fw, unsigned int domains) +{ + struct xe_force_wake_ref fw_ref = { .fw = fw }; + + fw_ref.domains = xe_force_wake_get(fw, domains); + + return fw_ref; +} + +DEFINE_CLASS(xe_force_wake, struct xe_force_wake_ref, + xe_force_wake_put(_T.fw, _T.domains), + xe_force_wake_constructor(fw, domains), + struct xe_force_wake *fw, unsigned int domains); + +/* + * Scoped helper for the forcewake class, using the same trick as scoped_guard() + * to bind the lifetime to the next statement/block. + */ +#define __xe_with_force_wake(ref, fw, domains, done) \ + for (CLASS(xe_force_wake, ref)(fw, domains), *(done) = NULL; \ + !(done); (done) = (void *)1) + +#define xe_with_force_wake(ref, fw, domains) \ + __xe_with_force_wake(ref, fw, domains, __UNIQUE_ID(done)) + +/* + * Used when xe_force_wake_constructor() has already been called by another + * function and the current function is responsible for releasing the forcewake + * reference in all possible cases and error paths. + */ +DEFINE_CLASS(xe_force_wake_release_only, struct xe_force_wake_ref, + if (_T.fw) xe_force_wake_put(_T.fw, _T.domains), fw_ref, + struct xe_force_wake_ref fw_ref); + #endif From 59e7528dbfd52efbed05e0f11b2143217a12bc74 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:41 -0800 Subject: [PATCH 0060/1610] drm/xe/pm: Add scope-based cleanup helper for runtime PM Add a scope-based helpers for runtime PM that may be used to simplify cleanup logic and potentially avoid goto-based cleanup. For example, using guard(xe_pm_runtime)(xe); will get runtime PM and cause a corresponding put to occur automatically when the current scope is exited. 'xe_pm_runtime_noresume' can be used as a guard replacement for the corresponding 'noresume' variant. There's also an xe_pm_runtime_ioctl conditional guard that can be used as a replacement for xe_runtime_ioctl(): ACQUIRE(xe_pm_runtime_ioctl, pm)(xe); if ((ret = ACQUIRE_ERR(xe_pm_runtime_ioctl, &pm)) < 0) /* failed */ In a few rare cases (such as gt_reset_worker()) we need to ensure that runtime PM is dropped when the function is exited by any means (including error paths), but the function does not need to acquire runtime PM because that has already been done earlier by a different function. For these special cases, an 'xe_pm_runtime_release_only' guard can be used to handle the release without doing an acquisition. These guards will be used in future patches to eliminate some of our goto-based cleanup. v2: - Specify success condition for xe_pm runtime_ioctl as _RET >= 0 so that positive values will be properly identified as success and trigger destructor cleanup properly. v3: - Add comments to the kerneldoc for the existing 'get' functions indicating that scope-based handling should be preferred where possible. (Gustavo) Cc: Gustavo Sousa Reviewed-by: Michal Wajdeczko Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-31-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_pm.c | 21 +++++++++++++++++++++ drivers/gpu/drm/xe/xe_pm.h | 17 +++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c index 44924512830f..766922530265 100644 --- a/drivers/gpu/drm/xe/xe_pm.c +++ b/drivers/gpu/drm/xe/xe_pm.c @@ -726,6 +726,13 @@ static void xe_pm_runtime_lockdep_prime(void) /** * xe_pm_runtime_get - Get a runtime_pm reference and resume synchronously * @xe: xe device instance + * + * When possible, scope-based runtime PM (through guard(xe_pm_runtime)) is + * be preferred over direct usage of this function. Manual get/put handling + * should only be used when the function contains goto-based logic which + * can break scope-based handling, or when the lifetime of the runtime PM + * reference does not match a specific scope (e.g., runtime PM obtained in one + * function and released in a different one). */ void xe_pm_runtime_get(struct xe_device *xe) { @@ -758,6 +765,13 @@ void xe_pm_runtime_put(struct xe_device *xe) * xe_pm_runtime_get_ioctl - Get a runtime_pm reference before ioctl * @xe: xe device instance * + * When possible, scope-based runtime PM (through + * ACQUIRE(xe_pm_runtime_ioctl, ...)) is be preferred over direct usage of this + * function. Manual get/put handling should only be used when the function + * contains goto-based logic which can break scope-based handling, or when the + * lifetime of the runtime PM reference does not match a specific scope (e.g., + * runtime PM obtained in one function and released in a different one). + * * Returns: Any number greater than or equal to 0 for success, negative error * code otherwise. */ @@ -827,6 +841,13 @@ static bool xe_pm_suspending_or_resuming(struct xe_device *xe) * It will warn if not protected. * The reference should be put back after this function regardless, since it * will always bump the usage counter, regardless. + * + * When possible, scope-based runtime PM (through guard(xe_pm_runtime_noresume)) + * is be preferred over direct usage of this function. Manual get/put handling + * should only be used when the function contains goto-based logic which can + * break scope-based handling, or when the lifetime of the runtime PM reference + * does not match a specific scope (e.g., runtime PM obtained in one function + * and released in a different one). */ void xe_pm_runtime_get_noresume(struct xe_device *xe) { diff --git a/drivers/gpu/drm/xe/xe_pm.h b/drivers/gpu/drm/xe/xe_pm.h index f7f89a18b6fc..6b27039e7b2d 100644 --- a/drivers/gpu/drm/xe/xe_pm.h +++ b/drivers/gpu/drm/xe/xe_pm.h @@ -6,6 +6,7 @@ #ifndef _XE_PM_H_ #define _XE_PM_H_ +#include #include #define DEFAULT_VRAM_THRESHOLD 300 /* in MB */ @@ -37,4 +38,20 @@ int xe_pm_block_on_suspend(struct xe_device *xe); void xe_pm_might_block_on_suspend(void); int xe_pm_module_init(void); +static inline void __xe_pm_runtime_noop(struct xe_device *xe) {} + +DEFINE_GUARD(xe_pm_runtime, struct xe_device *, + xe_pm_runtime_get(_T), xe_pm_runtime_put(_T)) +DEFINE_GUARD(xe_pm_runtime_noresume, struct xe_device *, + xe_pm_runtime_get_noresume(_T), xe_pm_runtime_put(_T)) +DEFINE_GUARD_COND(xe_pm_runtime, _ioctl, xe_pm_runtime_get_ioctl(_T), _RET >= 0) + +/* + * Used when a function needs to release runtime PM in all possible cases + * and error paths, but the wakeref was already acquired by a different + * function (i.e., get() has already happened so only a put() is needed). + */ +DEFINE_GUARD(xe_pm_runtime_release_only, struct xe_device *, + __xe_pm_runtime_noop(_T), xe_pm_runtime_put(_T)); + #endif From 83d2ea17d53f538724f0222f1cb5f60061efb06a Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:42 -0800 Subject: [PATCH 0061/1610] drm/xe/gt: Use scope-based cleanup Using scope-based cleanup for forcewake and runtime PM allows us to reduce or eliminate some of the goto-based error handling and simplify several functions. v2: - Drop changes to do_gt_restart(). This function still has goto-based logic, making scope-based cleanup unsafe for now. (Gustavo) Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-32-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_gt.c | 130 ++++++++++++------------------------- 1 file changed, 41 insertions(+), 89 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index 6d479948bf21..514ed50e6d83 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -103,14 +103,13 @@ void xe_gt_sanitize(struct xe_gt *gt) static void xe_gt_enable_host_l2_vram(struct xe_gt *gt) { - unsigned int fw_ref; u32 reg; if (!XE_GT_WA(gt, 16023588340)) return; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return; if (xe_gt_is_main_type(gt)) { @@ -120,12 +119,10 @@ static void xe_gt_enable_host_l2_vram(struct xe_gt *gt) } xe_gt_mcr_multicast_write(gt, XEHPC_L3CLOS_MASK(3), 0xF); - xe_force_wake_put(gt_to_fw(gt), fw_ref); } static void xe_gt_disable_host_l2_vram(struct xe_gt *gt) { - unsigned int fw_ref; u32 reg; if (!XE_GT_WA(gt, 16023588340)) @@ -134,15 +131,13 @@ static void xe_gt_disable_host_l2_vram(struct xe_gt *gt) if (xe_gt_is_media_type(gt)) return; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return; reg = xe_gt_mcr_unicast_read_any(gt, XE2_GAMREQSTRM_CTRL); reg &= ~CG_DIS_CNTLBUS; xe_gt_mcr_multicast_write(gt, XE2_GAMREQSTRM_CTRL, reg); - - xe_force_wake_put(gt_to_fw(gt), fw_ref); } static void gt_reset_worker(struct work_struct *w); @@ -389,7 +384,6 @@ put_exec_queue: int xe_gt_init_early(struct xe_gt *gt) { - unsigned int fw_ref; int err; if (IS_SRIOV_PF(gt_to_xe(gt))) { @@ -436,13 +430,12 @@ int xe_gt_init_early(struct xe_gt *gt) if (err) return err; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return -ETIMEDOUT; xe_gt_mcr_init_early(gt); xe_pat_init(gt); - xe_force_wake_put(gt_to_fw(gt), fw_ref); return 0; } @@ -460,16 +453,15 @@ static void dump_pat_on_error(struct xe_gt *gt) static int gt_init_with_gt_forcewake(struct xe_gt *gt) { - unsigned int fw_ref; int err; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return -ETIMEDOUT; err = xe_uc_init(>->uc); if (err) - goto err_force_wake; + return err; xe_gt_topology_init(gt); xe_gt_mcr_init(gt); @@ -478,7 +470,7 @@ static int gt_init_with_gt_forcewake(struct xe_gt *gt) if (xe_gt_is_main_type(gt)) { err = xe_ggtt_init(gt_to_tile(gt)->mem.ggtt); if (err) - goto err_force_wake; + return err; if (IS_SRIOV_PF(gt_to_xe(gt))) xe_lmtt_init(>_to_tile(gt)->sriov.pf.lmtt); } @@ -492,17 +484,17 @@ static int gt_init_with_gt_forcewake(struct xe_gt *gt) err = xe_hw_engines_init_early(gt); if (err) { dump_pat_on_error(gt); - goto err_force_wake; + return err; } err = xe_hw_engine_class_sysfs_init(gt); if (err) - goto err_force_wake; + return err; /* Initialize CCS mode sysfs after early initialization of HW engines */ err = xe_gt_ccs_mode_sysfs_init(gt); if (err) - goto err_force_wake; + return err; /* * Stash hardware-reported version. Since this register does not exist @@ -510,25 +502,16 @@ static int gt_init_with_gt_forcewake(struct xe_gt *gt) */ gt->info.gmdid = xe_mmio_read32(>->mmio, GMD_ID); - xe_force_wake_put(gt_to_fw(gt), fw_ref); return 0; - -err_force_wake: - xe_force_wake_put(gt_to_fw(gt), fw_ref); - - return err; } static int gt_init_with_all_forcewake(struct xe_gt *gt) { - unsigned int fw_ref; int err; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) { - err = -ETIMEDOUT; - goto err_force_wake; - } + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL); + if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)) + return -ETIMEDOUT; xe_gt_mcr_set_implicit_defaults(gt); xe_wa_process_gt(gt); @@ -537,20 +520,20 @@ static int gt_init_with_all_forcewake(struct xe_gt *gt) err = xe_gt_clock_init(gt); if (err) - goto err_force_wake; + return err; xe_mocs_init(gt); err = xe_execlist_init(gt); if (err) - goto err_force_wake; + return err; err = xe_hw_engines_init(gt); if (err) - goto err_force_wake; + return err; err = xe_uc_init_post_hwconfig(>->uc); if (err) - goto err_force_wake; + return err; if (xe_gt_is_main_type(gt)) { /* @@ -561,10 +544,8 @@ static int gt_init_with_all_forcewake(struct xe_gt *gt) gt->usm.bb_pool = xe_sa_bo_manager_init(gt_to_tile(gt), IS_DGFX(xe) ? SZ_1M : SZ_512K, 16); - if (IS_ERR(gt->usm.bb_pool)) { - err = PTR_ERR(gt->usm.bb_pool); - goto err_force_wake; - } + if (IS_ERR(gt->usm.bb_pool)) + return PTR_ERR(gt->usm.bb_pool); } } @@ -573,12 +554,12 @@ static int gt_init_with_all_forcewake(struct xe_gt *gt) err = xe_migrate_init(tile->migrate); if (err) - goto err_force_wake; + return err; } err = xe_uc_load_hw(>->uc); if (err) - goto err_force_wake; + return err; /* Configure default CCS mode of 1 engine with all resources */ if (xe_gt_ccs_mode_enabled(gt)) { @@ -592,14 +573,7 @@ static int gt_init_with_all_forcewake(struct xe_gt *gt) if (IS_SRIOV_PF(gt_to_xe(gt))) xe_gt_sriov_pf_init_hw(gt); - xe_force_wake_put(gt_to_fw(gt), fw_ref); - return 0; - -err_force_wake: - xe_force_wake_put(gt_to_fw(gt), fw_ref); - - return err; } static void xe_gt_fini(void *arg) @@ -902,56 +876,42 @@ void xe_gt_reset_async(struct xe_gt *gt) void xe_gt_suspend_prepare(struct xe_gt *gt) { - unsigned int fw_ref; - - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL); xe_uc_suspend_prepare(>->uc); - - xe_force_wake_put(gt_to_fw(gt), fw_ref); } int xe_gt_suspend(struct xe_gt *gt) { - unsigned int fw_ref; int err; xe_gt_dbg(gt, "suspending\n"); xe_gt_sanitize(gt); - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) - goto err_msg; + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL); + if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)) { + xe_gt_err(gt, "suspend failed (%pe)\n", ERR_PTR(-ETIMEDOUT)); + return -ETIMEDOUT; + } err = xe_uc_suspend(>->uc); - if (err) - goto err_force_wake; + if (err) { + xe_gt_err(gt, "suspend failed (%pe)\n", ERR_PTR(err)); + return err; + } xe_gt_idle_disable_pg(gt); xe_gt_disable_host_l2_vram(gt); - xe_force_wake_put(gt_to_fw(gt), fw_ref); xe_gt_dbg(gt, "suspended\n"); return 0; - -err_msg: - err = -ETIMEDOUT; -err_force_wake: - xe_force_wake_put(gt_to_fw(gt), fw_ref); - xe_gt_err(gt, "suspend failed (%pe)\n", ERR_PTR(err)); - - return err; } void xe_gt_shutdown(struct xe_gt *gt) { - unsigned int fw_ref; - - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL); do_gt_reset(gt); - xe_force_wake_put(gt_to_fw(gt), fw_ref); } /** @@ -976,32 +936,24 @@ int xe_gt_sanitize_freq(struct xe_gt *gt) int xe_gt_resume(struct xe_gt *gt) { - unsigned int fw_ref; int err; xe_gt_dbg(gt, "resuming\n"); - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) - goto err_msg; + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL); + if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)) { + xe_gt_err(gt, "resume failed (%pe)\n", ERR_PTR(-ETIMEDOUT)); + return -ETIMEDOUT; + } err = do_gt_restart(gt); if (err) - goto err_force_wake; + return err; xe_gt_idle_enable_pg(gt); - xe_force_wake_put(gt_to_fw(gt), fw_ref); xe_gt_dbg(gt, "resumed\n"); return 0; - -err_msg: - err = -ETIMEDOUT; -err_force_wake: - xe_force_wake_put(gt_to_fw(gt), fw_ref); - xe_gt_err(gt, "resume failed (%pe)\n", ERR_PTR(err)); - - return err; } struct xe_hw_engine *xe_gt_hw_engine(struct xe_gt *gt, From 917714f2787db1f42cc41705e02cb381734ad663 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:43 -0800 Subject: [PATCH 0062/1610] drm/xe/gt_idle: Use scope-based cleanup Use scope-based cleanup for runtime PM and forcewake in the GT idle code. v2: - Use scoped_guard() over guard() in idle_status_show() and idle_residency_ms_show(). (Gustavo) - Eliminate unnecessary 'ret' local variable in name_show(). Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-33-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_gt_idle.c | 41 ++++++++++----------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_idle.c b/drivers/gpu/drm/xe/xe_gt_idle.c index bdc9d9877ec4..3ca7bd7c9bcd 100644 --- a/drivers/gpu/drm/xe/xe_gt_idle.c +++ b/drivers/gpu/drm/xe/xe_gt_idle.c @@ -103,7 +103,6 @@ void xe_gt_idle_enable_pg(struct xe_gt *gt) struct xe_gt_idle *gtidle = >->gtidle; struct xe_mmio *mmio = >->mmio; u32 vcs_mask, vecs_mask; - unsigned int fw_ref; int i, j; if (IS_SRIOV_VF(xe)) @@ -135,7 +134,7 @@ void xe_gt_idle_enable_pg(struct xe_gt *gt) } } - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); if (xe->info.skip_guc_pc) { /* * GuC sets the hysteresis value when GuC PC is enabled @@ -146,13 +145,11 @@ void xe_gt_idle_enable_pg(struct xe_gt *gt) } xe_mmio_write32(mmio, POWERGATE_ENABLE, gtidle->powergate_enable); - xe_force_wake_put(gt_to_fw(gt), fw_ref); } void xe_gt_idle_disable_pg(struct xe_gt *gt) { struct xe_gt_idle *gtidle = >->gtidle; - unsigned int fw_ref; if (IS_SRIOV_VF(gt_to_xe(gt))) return; @@ -160,9 +157,8 @@ void xe_gt_idle_disable_pg(struct xe_gt *gt) xe_device_assert_mem_access(gt_to_xe(gt)); gtidle->powergate_enable = 0; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); xe_mmio_write32(>->mmio, POWERGATE_ENABLE, gtidle->powergate_enable); - xe_force_wake_put(gt_to_fw(gt), fw_ref); } /** @@ -181,7 +177,6 @@ int xe_gt_idle_pg_print(struct xe_gt *gt, struct drm_printer *p) enum xe_gt_idle_state state; u32 pg_enabled, pg_status = 0; u32 vcs_mask, vecs_mask; - unsigned int fw_ref; int n; /* * Media Slices @@ -218,14 +213,12 @@ int xe_gt_idle_pg_print(struct xe_gt *gt, struct drm_printer *p) /* Do not wake the GT to read powergating status */ if (state != GT_IDLE_C6) { - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return -ETIMEDOUT; pg_enabled = xe_mmio_read32(>->mmio, POWERGATE_ENABLE); pg_status = xe_mmio_read32(>->mmio, POWERGATE_DOMAIN_STATUS); - - xe_force_wake_put(gt_to_fw(gt), fw_ref); } if (gt->info.engine_mask & XE_HW_ENGINE_RCS_MASK) { @@ -263,13 +256,9 @@ static ssize_t name_show(struct kobject *kobj, struct device *dev = kobj_to_dev(kobj); struct xe_gt_idle *gtidle = dev_to_gtidle(dev); struct xe_guc_pc *pc = gtidle_to_pc(gtidle); - ssize_t ret; - xe_pm_runtime_get(pc_to_xe(pc)); - ret = sysfs_emit(buff, "%s\n", gtidle->name); - xe_pm_runtime_put(pc_to_xe(pc)); - - return ret; + guard(xe_pm_runtime)(pc_to_xe(pc)); + return sysfs_emit(buff, "%s\n", gtidle->name); } static struct kobj_attribute name_attr = __ATTR_RO(name); @@ -281,9 +270,8 @@ static ssize_t idle_status_show(struct kobject *kobj, struct xe_guc_pc *pc = gtidle_to_pc(gtidle); enum xe_gt_idle_state state; - xe_pm_runtime_get(pc_to_xe(pc)); - state = gtidle->idle_status(pc); - xe_pm_runtime_put(pc_to_xe(pc)); + scoped_guard(xe_pm_runtime, pc_to_xe(pc)) + state = gtidle->idle_status(pc); return sysfs_emit(buff, "%s\n", gt_idle_state_to_string(state)); } @@ -311,9 +299,8 @@ static ssize_t idle_residency_ms_show(struct kobject *kobj, struct xe_guc_pc *pc = gtidle_to_pc(gtidle); u64 residency; - xe_pm_runtime_get(pc_to_xe(pc)); - residency = xe_gt_idle_residency_msec(gtidle); - xe_pm_runtime_put(pc_to_xe(pc)); + scoped_guard(xe_pm_runtime, pc_to_xe(pc)) + residency = xe_gt_idle_residency_msec(gtidle); return sysfs_emit(buff, "%llu\n", residency); } @@ -396,21 +383,17 @@ void xe_gt_idle_enable_c6(struct xe_gt *gt) int xe_gt_idle_disable_c6(struct xe_gt *gt) { - unsigned int fw_ref; - xe_device_assert_mem_access(gt_to_xe(gt)); if (IS_SRIOV_VF(gt_to_xe(gt))) return 0; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return -ETIMEDOUT; xe_mmio_write32(>->mmio, RC_CONTROL, 0); xe_mmio_write32(>->mmio, RC_STATE, 0); - xe_force_wake_put(gt_to_fw(gt), fw_ref); - return 0; } From 3947e482b5ebb95be49803fdd584a38f005f5042 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:44 -0800 Subject: [PATCH 0063/1610] drm/xe/guc: Use scope-based cleanup Use scope-based cleanup for forcewake and runtime PM. Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-34-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_guc.c | 13 ++++--------- drivers/gpu/drm/xe/xe_guc_log.c | 10 ++++------ drivers/gpu/drm/xe/xe_guc_submit.c | 11 +++-------- drivers/gpu/drm/xe/xe_guc_tlb_inval.c | 4 +--- 4 files changed, 12 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c index a686b04879d6..cf92de1c88a7 100644 --- a/drivers/gpu/drm/xe/xe_guc.c +++ b/drivers/gpu/drm/xe/xe_guc.c @@ -660,11 +660,9 @@ static void guc_fini_hw(void *arg) { struct xe_guc *guc = arg; struct xe_gt *gt = guc_to_gt(guc); - unsigned int fw_ref; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - xe_uc_sanitize_reset(&guc_to_gt(guc)->uc); - xe_force_wake_put(gt_to_fw(gt), fw_ref); + xe_with_force_wake(fw_ref, gt_to_fw(gt), XE_FORCEWAKE_ALL) + xe_uc_sanitize_reset(&guc_to_gt(guc)->uc); guc_g2g_fini(guc); } @@ -1621,15 +1619,14 @@ int xe_guc_start(struct xe_guc *guc) void xe_guc_print_info(struct xe_guc *guc, struct drm_printer *p) { struct xe_gt *gt = guc_to_gt(guc); - unsigned int fw_ref; u32 status; int i; xe_uc_fw_print(&guc->fw, p); if (!IS_SRIOV_VF(gt_to_xe(gt))) { - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return; status = xe_mmio_read32(>->mmio, GUC_STATUS); @@ -1649,8 +1646,6 @@ void xe_guc_print_info(struct xe_guc *guc, struct drm_printer *p) drm_printf(p, "\t%2d: \t0x%x\n", i, xe_mmio_read32(>->mmio, SOFT_SCRATCH(i))); } - - xe_force_wake_put(gt_to_fw(gt), fw_ref); } drm_puts(p, "\n"); diff --git a/drivers/gpu/drm/xe/xe_guc_log.c b/drivers/gpu/drm/xe/xe_guc_log.c index c01ccb35dc75..0c704a11078a 100644 --- a/drivers/gpu/drm/xe/xe_guc_log.c +++ b/drivers/gpu/drm/xe/xe_guc_log.c @@ -145,7 +145,6 @@ struct xe_guc_log_snapshot *xe_guc_log_snapshot_capture(struct xe_guc_log *log, struct xe_device *xe = log_to_xe(log); struct xe_guc *guc = log_to_guc(log); struct xe_gt *gt = log_to_gt(log); - unsigned int fw_ref; size_t remain; int i; @@ -165,13 +164,12 @@ struct xe_guc_log_snapshot *xe_guc_log_snapshot_capture(struct xe_guc_log *log, remain -= size; } - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) { + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) snapshot->stamp = ~0ULL; - } else { + else snapshot->stamp = xe_mmio_read64_2x32(>->mmio, GUC_PMTIMESTAMP_LO); - xe_force_wake_put(gt_to_fw(gt), fw_ref); - } + snapshot->ktime = ktime_get_boottime_ns(); snapshot->level = log->level; snapshot->ver_found = guc->fw.versions.found[XE_UC_FW_VER_RELEASE]; diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index d4ffdb71ef3d..7e0882074a99 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -1225,7 +1225,6 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) struct xe_guc *guc = exec_queue_to_guc(q); const char *process_name = "no process"; struct xe_device *xe = guc_to_xe(guc); - unsigned int fw_ref; int err = -ETIME; pid_t pid = -1; int i = 0; @@ -1258,13 +1257,11 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) if (!exec_queue_killed(q) && !xe->devcoredump.captured && !xe_guc_capture_get_matching_and_lock(q)) { /* take force wake before engine register manual capture */ - fw_ref = xe_force_wake_get(gt_to_fw(q->gt), XE_FORCEWAKE_ALL); - if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(q->gt), XE_FORCEWAKE_ALL); + if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)) xe_gt_info(q->gt, "failed to get forcewake for coredump capture\n"); xe_engine_snapshot_capture_for_queue(q); - - xe_force_wake_put(gt_to_fw(q->gt), fw_ref); } /* @@ -1455,7 +1452,7 @@ static void __guc_exec_queue_destroy_async(struct work_struct *w) struct xe_exec_queue *q = ge->q; struct xe_guc *guc = exec_queue_to_guc(q); - xe_pm_runtime_get(guc_to_xe(guc)); + guard(xe_pm_runtime)(guc_to_xe(guc)); trace_xe_exec_queue_destroy(q); if (xe_exec_queue_is_lr(q)) @@ -1464,8 +1461,6 @@ static void __guc_exec_queue_destroy_async(struct work_struct *w) cancel_delayed_work_sync(&ge->sched.base.work_tdr); xe_exec_queue_fini(q); - - xe_pm_runtime_put(guc_to_xe(guc)); } static void guc_exec_queue_destroy_async(struct xe_exec_queue *q) diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c index a80175c7c478..848d3493df10 100644 --- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c +++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c @@ -71,12 +71,11 @@ static int send_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval, u32 seqno) return send_tlb_inval(guc, action, ARRAY_SIZE(action)); } else if (xe_device_uc_enabled(xe) && !xe_device_wedged(xe)) { struct xe_mmio *mmio = >->mmio; - unsigned int fw_ref; if (IS_SRIOV_VF(xe)) return -ECANCELED; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); if (xe->info.platform == XE_PVC || GRAPHICS_VER(xe) >= 20) { xe_mmio_write32(mmio, PVC_GUC_TLB_INV_DESC1, PVC_GUC_TLB_INV_DESC1_INVALIDATE); @@ -86,7 +85,6 @@ static int send_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval, u32 seqno) xe_mmio_write32(mmio, GUC_TLB_INV_CR, GUC_TLB_INV_CR_INVALIDATE); } - xe_force_wake_put(gt_to_fw(gt), fw_ref); } return -ECANCELED; From e9bc4162bf39154c1eb8d5edb11a00fc30771c39 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:45 -0800 Subject: [PATCH 0064/1610] drm/xe/guc_pc: Use scope-based cleanup Use scope-based cleanup for forcewake and runtime PM in the GuC PC code. This allows us to eliminate to goto-based cleanup and simplifies some other functions. Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-35-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_guc_pc.c | 62 ++++++++++------------------------ 1 file changed, 17 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c index 951a49fb1d3e..e2e6edb851ae 100644 --- a/drivers/gpu/drm/xe/xe_guc_pc.c +++ b/drivers/gpu/drm/xe/xe_guc_pc.c @@ -499,21 +499,17 @@ u32 xe_guc_pc_get_cur_freq_fw(struct xe_guc_pc *pc) int xe_guc_pc_get_cur_freq(struct xe_guc_pc *pc, u32 *freq) { struct xe_gt *gt = pc_to_gt(pc); - unsigned int fw_ref; /* * GuC SLPC plays with cur freq request when GuCRC is enabled * Block RC6 for a more reliable read. */ - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT)) { - xe_force_wake_put(gt_to_fw(gt), fw_ref); + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FW_GT)) return -ETIMEDOUT; - } *freq = get_cur_freq(gt); - xe_force_wake_put(gt_to_fw(gt), fw_ref); return 0; } @@ -1087,13 +1083,8 @@ int xe_guc_pc_gucrc_disable(struct xe_guc_pc *pc) */ int xe_guc_pc_override_gucrc_mode(struct xe_guc_pc *pc, enum slpc_gucrc_mode mode) { - int ret; - - xe_pm_runtime_get(pc_to_xe(pc)); - ret = pc_action_set_param(pc, SLPC_PARAM_PWRGATE_RC_MODE, mode); - xe_pm_runtime_put(pc_to_xe(pc)); - - return ret; + guard(xe_pm_runtime)(pc_to_xe(pc)); + return pc_action_set_param(pc, SLPC_PARAM_PWRGATE_RC_MODE, mode); } /** @@ -1104,13 +1095,8 @@ int xe_guc_pc_override_gucrc_mode(struct xe_guc_pc *pc, enum slpc_gucrc_mode mod */ int xe_guc_pc_unset_gucrc_mode(struct xe_guc_pc *pc) { - int ret; - - xe_pm_runtime_get(pc_to_xe(pc)); - ret = pc_action_unset_param(pc, SLPC_PARAM_PWRGATE_RC_MODE); - xe_pm_runtime_put(pc_to_xe(pc)); - - return ret; + guard(xe_pm_runtime)(pc_to_xe(pc)); + return pc_action_unset_param(pc, SLPC_PARAM_PWRGATE_RC_MODE); } static void pc_init_pcode_freq(struct xe_guc_pc *pc) @@ -1198,7 +1184,7 @@ int xe_guc_pc_set_power_profile(struct xe_guc_pc *pc, const char *buf) return -EINVAL; guard(mutex)(&pc->freq_lock); - xe_pm_runtime_get_noresume(pc_to_xe(pc)); + guard(xe_pm_runtime_noresume)(pc_to_xe(pc)); ret = pc_action_set_param(pc, SLPC_PARAM_POWER_PROFILE, @@ -1209,8 +1195,6 @@ int xe_guc_pc_set_power_profile(struct xe_guc_pc *pc, const char *buf) else pc->power_profile = val; - xe_pm_runtime_put(pc_to_xe(pc)); - return ret; } @@ -1223,17 +1207,14 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) struct xe_device *xe = pc_to_xe(pc); struct xe_gt *gt = pc_to_gt(pc); u32 size = PAGE_ALIGN(sizeof(struct slpc_shared_data)); - unsigned int fw_ref; ktime_t earlier; int ret; xe_gt_assert(gt, xe_device_uc_enabled(xe)); - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT)) { - xe_force_wake_put(gt_to_fw(gt), fw_ref); + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FW_GT)) return -ETIMEDOUT; - } if (xe->info.skip_guc_pc) { if (xe->info.platform != XE_PVC) @@ -1241,9 +1222,7 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) /* Request max possible since dynamic freq mgmt is not enabled */ pc_set_cur_freq(pc, UINT_MAX); - - ret = 0; - goto out; + return 0; } xe_map_memset(xe, &pc->bo->vmap, 0, 0, size); @@ -1252,7 +1231,7 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) earlier = ktime_get(); ret = pc_action_reset(pc); if (ret) - goto out; + return ret; if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING, SLPC_RESET_TIMEOUT_MS)) { @@ -1263,8 +1242,7 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING, SLPC_RESET_EXTENDED_TIMEOUT_MS)) { xe_gt_err(gt, "GuC PC Start failed: Dynamic GT frequency control and GT sleep states are now disabled.\n"); - ret = -EIO; - goto out; + return -EIO; } xe_gt_warn(gt, "GuC PC excessive start time: %lldms", @@ -1273,21 +1251,20 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) ret = pc_init_freqs(pc); if (ret) - goto out; + return ret; ret = pc_set_mert_freq_cap(pc); if (ret) - goto out; + return ret; if (xe->info.platform == XE_PVC) { xe_guc_pc_gucrc_disable(pc); - ret = 0; - goto out; + return 0; } ret = pc_action_setup_gucrc(pc, GUCRC_FIRMWARE_CONTROL); if (ret) - goto out; + return ret; /* Enable SLPC Optimized Strategy for compute */ ret = pc_action_set_strategy(pc, SLPC_OPTIMIZED_STRATEGY_COMPUTE); @@ -1297,8 +1274,6 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) if (unlikely(ret)) xe_gt_err(gt, "Failed to set SLPC power profile: %pe\n", ERR_PTR(ret)); -out: - xe_force_wake_put(gt_to_fw(gt), fw_ref); return ret; } @@ -1330,19 +1305,16 @@ static void xe_guc_pc_fini_hw(void *arg) { struct xe_guc_pc *pc = arg; struct xe_device *xe = pc_to_xe(pc); - unsigned int fw_ref; if (xe_device_wedged(xe)) return; - fw_ref = xe_force_wake_get(gt_to_fw(pc_to_gt(pc)), XE_FORCEWAKE_ALL); + CLASS(xe_force_wake, fw_ref)(gt_to_fw(pc_to_gt(pc)), XE_FORCEWAKE_ALL); xe_guc_pc_gucrc_disable(pc); XE_WARN_ON(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))); - - xe_force_wake_put(gt_to_fw(pc_to_gt(pc)), fw_ref); } /** From 008db7d4e1a465bf65c5cf7a4cc7ab041b2dc00e Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:46 -0800 Subject: [PATCH 0065/1610] drm/xe/mocs: Use scope-based cleanup Using scope-based cleanup for runtime PM and forcewake in the MOCS code allows us to eliminate some goto-based error handling and simplify some other functions. Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-36-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/tests/xe_mocs.c | 17 ++++++----------- drivers/gpu/drm/xe/xe_mocs.c | 18 ++++++------------ 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/xe/tests/xe_mocs.c b/drivers/gpu/drm/xe/tests/xe_mocs.c index 6bb278167aaf..28374330b894 100644 --- a/drivers/gpu/drm/xe/tests/xe_mocs.c +++ b/drivers/gpu/drm/xe/tests/xe_mocs.c @@ -43,14 +43,12 @@ static void read_l3cc_table(struct xe_gt *gt, { struct kunit *test = kunit_get_current_test(); u32 l3cc, l3cc_expected; - unsigned int fw_ref, i; + unsigned int i; u32 reg_val; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) { - xe_force_wake_put(gt_to_fw(gt), fw_ref); + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL); + if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)) KUNIT_FAIL_AND_ABORT(test, "Forcewake Failed.\n"); - } for (i = 0; i < info->num_mocs_regs; i++) { if (!(i & 1)) { @@ -74,7 +72,6 @@ static void read_l3cc_table(struct xe_gt *gt, KUNIT_EXPECT_EQ_MSG(test, l3cc_expected, l3cc, "l3cc idx=%u has incorrect val.\n", i); } - xe_force_wake_put(gt_to_fw(gt), fw_ref); } static void read_mocs_table(struct xe_gt *gt, @@ -82,14 +79,14 @@ static void read_mocs_table(struct xe_gt *gt, { struct kunit *test = kunit_get_current_test(); u32 mocs, mocs_expected; - unsigned int fw_ref, i; + unsigned int i; u32 reg_val; KUNIT_EXPECT_TRUE_MSG(test, info->unused_entries_index, "Unused entries index should have been defined\n"); - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - KUNIT_ASSERT_NE_MSG(test, fw_ref, 0, "Forcewake Failed.\n"); + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + KUNIT_ASSERT_NE_MSG(test, fw_ref.domains, 0, "Forcewake Failed.\n"); for (i = 0; i < info->num_mocs_regs; i++) { if (regs_are_mcr(gt)) @@ -106,8 +103,6 @@ static void read_mocs_table(struct xe_gt *gt, KUNIT_EXPECT_EQ_MSG(test, mocs_expected, mocs, "mocs reg 0x%x has incorrect val.\n", i); } - - xe_force_wake_put(gt_to_fw(gt), fw_ref); } static int mocs_kernel_test_run_device(struct xe_device *xe) diff --git a/drivers/gpu/drm/xe/xe_mocs.c b/drivers/gpu/drm/xe/xe_mocs.c index 6613d3b48a84..0b7225bd77e0 100644 --- a/drivers/gpu/drm/xe/xe_mocs.c +++ b/drivers/gpu/drm/xe/xe_mocs.c @@ -811,26 +811,20 @@ int xe_mocs_dump(struct xe_gt *gt, struct drm_printer *p) struct xe_device *xe = gt_to_xe(gt); enum xe_force_wake_domains domain; struct xe_mocs_info table; - unsigned int fw_ref, flags; - int err = 0; + unsigned int flags; flags = get_mocs_settings(xe, &table); domain = flags & HAS_LNCF_MOCS ? XE_FORCEWAKE_ALL : XE_FW_GT; - xe_pm_runtime_get_noresume(xe); - fw_ref = xe_force_wake_get(gt_to_fw(gt), domain); - if (!xe_force_wake_ref_has_domain(fw_ref, domain)) { - err = -ETIMEDOUT; - goto err_fw; - } + guard(xe_pm_runtime_noresume)(xe); + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), domain); + if (!xe_force_wake_ref_has_domain(fw_ref.domains, domain)) + return -ETIMEDOUT; table.ops->dump(&table, flags, gt, p); -err_fw: - xe_force_wake_put(gt_to_fw(gt), fw_ref); - xe_pm_runtime_put(xe); - return err; + return 0; } #if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST) From ba2562a391c66bff5bcc35583ce8c0beda862f03 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:47 -0800 Subject: [PATCH 0066/1610] drm/xe/pat: Use scope-based forcewake Use scope-based cleanup for forcewake in the PAT code to slightly simplify the code. Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-37-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_pat.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_pat.c b/drivers/gpu/drm/xe/xe_pat.c index 1b4d5d3def0f..717425dd0475 100644 --- a/drivers/gpu/drm/xe/xe_pat.c +++ b/drivers/gpu/drm/xe/xe_pat.c @@ -239,11 +239,10 @@ static void program_pat_mcr(struct xe_gt *gt, const struct xe_pat_table_entry ta static int xelp_dump(struct xe_gt *gt, struct drm_printer *p) { struct xe_device *xe = gt_to_xe(gt); - unsigned int fw_ref; int i; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return -ETIMEDOUT; drm_printf(p, "PAT table:\n"); @@ -256,7 +255,6 @@ static int xelp_dump(struct xe_gt *gt, struct drm_printer *p) XELP_MEM_TYPE_STR_MAP[mem_type], pat); } - xe_force_wake_put(gt_to_fw(gt), fw_ref); return 0; } @@ -268,11 +266,10 @@ static const struct xe_pat_ops xelp_pat_ops = { static int xehp_dump(struct xe_gt *gt, struct drm_printer *p) { struct xe_device *xe = gt_to_xe(gt); - unsigned int fw_ref; int i; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return -ETIMEDOUT; drm_printf(p, "PAT table:\n"); @@ -287,7 +284,6 @@ static int xehp_dump(struct xe_gt *gt, struct drm_printer *p) XELP_MEM_TYPE_STR_MAP[mem_type], pat); } - xe_force_wake_put(gt_to_fw(gt), fw_ref); return 0; } @@ -299,11 +295,10 @@ static const struct xe_pat_ops xehp_pat_ops = { static int xehpc_dump(struct xe_gt *gt, struct drm_printer *p) { struct xe_device *xe = gt_to_xe(gt); - unsigned int fw_ref; int i; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return -ETIMEDOUT; drm_printf(p, "PAT table:\n"); @@ -316,7 +311,6 @@ static int xehpc_dump(struct xe_gt *gt, struct drm_printer *p) REG_FIELD_GET(XEHPC_CLOS_LEVEL_MASK, pat), pat); } - xe_force_wake_put(gt_to_fw(gt), fw_ref); return 0; } @@ -328,11 +322,10 @@ static const struct xe_pat_ops xehpc_pat_ops = { static int xelpg_dump(struct xe_gt *gt, struct drm_printer *p) { struct xe_device *xe = gt_to_xe(gt); - unsigned int fw_ref; int i; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return -ETIMEDOUT; drm_printf(p, "PAT table:\n"); @@ -350,7 +343,6 @@ static int xelpg_dump(struct xe_gt *gt, struct drm_printer *p) REG_FIELD_GET(XELPG_INDEX_COH_MODE_MASK, pat), pat); } - xe_force_wake_put(gt_to_fw(gt), fw_ref); return 0; } @@ -367,12 +359,11 @@ static const struct xe_pat_ops xelpg_pat_ops = { static int xe2_dump(struct xe_gt *gt, struct drm_printer *p) { struct xe_device *xe = gt_to_xe(gt); - unsigned int fw_ref; u32 pat; int i; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return -ETIMEDOUT; drm_printf(p, "PAT table: (* = reserved entry)\n"); @@ -412,7 +403,6 @@ static int xe2_dump(struct xe_gt *gt, struct drm_printer *p) REG_FIELD_GET(XE2_COH_MODE, pat), pat); - xe_force_wake_put(gt_to_fw(gt), fw_ref); return 0; } @@ -425,12 +415,11 @@ static const struct xe_pat_ops xe2_pat_ops = { static int xe3p_xpc_dump(struct xe_gt *gt, struct drm_printer *p) { struct xe_device *xe = gt_to_xe(gt); - unsigned int fw_ref; u32 pat; int i; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return -ETIMEDOUT; drm_printf(p, "PAT table: (* = reserved entry)\n"); @@ -462,7 +451,6 @@ static int xe3p_xpc_dump(struct xe_gt *gt, struct drm_printer *p) REG_FIELD_GET(XE2_COH_MODE, pat), pat); - xe_force_wake_put(gt_to_fw(gt), fw_ref); return 0; } From 62a35753f547c7744c062750703c2ae9883b33c5 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:48 -0800 Subject: [PATCH 0067/1610] drm/xe/pxp: Use scope-based cleanup Use scope-based cleanup for forcewake and runtime pm. This allows us to eliminate some goto-based error handling and simplify other functions. Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-38-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_pxp.c | 55 ++++++++++++------------------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index bdbdbbf6a678..508f4c128a48 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -58,10 +58,9 @@ bool xe_pxp_is_enabled(const struct xe_pxp *pxp) static bool pxp_prerequisites_done(const struct xe_pxp *pxp) { struct xe_gt *gt = pxp->gt; - unsigned int fw_ref; bool ready; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL); /* * If force_wake fails we could falsely report the prerequisites as not @@ -71,14 +70,12 @@ static bool pxp_prerequisites_done(const struct xe_pxp *pxp) * PXP. Therefore, we can just log the force_wake error and not escalate * it. */ - XE_WARN_ON(!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)); + XE_WARN_ON(!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)); /* PXP requires both HuC authentication via GSC and GSC proxy initialized */ ready = xe_huc_is_authenticated(>->uc.huc, XE_HUC_AUTH_VIA_GSC) && xe_gsc_proxy_init_done(>->uc.gsc); - xe_force_wake_put(gt_to_fw(gt), fw_ref); - return ready; } @@ -104,13 +101,12 @@ int xe_pxp_get_readiness_status(struct xe_pxp *pxp) xe_uc_fw_status_to_error(pxp->gt->uc.gsc.fw.status)) return -EIO; - xe_pm_runtime_get(pxp->xe); + guard(xe_pm_runtime)(pxp->xe); /* PXP requires both HuC loaded and GSC proxy initialized */ if (pxp_prerequisites_done(pxp)) ret = 1; - xe_pm_runtime_put(pxp->xe); return ret; } @@ -135,35 +131,28 @@ static void pxp_invalidate_queues(struct xe_pxp *pxp); static int pxp_terminate_hw(struct xe_pxp *pxp) { struct xe_gt *gt = pxp->gt; - unsigned int fw_ref; int ret = 0; drm_dbg(&pxp->xe->drm, "Terminating PXP\n"); - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT)) { - ret = -EIO; - goto out; - } + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FW_GT)) + return -EIO; /* terminate the hw session */ ret = xe_pxp_submit_session_termination(pxp, ARB_SESSION); if (ret) - goto out; + return ret; ret = pxp_wait_for_session_state(pxp, ARB_SESSION, false); if (ret) - goto out; + return ret; /* Trigger full HW cleanup */ xe_mmio_write32(>->mmio, KCR_GLOBAL_TERMINATE, 1); /* now we can tell the GSC to clean up its own state */ - ret = xe_pxp_submit_session_invalidation(&pxp->gsc_res, ARB_SESSION); - -out: - xe_force_wake_put(gt_to_fw(gt), fw_ref); - return ret; + return xe_pxp_submit_session_invalidation(&pxp->gsc_res, ARB_SESSION); } static void mark_termination_in_progress(struct xe_pxp *pxp) @@ -326,14 +315,12 @@ static int kcr_pxp_set_status(const struct xe_pxp *pxp, bool enable) { u32 val = enable ? _MASKED_BIT_ENABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES) : _MASKED_BIT_DISABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES); - unsigned int fw_ref; - fw_ref = xe_force_wake_get(gt_to_fw(pxp->gt), XE_FW_GT); - if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT)) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(pxp->gt), XE_FW_GT); + if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FW_GT)) return -EIO; xe_mmio_write32(&pxp->gt->mmio, KCR_INIT, val); - xe_force_wake_put(gt_to_fw(pxp->gt), fw_ref); return 0; } @@ -453,34 +440,28 @@ out: static int __pxp_start_arb_session(struct xe_pxp *pxp) { int ret; - unsigned int fw_ref; - fw_ref = xe_force_wake_get(gt_to_fw(pxp->gt), XE_FW_GT); - if (!xe_force_wake_ref_has_domain(fw_ref, XE_FW_GT)) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(pxp->gt), XE_FW_GT); + if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FW_GT)) return -EIO; - if (pxp_session_is_in_play(pxp, ARB_SESSION)) { - ret = -EEXIST; - goto out_force_wake; - } + if (pxp_session_is_in_play(pxp, ARB_SESSION)) + return -EEXIST; ret = xe_pxp_submit_session_init(&pxp->gsc_res, ARB_SESSION); if (ret) { drm_err(&pxp->xe->drm, "Failed to init PXP arb session: %pe\n", ERR_PTR(ret)); - goto out_force_wake; + return ret; } ret = pxp_wait_for_session_state(pxp, ARB_SESSION, true); if (ret) { drm_err(&pxp->xe->drm, "PXP ARB session failed to go in play%pe\n", ERR_PTR(ret)); - goto out_force_wake; + return ret; } drm_dbg(&pxp->xe->drm, "PXP ARB session is active\n"); - -out_force_wake: - xe_force_wake_put(gt_to_fw(pxp->gt), fw_ref); - return ret; + return 0; } /** From be675564cca58fd509b3666bbb1b7f61c6cc03f9 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:49 -0800 Subject: [PATCH 0068/1610] drm/xe/gsc: Use scope-based cleanup Use scope-based cleanup for forcewake and runtime PM to eliminate some goto-based error handling and simplify other functions. Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-39-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_gsc.c | 21 ++++++--------------- drivers/gpu/drm/xe/xe_gsc_proxy.c | 17 +++++++---------- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gsc.c b/drivers/gpu/drm/xe/xe_gsc.c index dd69cb834f8e..a3157b0fe791 100644 --- a/drivers/gpu/drm/xe/xe_gsc.c +++ b/drivers/gpu/drm/xe/xe_gsc.c @@ -352,7 +352,6 @@ static void gsc_work(struct work_struct *work) struct xe_gsc *gsc = container_of(work, typeof(*gsc), work); struct xe_gt *gt = gsc_to_gt(gsc); struct xe_device *xe = gt_to_xe(gt); - unsigned int fw_ref; u32 actions; int ret; @@ -361,13 +360,12 @@ static void gsc_work(struct work_struct *work) gsc->work_actions = 0; spin_unlock_irq(&gsc->lock); - xe_pm_runtime_get(xe); - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC); + guard(xe_pm_runtime)(xe); + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GSC); if (actions & GSC_ACTION_ER_COMPLETE) { - ret = gsc_er_complete(gt); - if (ret) - goto out; + if (gsc_er_complete(gt)) + return; } if (actions & GSC_ACTION_FW_LOAD) { @@ -380,10 +378,6 @@ static void gsc_work(struct work_struct *work) if (actions & GSC_ACTION_SW_PROXY) xe_gsc_proxy_request_handler(gsc); - -out: - xe_force_wake_put(gt_to_fw(gt), fw_ref); - xe_pm_runtime_put(xe); } void xe_gsc_hwe_irq_handler(struct xe_hw_engine *hwe, u16 intr_vec) @@ -615,7 +609,6 @@ void xe_gsc_print_info(struct xe_gsc *gsc, struct drm_printer *p) { struct xe_gt *gt = gsc_to_gt(gsc); struct xe_mmio *mmio = >->mmio; - unsigned int fw_ref; xe_uc_fw_print(&gsc->fw, p); @@ -624,8 +617,8 @@ void xe_gsc_print_info(struct xe_gsc *gsc, struct drm_printer *p) if (!xe_uc_fw_is_enabled(&gsc->fw)) return; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GSC); + if (!fw_ref.domains) return; drm_printf(p, "\nHECI1 FWSTS: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", @@ -635,6 +628,4 @@ void xe_gsc_print_info(struct xe_gsc *gsc, struct drm_printer *p) xe_mmio_read32(mmio, HECI_FWSTS4(MTL_GSC_HECI1_BASE)), xe_mmio_read32(mmio, HECI_FWSTS5(MTL_GSC_HECI1_BASE)), xe_mmio_read32(mmio, HECI_FWSTS6(MTL_GSC_HECI1_BASE))); - - xe_force_wake_put(gt_to_fw(gt), fw_ref); } diff --git a/drivers/gpu/drm/xe/xe_gsc_proxy.c b/drivers/gpu/drm/xe/xe_gsc_proxy.c index 464282a89eef..e7573a0c5e5d 100644 --- a/drivers/gpu/drm/xe/xe_gsc_proxy.c +++ b/drivers/gpu/drm/xe/xe_gsc_proxy.c @@ -440,22 +440,19 @@ static void xe_gsc_proxy_remove(void *arg) struct xe_gsc *gsc = arg; struct xe_gt *gt = gsc_to_gt(gsc); struct xe_device *xe = gt_to_xe(gt); - unsigned int fw_ref = 0; if (!gsc->proxy.component_added) return; /* disable HECI2 IRQs */ - xe_pm_runtime_get(xe); - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC); - if (!fw_ref) - xe_gt_err(gt, "failed to get forcewake to disable GSC interrupts\n"); + scoped_guard(xe_pm_runtime, xe) { + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GSC); + if (!fw_ref.domains) + xe_gt_err(gt, "failed to get forcewake to disable GSC interrupts\n"); - /* try do disable irq even if forcewake failed */ - gsc_proxy_irq_toggle(gsc, false); - - xe_force_wake_put(gt_to_fw(gt), fw_ref); - xe_pm_runtime_put(xe); + /* try do disable irq even if forcewake failed */ + gsc_proxy_irq_toggle(gsc, false); + } xe_gsc_wait_for_worker_completion(gsc); From 89bba8fe925a9dc30b8fdcdd2316eb5b322c296d Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:50 -0800 Subject: [PATCH 0069/1610] drm/xe/device: Use scope-based cleanup Convert device code to use scope-based forcewake and runtime PM. Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-40-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_device.c | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 9f2f19dc1fd3..92f883dd8877 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -166,7 +166,7 @@ static void xe_file_close(struct drm_device *dev, struct drm_file *file) struct xe_exec_queue *q; unsigned long idx; - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); /* * No need for exec_queue.lock here as there is no contention for it @@ -184,8 +184,6 @@ static void xe_file_close(struct drm_device *dev, struct drm_file *file) xe_vm_close_and_put(vm); xe_file_put(xef); - - xe_pm_runtime_put(xe); } static const struct drm_ioctl_desc xe_ioctls[] = { @@ -220,10 +218,10 @@ static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (xe_device_wedged(xe)) return -ECANCELED; - ret = xe_pm_runtime_get_ioctl(xe); + ACQUIRE(xe_pm_runtime_ioctl, pm)(xe); + ret = ACQUIRE_ERR(xe_pm_runtime_ioctl, &pm); if (ret >= 0) ret = drm_ioctl(file, cmd, arg); - xe_pm_runtime_put(xe); return ret; } @@ -238,10 +236,10 @@ static long xe_drm_compat_ioctl(struct file *file, unsigned int cmd, unsigned lo if (xe_device_wedged(xe)) return -ECANCELED; - ret = xe_pm_runtime_get_ioctl(xe); + ACQUIRE(xe_pm_runtime_ioctl, pm)(xe); + ret = ACQUIRE_ERR(xe_pm_runtime_ioctl, &pm); if (ret >= 0) ret = drm_compat_ioctl(file, cmd, arg); - xe_pm_runtime_put(xe); return ret; } @@ -775,7 +773,6 @@ ALLOW_ERROR_INJECTION(xe_device_probe_early, ERRNO); /* See xe_pci_probe() */ static int probe_has_flat_ccs(struct xe_device *xe) { struct xe_gt *gt; - unsigned int fw_ref; u32 reg; /* Always enabled/disabled, no runtime check to do */ @@ -786,8 +783,8 @@ static int probe_has_flat_ccs(struct xe_device *xe) if (!gt) return 0; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return -ETIMEDOUT; reg = xe_gt_mcr_unicast_read_any(gt, XE2_FLAT_CCS_BASE_RANGE_LOWER); @@ -797,8 +794,6 @@ static int probe_has_flat_ccs(struct xe_device *xe) drm_dbg(&xe->drm, "Flat CCS has been disabled in bios, May lead to performance impact"); - xe_force_wake_put(gt_to_fw(gt), fw_ref); - return 0; } @@ -1034,7 +1029,6 @@ void xe_device_wmb(struct xe_device *xe) */ static void tdf_request_sync(struct xe_device *xe) { - unsigned int fw_ref; struct xe_gt *gt; u8 id; @@ -1042,8 +1036,8 @@ static void tdf_request_sync(struct xe_device *xe) if (xe_gt_is_media_type(gt)) continue; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return; xe_mmio_write32(>->mmio, XE2_TDF_CTRL, TRANSIENT_FLUSH_REQUEST); @@ -1058,15 +1052,12 @@ static void tdf_request_sync(struct xe_device *xe) if (xe_mmio_wait32(>->mmio, XE2_TDF_CTRL, TRANSIENT_FLUSH_REQUEST, 0, 150, NULL, false)) xe_gt_err_once(gt, "TD flush timeout\n"); - - xe_force_wake_put(gt_to_fw(gt), fw_ref); } } void xe_device_l2_flush(struct xe_device *xe) { struct xe_gt *gt; - unsigned int fw_ref; gt = xe_root_mmio_gt(xe); if (!gt) @@ -1075,8 +1066,8 @@ void xe_device_l2_flush(struct xe_device *xe) if (!XE_GT_WA(gt, 16023588340)) return; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return; spin_lock(>->global_invl_lock); @@ -1086,8 +1077,6 @@ void xe_device_l2_flush(struct xe_device *xe) xe_gt_err_once(gt, "Global invalidation timeout\n"); spin_unlock(>->global_invl_lock); - - xe_force_wake_put(gt_to_fw(gt), fw_ref); } /** From 7fc616a309e854f75bcc46e82b948065886ebddf Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:51 -0800 Subject: [PATCH 0070/1610] drm/xe/devcoredump: Use scope-based cleanup Use scope-based cleanup for forcewake and runtime PM in the devcoredump code. This eliminates some goto-based error handling and slightly simplifies other functions. v2: - Move the forcewake acquisition slightly higher in devcoredump_snapshot() so that we maintain an easy-to-understand LIFO cleanup order. (Gustavo) Cc: Gustavo Sousa Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-41-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_devcoredump.c | 30 ++++++++++++----------------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c index 203e3038cc81..bf347714b5e0 100644 --- a/drivers/gpu/drm/xe/xe_devcoredump.c +++ b/drivers/gpu/drm/xe/xe_devcoredump.c @@ -276,7 +276,6 @@ static void xe_devcoredump_deferred_snap_work(struct work_struct *work) struct xe_devcoredump_snapshot *ss = container_of(work, typeof(*ss), work); struct xe_devcoredump *coredump = container_of(ss, typeof(*coredump), snapshot); struct xe_device *xe = coredump_to_xe(coredump); - unsigned int fw_ref; /* * NB: Despite passing a GFP_ flags parameter here, more allocations are done @@ -287,15 +286,15 @@ static void xe_devcoredump_deferred_snap_work(struct work_struct *work) xe_devcoredump_read, xe_devcoredump_free, XE_COREDUMP_TIMEOUT_JIFFIES); - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); /* keep going if fw fails as we still want to save the memory and SW data */ - fw_ref = xe_force_wake_get(gt_to_fw(ss->gt), XE_FORCEWAKE_ALL); - if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) - xe_gt_info(ss->gt, "failed to get forcewake for coredump capture\n"); - xe_vm_snapshot_capture_delayed(ss->vm); - xe_guc_exec_queue_snapshot_capture_delayed(ss->ge); - xe_force_wake_put(gt_to_fw(ss->gt), fw_ref); + xe_with_force_wake(fw_ref, gt_to_fw(ss->gt), XE_FORCEWAKE_ALL) { + if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)) + xe_gt_info(ss->gt, "failed to get forcewake for coredump capture\n"); + xe_vm_snapshot_capture_delayed(ss->vm); + xe_guc_exec_queue_snapshot_capture_delayed(ss->ge); + } ss->read.chunk_position = 0; @@ -306,7 +305,7 @@ static void xe_devcoredump_deferred_snap_work(struct work_struct *work) ss->read.buffer = kvmalloc(XE_DEVCOREDUMP_CHUNK_MAX, GFP_USER); if (!ss->read.buffer) - goto put_pm; + return; __xe_devcoredump_read(ss->read.buffer, XE_DEVCOREDUMP_CHUNK_MAX, @@ -314,15 +313,12 @@ static void xe_devcoredump_deferred_snap_work(struct work_struct *work) } else { ss->read.buffer = kvmalloc(ss->read.size, GFP_USER); if (!ss->read.buffer) - goto put_pm; + return; __xe_devcoredump_read(ss->read.buffer, ss->read.size, 0, coredump); xe_devcoredump_snapshot_free(ss); } - -put_pm: - xe_pm_runtime_put(xe); } static void devcoredump_snapshot(struct xe_devcoredump *coredump, @@ -332,7 +328,6 @@ static void devcoredump_snapshot(struct xe_devcoredump *coredump, struct xe_devcoredump_snapshot *ss = &coredump->snapshot; struct xe_guc *guc = exec_queue_to_guc(q); const char *process_name = "no process"; - unsigned int fw_ref; bool cookie; ss->snapshot_time = ktime_get_real(); @@ -348,10 +343,10 @@ static void devcoredump_snapshot(struct xe_devcoredump *coredump, ss->gt = q->gt; INIT_WORK(&ss->work, xe_devcoredump_deferred_snap_work); - cookie = dma_fence_begin_signalling(); - /* keep going if fw fails as we still want to save the memory and SW data */ - fw_ref = xe_force_wake_get(gt_to_fw(q->gt), XE_FORCEWAKE_ALL); + CLASS(xe_force_wake, fw_ref)(gt_to_fw(q->gt), XE_FORCEWAKE_ALL); + + cookie = dma_fence_begin_signalling(); ss->guc.log = xe_guc_log_snapshot_capture(&guc->log, true); ss->guc.ct = xe_guc_ct_snapshot_capture(&guc->ct); @@ -364,7 +359,6 @@ static void devcoredump_snapshot(struct xe_devcoredump *coredump, queue_work(system_unbound_wq, &ss->work); - xe_force_wake_put(gt_to_fw(q->gt), fw_ref); dma_fence_end_signalling(cookie); } From b11f88699b13d7b6e314b9d19107aebdc79570f0 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:52 -0800 Subject: [PATCH 0071/1610] drm/xe/display: Use scoped-cleanup Eliminate some goto-based cleanup by utilizing scoped cleanup helpers. v2: - Eliminate unnecessary 'ret' variable in intel_hdcp_gsc_check_status() (Gustavo) Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-42-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/display/xe_fb_pin.c | 23 +++++++----------- drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 31 +++++++----------------- 2 files changed, 18 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index 1fd4a815e784..6a935a75f2a4 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -210,10 +210,11 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, /* TODO: Consider sharing framebuffer mapping? * embed i915_vma inside intel_framebuffer */ - xe_pm_runtime_get_noresume(xe); - ret = mutex_lock_interruptible(&ggtt->lock); + guard(xe_pm_runtime_noresume)(xe); + ACQUIRE(mutex_intr, lock)(&ggtt->lock); + ret = ACQUIRE_ERR(mutex_intr, &lock); if (ret) - goto out; + return ret; align = XE_PAGE_SIZE; if (xe_bo_is_vram(bo) && ggtt->flags & XE_GGTT_FLAGS_64K) @@ -223,15 +224,13 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, vma->node = bo->ggtt_node[tile0->id]; } else if (view->type == I915_GTT_VIEW_NORMAL) { vma->node = xe_ggtt_node_init(ggtt); - if (IS_ERR(vma->node)) { - ret = PTR_ERR(vma->node); - goto out_unlock; - } + if (IS_ERR(vma->node)) + return PTR_ERR(vma->node); ret = xe_ggtt_node_insert_locked(vma->node, xe_bo_size(bo), align, 0); if (ret) { xe_ggtt_node_fini(vma->node); - goto out_unlock; + return ret; } xe_ggtt_map_bo(ggtt, vma->node, bo, xe->pat.idx[XE_CACHE_NONE]); @@ -245,13 +244,13 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, vma->node = xe_ggtt_node_init(ggtt); if (IS_ERR(vma->node)) { ret = PTR_ERR(vma->node); - goto out_unlock; + return ret; } ret = xe_ggtt_node_insert_locked(vma->node, size, align, 0); if (ret) { xe_ggtt_node_fini(vma->node); - goto out_unlock; + return ret; } ggtt_ofs = vma->node->base.start; @@ -265,10 +264,6 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, rot_info->plane[i].dst_stride); } -out_unlock: - mutex_unlock(&ggtt->lock); -out: - xe_pm_runtime_put(xe); return ret; } diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c index 4ae847b628e2..71d21fde1736 100644 --- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c @@ -36,8 +36,6 @@ bool intel_hdcp_gsc_check_status(struct drm_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; - bool ret = true; - unsigned int fw_ref; if (!gsc || !xe_uc_fw_is_enabled(&gsc->fw)) { drm_dbg_kms(&xe->drm, @@ -45,22 +43,15 @@ bool intel_hdcp_gsc_check_status(struct drm_device *drm) return false; } - xe_pm_runtime_get(xe); - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC); - if (!fw_ref) { + guard(xe_pm_runtime)(xe); + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GSC); + if (!fw_ref.domains) { drm_dbg_kms(&xe->drm, "failed to get forcewake to check proxy status\n"); - ret = false; - goto out; + return false; } - if (!xe_gsc_proxy_init_done(gsc)) - ret = false; - - xe_force_wake_put(gt_to_fw(gt), fw_ref); -out: - xe_pm_runtime_put(xe); - return ret; + return xe_gsc_proxy_init_done(gsc); } /*This function helps allocate memory for the command that we will send to gsc cs */ @@ -166,17 +157,15 @@ ssize_t intel_hdcp_gsc_msg_send(struct intel_hdcp_gsc_context *gsc_context, u32 addr_out_off, addr_in_wr_off = 0; int ret, tries = 0; - if (msg_in_len > max_msg_size || msg_out_len > max_msg_size) { - ret = -ENOSPC; - goto out; - } + if (msg_in_len > max_msg_size || msg_out_len > max_msg_size) + return -ENOSPC; msg_size_in = msg_in_len + HDCP_GSC_HEADER_SIZE; msg_size_out = msg_out_len + HDCP_GSC_HEADER_SIZE; addr_out_off = PAGE_SIZE; host_session_id = xe_gsc_create_host_session_id(); - xe_pm_runtime_get_noresume(xe); + guard(xe_pm_runtime_noresume)(xe); addr_in_wr_off = xe_gsc_emit_header(xe, &gsc_context->hdcp_bo->vmap, addr_in_wr_off, HECI_MEADDRESS_HDCP, host_session_id, msg_in_len); @@ -201,13 +190,11 @@ ssize_t intel_hdcp_gsc_msg_send(struct intel_hdcp_gsc_context *gsc_context, } while (++tries < 20); if (ret) - goto out; + return ret; xe_map_memcpy_from(xe, msg_out, &gsc_context->hdcp_bo->vmap, addr_out_off + HDCP_GSC_HEADER_SIZE, msg_out_len); -out: - xe_pm_runtime_put(xe); return ret; } From 1fe7ea3287ba35b92db7f8fecf773a6bc9273f51 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:53 -0800 Subject: [PATCH 0072/1610] drm/xe: Return forcewake reference type from force_wake_get_any_engine() Adjust the signature of force_wake_get_any_engine() such that it returns a 'struct xe_force_wake_ref' rather than a boolean success/failure. Failure cases are now recognized by inspecting the hardware engine returned by reference; a NULL hwe indicates that no engine's forcewake could be obtained. These changes will make it cleaner and easier to incorporate scope-based cleanup in force_wake_get_any_engine()'s caller in a future patch. Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-43-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_drm_client.c | 38 +++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_drm_client.c b/drivers/gpu/drm/xe/xe_drm_client.c index f931ff9b1ec0..78551832723b 100644 --- a/drivers/gpu/drm/xe/xe_drm_client.c +++ b/drivers/gpu/drm/xe/xe_drm_client.c @@ -285,32 +285,31 @@ static struct xe_hw_engine *any_engine(struct xe_device *xe) return NULL; } -static bool force_wake_get_any_engine(struct xe_device *xe, - struct xe_hw_engine **phwe, - unsigned int *pfw_ref) +/* + * Pick any engine and grab its forcewake. On error phwe will be NULL and + * the returned forcewake reference will be invalid. Callers should check + * phwe against NULL. + */ +static struct xe_force_wake_ref force_wake_get_any_engine(struct xe_device *xe, + struct xe_hw_engine **phwe) { enum xe_force_wake_domains domain; - unsigned int fw_ref; + struct xe_force_wake_ref fw_ref = {}; struct xe_hw_engine *hwe; - struct xe_force_wake *fw; + + *phwe = NULL; hwe = any_engine(xe); if (!hwe) - return false; + return fw_ref; /* will be invalid */ domain = xe_hw_engine_to_fw_domain(hwe); - fw = gt_to_fw(hwe->gt); - fw_ref = xe_force_wake_get(fw, domain); - if (!xe_force_wake_ref_has_domain(fw_ref, domain)) { - xe_force_wake_put(fw, fw_ref); - return false; - } + fw_ref = xe_force_wake_constructor(gt_to_fw(hwe->gt), domain); + if (xe_force_wake_ref_has_domain(fw_ref.domains, domain)) + *phwe = hwe; /* valid forcewake */ - *phwe = hwe; - *pfw_ref = fw_ref; - - return true; + return fw_ref; } static void show_run_ticks(struct drm_printer *p, struct drm_file *file) @@ -322,7 +321,7 @@ static void show_run_ticks(struct drm_printer *p, struct drm_file *file) struct xe_hw_engine *hwe; struct xe_exec_queue *q; u64 gpu_timestamp; - unsigned int fw_ref; + struct xe_force_wake_ref fw_ref; /* * RING_TIMESTAMP registers are inaccessible in VF mode. @@ -340,7 +339,8 @@ static void show_run_ticks(struct drm_printer *p, struct drm_file *file) !atomic_read(&xef->exec_queue.pending_removal)); xe_pm_runtime_get(xe); - if (!force_wake_get_any_engine(xe, &hwe, &fw_ref)) { + fw_ref = force_wake_get_any_engine(xe, &hwe); + if (!hwe) { xe_pm_runtime_put(xe); return; } @@ -360,7 +360,7 @@ static void show_run_ticks(struct drm_printer *p, struct drm_file *file) gpu_timestamp = xe_hw_engine_read_timestamp(hwe); - xe_force_wake_put(gt_to_fw(hwe->gt), fw_ref); + xe_force_wake_put(gt_to_fw(hwe->gt), fw_ref.domains); xe_pm_runtime_put(xe); for (class = 0; class < XE_ENGINE_CLASS_MAX; class++) { From 062a6b83d56066f86c1bed170265ecfa98b83175 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:54 -0800 Subject: [PATCH 0073/1610] drm/xe/drm_client: Use scope-based cleanup Use scope-based cleanup for forcewake and runtime PM. v2: - Use xe_force_wake_release_only rather than a custom one-off class for "any engine" forcewake. (Gustavo) Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-44-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_drm_client.c | 37 +++++++++++++----------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_drm_client.c b/drivers/gpu/drm/xe/xe_drm_client.c index 78551832723b..2787bbb36141 100644 --- a/drivers/gpu/drm/xe/xe_drm_client.c +++ b/drivers/gpu/drm/xe/xe_drm_client.c @@ -321,7 +321,6 @@ static void show_run_ticks(struct drm_printer *p, struct drm_file *file) struct xe_hw_engine *hwe; struct xe_exec_queue *q; u64 gpu_timestamp; - struct xe_force_wake_ref fw_ref; /* * RING_TIMESTAMP registers are inaccessible in VF mode. @@ -338,30 +337,26 @@ static void show_run_ticks(struct drm_printer *p, struct drm_file *file) wait_var_event(&xef->exec_queue.pending_removal, !atomic_read(&xef->exec_queue.pending_removal)); - xe_pm_runtime_get(xe); - fw_ref = force_wake_get_any_engine(xe, &hwe); - if (!hwe) { - xe_pm_runtime_put(xe); - return; - } + scoped_guard(xe_pm_runtime, xe) { + CLASS(xe_force_wake_release_only, fw_ref)(force_wake_get_any_engine(xe, &hwe)); + if (!hwe) + return; - /* Accumulate all the exec queues from this client */ - mutex_lock(&xef->exec_queue.lock); - xa_for_each(&xef->exec_queue.xa, i, q) { - xe_exec_queue_get(q); + /* Accumulate all the exec queues from this client */ + mutex_lock(&xef->exec_queue.lock); + xa_for_each(&xef->exec_queue.xa, i, q) { + xe_exec_queue_get(q); + mutex_unlock(&xef->exec_queue.lock); + + xe_exec_queue_update_run_ticks(q); + + mutex_lock(&xef->exec_queue.lock); + xe_exec_queue_put(q); + } mutex_unlock(&xef->exec_queue.lock); - xe_exec_queue_update_run_ticks(q); - - mutex_lock(&xef->exec_queue.lock); - xe_exec_queue_put(q); + gpu_timestamp = xe_hw_engine_read_timestamp(hwe); } - mutex_unlock(&xef->exec_queue.lock); - - gpu_timestamp = xe_hw_engine_read_timestamp(hwe); - - xe_force_wake_put(gt_to_fw(hwe->gt), fw_ref.domains); - xe_pm_runtime_put(xe); for (class = 0; class < XE_ENGINE_CLASS_MAX; class++) { const char *class_name; From bedad003e8e76ef37d069816ae418e7917c5f4d8 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:55 -0800 Subject: [PATCH 0074/1610] drm/xe/gt_debugfs: Use scope-based cleanup Use scope-based cleanup for forcewake and runtime PM to simplify the debugfs code slightly. Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-45-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_gt_debugfs.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt_debugfs.c b/drivers/gpu/drm/xe/xe_gt_debugfs.c index e4fd632f43cf..7c3de6539044 100644 --- a/drivers/gpu/drm/xe/xe_gt_debugfs.c +++ b/drivers/gpu/drm/xe/xe_gt_debugfs.c @@ -105,35 +105,24 @@ int xe_gt_debugfs_show_with_rpm(struct seq_file *m, void *data) struct drm_info_node *node = m->private; struct xe_gt *gt = node_to_gt(node); struct xe_device *xe = gt_to_xe(gt); - int ret; - xe_pm_runtime_get(xe); - ret = xe_gt_debugfs_simple_show(m, data); - xe_pm_runtime_put(xe); - - return ret; + guard(xe_pm_runtime)(xe); + return xe_gt_debugfs_simple_show(m, data); } static int hw_engines(struct xe_gt *gt, struct drm_printer *p) { struct xe_hw_engine *hwe; enum xe_hw_engine_id id; - unsigned int fw_ref; - int ret = 0; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) { - ret = -ETIMEDOUT; - goto fw_put; - } + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL); + if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)) + return -ETIMEDOUT; for_each_hw_engine(hwe, gt, id) xe_hw_engine_print(hwe, p); -fw_put: - xe_force_wake_put(gt_to_fw(gt), fw_ref); - - return ret; + return 0; } static int steering(struct xe_gt *gt, struct drm_printer *p) @@ -269,9 +258,8 @@ static void force_reset(struct xe_gt *gt) { struct xe_device *xe = gt_to_xe(gt); - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); xe_gt_reset_async(gt); - xe_pm_runtime_put(xe); } static ssize_t force_reset_write(struct file *file, @@ -297,9 +285,8 @@ static void force_reset_sync(struct xe_gt *gt) { struct xe_device *xe = gt_to_xe(gt); - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); xe_gt_reset(gt); - xe_pm_runtime_put(xe); } static ssize_t force_reset_sync_write(struct file *file, From 175b9aaba3e2b32935204b46ff1ea6356b775801 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:56 -0800 Subject: [PATCH 0075/1610] drm/xe/huc: Use scope-based forcewake Use scope-based forcewake in the HuC code for a small simplification and consistency with other parts of the driver. Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-46-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_huc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_huc.c b/drivers/gpu/drm/xe/xe_huc.c index 0a70c8924582..4212162913af 100644 --- a/drivers/gpu/drm/xe/xe_huc.c +++ b/drivers/gpu/drm/xe/xe_huc.c @@ -300,19 +300,16 @@ void xe_huc_sanitize(struct xe_huc *huc) void xe_huc_print_info(struct xe_huc *huc, struct drm_printer *p) { struct xe_gt *gt = huc_to_gt(huc); - unsigned int fw_ref; xe_uc_fw_print(&huc->fw, p); if (!xe_uc_fw_is_enabled(&huc->fw)) return; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return; drm_printf(p, "\nHuC status: 0x%08x\n", xe_mmio_read32(>->mmio, HUC_KERNEL_LOAD_INFO)); - - xe_force_wake_put(gt_to_fw(gt), fw_ref); } From 667fc27e81bc4bd0aae008b6c3f16df9e707707e Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:57 -0800 Subject: [PATCH 0076/1610] drm/xe/query: Use scope-based forcewake Use scope-based forcewake handling for consistency with other parts of the driver. Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-47-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_query.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_query.c b/drivers/gpu/drm/xe/xe_query.c index 1c0915e2cc16..a7bf1fd6dd6a 100644 --- a/drivers/gpu/drm/xe/xe_query.c +++ b/drivers/gpu/drm/xe/xe_query.c @@ -122,7 +122,6 @@ query_engine_cycles(struct xe_device *xe, __ktime_func_t cpu_clock; struct xe_hw_engine *hwe; struct xe_gt *gt; - unsigned int fw_ref; if (IS_SRIOV_VF(xe)) return -EOPNOTSUPP; @@ -158,17 +157,14 @@ query_engine_cycles(struct xe_device *xe, if (!hwe) return -EINVAL; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) { - xe_force_wake_put(gt_to_fw(gt), fw_ref); - return -EIO; + xe_with_force_wake(fw_ref, gt_to_fw(gt), XE_FORCEWAKE_ALL) { + if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)) + return -EIO; + + hwe_read_timestamp(hwe, &resp.engine_cycles, &resp.cpu_timestamp, + &resp.cpu_delta, cpu_clock); } - hwe_read_timestamp(hwe, &resp.engine_cycles, &resp.cpu_timestamp, - &resp.cpu_delta, cpu_clock); - - xe_force_wake_put(gt_to_fw(gt), fw_ref); - if (GRAPHICS_VER(xe) >= 20) resp.width = 64; else From f875dead3ec75ba37edf986603a69c89e4a771e6 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:58 -0800 Subject: [PATCH 0077/1610] drm/xe/reg_sr: Use scope-based forcewake Use scope-based forcewake to slightly simplify the reg_sr code. Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-48-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_reg_sr.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_reg_sr.c b/drivers/gpu/drm/xe/xe_reg_sr.c index fc8447a838c4..1a465385f909 100644 --- a/drivers/gpu/drm/xe/xe_reg_sr.c +++ b/drivers/gpu/drm/xe/xe_reg_sr.c @@ -168,7 +168,6 @@ void xe_reg_sr_apply_mmio(struct xe_reg_sr *sr, struct xe_gt *gt) { struct xe_reg_sr_entry *entry; unsigned long reg; - unsigned int fw_ref; if (xa_empty(&sr->xa)) return; @@ -178,20 +177,14 @@ void xe_reg_sr_apply_mmio(struct xe_reg_sr *sr, struct xe_gt *gt) xe_gt_dbg(gt, "Applying %s save-restore MMIOs\n", sr->name); - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); - if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) - goto err_force_wake; + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL); + if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)) { + xe_gt_err(gt, "Failed to apply, err=-ETIMEDOUT\n"); + return; + } xa_for_each(&sr->xa, reg, entry) apply_one_mmio(gt, entry); - - xe_force_wake_put(gt_to_fw(gt), fw_ref); - - return; - -err_force_wake: - xe_force_wake_put(gt_to_fw(gt), fw_ref); - xe_gt_err(gt, "Failed to apply, err=-ETIMEDOUT\n"); } /** From 60a4661d12ca58c794337d09d26f3f57e235cd2d Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:43:59 -0800 Subject: [PATCH 0078/1610] drm/xe/vram: Use scope-based forcewake Switch VRAM code to use scope-based forcewake for consistency with other parts of the driver. Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-49-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_vram.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_vram.c b/drivers/gpu/drm/xe/xe_vram.c index 0e10da790cc5..0a645e76e5fa 100644 --- a/drivers/gpu/drm/xe/xe_vram.c +++ b/drivers/gpu/drm/xe/xe_vram.c @@ -186,12 +186,11 @@ static int determine_lmem_bar_size(struct xe_device *xe, struct xe_vram_region * static int get_flat_ccs_offset(struct xe_gt *gt, u64 tile_size, u64 *poffset) { struct xe_device *xe = gt_to_xe(gt); - unsigned int fw_ref; u64 offset; u32 reg; - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); - if (!fw_ref) + CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); + if (!fw_ref.domains) return -ETIMEDOUT; if (GRAPHICS_VER(xe) >= 20) { @@ -223,7 +222,6 @@ static int get_flat_ccs_offset(struct xe_gt *gt, u64 tile_size, u64 *poffset) offset = (u64)REG_FIELD_GET(XEHP_FLAT_CCS_PTR, reg) * SZ_64K; } - xe_force_wake_put(gt_to_fw(gt), fw_ref); *poffset = offset; return 0; From faa4b73bf75003ad89ed4d1afd3e9e59a48a63fd Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:44:00 -0800 Subject: [PATCH 0079/1610] drm/xe/bo: Use scope-based runtime PM Use scope-based runtime power management in the BO code for consistency with other parts of the driver. v2: - Drop unnecessary 'ret' variable. (Gustavo) Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-50-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_bo.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index bbda20d7c089..465cf9fc7ce9 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -2032,13 +2032,9 @@ static int xe_bo_vm_access(struct vm_area_struct *vma, unsigned long addr, struct ttm_buffer_object *ttm_bo = vma->vm_private_data; struct xe_bo *bo = ttm_to_xe_bo(ttm_bo); struct xe_device *xe = xe_bo_device(bo); - int ret; - xe_pm_runtime_get(xe); - ret = ttm_bo_vm_access(vma, addr, buf, len, write); - xe_pm_runtime_put(xe); - - return ret; + guard(xe_pm_runtime)(xe); + return ttm_bo_vm_access(vma, addr, buf, len, write); } /** From 8a579f4b2476fd1df07e2bca9fedc82a39a56a65 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:44:01 -0800 Subject: [PATCH 0080/1610] drm/xe/ggtt: Use scope-based runtime pm Switch the GGTT code to scope-based runtime PM for consistency with other parts of the driver. Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-51-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_ggtt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index ef481b334af4..48ab8b43fcd0 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -396,9 +396,8 @@ static void ggtt_node_remove_work_func(struct work_struct *work) delayed_removal_work); struct xe_device *xe = tile_to_xe(node->ggtt->tile); - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); ggtt_node_remove(node); - xe_pm_runtime_put(xe); } /** From 008f3fcf31b7a7a6b13b774b76871679805c2661 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:44:02 -0800 Subject: [PATCH 0081/1610] drm/xe/hwmon: Use scope-based runtime PM Use scope-based runtime power management in the hwmon code for consistency with other parts of the driver. v2: - Drop unnecessary 'ret' variables. (Gustavo) Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-52-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_hwmon.c | 52 ++++++++++------------------------- 1 file changed, 14 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index 97879daeefc1..ff2aea52ef75 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -502,7 +502,7 @@ xe_hwmon_power_max_interval_show(struct device *dev, struct device_attribute *at int ret = 0; - xe_pm_runtime_get(hwmon->xe); + guard(xe_pm_runtime)(hwmon->xe); mutex_lock(&hwmon->hwmon_lock); @@ -521,8 +521,6 @@ xe_hwmon_power_max_interval_show(struct device *dev, struct device_attribute *at mutex_unlock(&hwmon->hwmon_lock); - xe_pm_runtime_put(hwmon->xe); - x = REG_FIELD_GET(PWR_LIM_TIME_X, reg_val); y = REG_FIELD_GET(PWR_LIM_TIME_Y, reg_val); @@ -604,7 +602,7 @@ xe_hwmon_power_max_interval_store(struct device *dev, struct device_attribute *a rxy = REG_FIELD_PREP(PWR_LIM_TIME_X, x) | REG_FIELD_PREP(PWR_LIM_TIME_Y, y); - xe_pm_runtime_get(hwmon->xe); + guard(xe_pm_runtime)(hwmon->xe); mutex_lock(&hwmon->hwmon_lock); @@ -616,8 +614,6 @@ xe_hwmon_power_max_interval_store(struct device *dev, struct device_attribute *a mutex_unlock(&hwmon->hwmon_lock); - xe_pm_runtime_put(hwmon->xe); - return count; } @@ -1124,37 +1120,25 @@ xe_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long *val) { struct xe_hwmon *hwmon = dev_get_drvdata(dev); - int ret; - xe_pm_runtime_get(hwmon->xe); + guard(xe_pm_runtime)(hwmon->xe); switch (type) { case hwmon_temp: - ret = xe_hwmon_temp_read(hwmon, attr, channel, val); - break; + return xe_hwmon_temp_read(hwmon, attr, channel, val); case hwmon_power: - ret = xe_hwmon_power_read(hwmon, attr, channel, val); - break; + return xe_hwmon_power_read(hwmon, attr, channel, val); case hwmon_curr: - ret = xe_hwmon_curr_read(hwmon, attr, channel, val); - break; + return xe_hwmon_curr_read(hwmon, attr, channel, val); case hwmon_in: - ret = xe_hwmon_in_read(hwmon, attr, channel, val); - break; + return xe_hwmon_in_read(hwmon, attr, channel, val); case hwmon_energy: - ret = xe_hwmon_energy_read(hwmon, attr, channel, val); - break; + return xe_hwmon_energy_read(hwmon, attr, channel, val); case hwmon_fan: - ret = xe_hwmon_fan_read(hwmon, attr, channel, val); - break; + return xe_hwmon_fan_read(hwmon, attr, channel, val); default: - ret = -EOPNOTSUPP; - break; + return -EOPNOTSUPP; } - - xe_pm_runtime_put(hwmon->xe); - - return ret; } static int @@ -1162,25 +1146,17 @@ xe_hwmon_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long val) { struct xe_hwmon *hwmon = dev_get_drvdata(dev); - int ret; - xe_pm_runtime_get(hwmon->xe); + guard(xe_pm_runtime)(hwmon->xe); switch (type) { case hwmon_power: - ret = xe_hwmon_power_write(hwmon, attr, channel, val); - break; + return xe_hwmon_power_write(hwmon, attr, channel, val); case hwmon_curr: - ret = xe_hwmon_curr_write(hwmon, attr, channel, val); - break; + return xe_hwmon_curr_write(hwmon, attr, channel, val); default: - ret = -EOPNOTSUPP; - break; + return -EOPNOTSUPP; } - - xe_pm_runtime_put(hwmon->xe); - - return ret; } static int xe_hwmon_read_label(struct device *dev, From fcee6854e6fb9ddff0597296728a4f7fd67bccc9 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:44:03 -0800 Subject: [PATCH 0082/1610] drm/xe/sriov: Use scope-based runtime PM Use scope-based runtime power management in the SRIOV code for consistency with other parts of the driver. v2: - Drop unnecessary 'ret' variables. (Gustavo) Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-53-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_pci_sriov.c | 10 +++------- drivers/gpu/drm/xe/xe_sriov_pf_debugfs.c | 6 ++---- drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c | 16 ++++------------ drivers/gpu/drm/xe/xe_sriov_vf_ccs.c | 5 +---- drivers/gpu/drm/xe/xe_tile_sriov_pf_debugfs.c | 3 +-- 5 files changed, 11 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_pci_sriov.c b/drivers/gpu/drm/xe/xe_pci_sriov.c index 9ff69c4843b0..3fd22034f03e 100644 --- a/drivers/gpu/drm/xe/xe_pci_sriov.c +++ b/drivers/gpu/drm/xe/xe_pci_sriov.c @@ -219,7 +219,6 @@ static int pf_disable_vfs(struct xe_device *xe) int xe_pci_sriov_configure(struct pci_dev *pdev, int num_vfs) { struct xe_device *xe = pdev_to_xe_device(pdev); - int ret; if (!IS_SRIOV_PF(xe)) return -ENODEV; @@ -233,14 +232,11 @@ int xe_pci_sriov_configure(struct pci_dev *pdev, int num_vfs) if (num_vfs && pci_num_vf(pdev)) return -EBUSY; - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); if (num_vfs > 0) - ret = pf_enable_vfs(xe, num_vfs); + return pf_enable_vfs(xe, num_vfs); else - ret = pf_disable_vfs(xe); - xe_pm_runtime_put(xe); - - return ret; + return pf_disable_vfs(xe); } /** diff --git a/drivers/gpu/drm/xe/xe_sriov_pf_debugfs.c b/drivers/gpu/drm/xe/xe_sriov_pf_debugfs.c index bad751217e1e..e84bdde9bc80 100644 --- a/drivers/gpu/drm/xe/xe_sriov_pf_debugfs.c +++ b/drivers/gpu/drm/xe/xe_sriov_pf_debugfs.c @@ -70,9 +70,8 @@ static ssize_t from_file_write_to_xe_call(struct file *file, const char __user * if (ret < 0) return ret; if (yes) { - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); ret = call(xe); - xe_pm_runtime_put(xe); } if (ret < 0) return ret; @@ -209,9 +208,8 @@ static ssize_t from_file_write_to_vf_call(struct file *file, const char __user * if (ret < 0) return ret; if (yes) { - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); ret = call(xe, vfid); - xe_pm_runtime_put(xe); } if (ret < 0) return ret; diff --git a/drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c b/drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c index c0b767ac735c..3d140506ba36 100644 --- a/drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c +++ b/drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c @@ -389,16 +389,12 @@ static ssize_t xe_sriov_dev_attr_store(struct kobject *kobj, struct attribute *a struct xe_sriov_dev_attr *vattr = to_xe_sriov_dev_attr(attr); struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); struct xe_device *xe = vkobj->xe; - ssize_t ret; if (!vattr->store) return -EPERM; - xe_pm_runtime_get(xe); - ret = xe_sriov_pf_wait_ready(xe) ?: vattr->store(xe, buf, count); - xe_pm_runtime_put(xe); - - return ret; + guard(xe_pm_runtime)(xe); + return xe_sriov_pf_wait_ready(xe) ?: vattr->store(xe, buf, count); } static ssize_t xe_sriov_vf_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) @@ -423,18 +419,14 @@ static ssize_t xe_sriov_vf_attr_store(struct kobject *kobj, struct attribute *at struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); struct xe_device *xe = vkobj->xe; unsigned int vfid = vkobj->vfid; - ssize_t ret; xe_sriov_pf_assert_vfid(xe, vfid); if (!vattr->store) return -EPERM; - xe_pm_runtime_get(xe); - ret = xe_sriov_pf_wait_ready(xe) ?: vattr->store(xe, vfid, buf, count); - xe_pm_runtime_get(xe); - - return ret; + guard(xe_pm_runtime)(xe); + return xe_sriov_pf_wait_ready(xe) ?: vattr->store(xe, vfid, buf, count); } static const struct sysfs_ops xe_sriov_dev_sysfs_ops = { diff --git a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c index 33f4238604e1..052a5071e69f 100644 --- a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c +++ b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c @@ -477,8 +477,7 @@ void xe_sriov_vf_ccs_print(struct xe_device *xe, struct drm_printer *p) if (!IS_VF_CCS_READY(xe)) return; - xe_pm_runtime_get(xe); - + guard(xe_pm_runtime)(xe); for_each_ccs_rw_ctx(ctx_id) { bb_pool = xe->sriov.vf.ccs.contexts[ctx_id].mem.ccs_bb_pool; if (!bb_pool) @@ -489,6 +488,4 @@ void xe_sriov_vf_ccs_print(struct xe_device *xe, struct drm_printer *p) drm_suballoc_dump_debug_info(&bb_pool->base, p, xe_sa_manager_gpu_addr(bb_pool)); drm_puts(p, "\n"); } - - xe_pm_runtime_put(xe); } diff --git a/drivers/gpu/drm/xe/xe_tile_sriov_pf_debugfs.c b/drivers/gpu/drm/xe/xe_tile_sriov_pf_debugfs.c index f3f478f14ff5..7f97db2f89bb 100644 --- a/drivers/gpu/drm/xe/xe_tile_sriov_pf_debugfs.c +++ b/drivers/gpu/drm/xe/xe_tile_sriov_pf_debugfs.c @@ -141,12 +141,11 @@ static int NAME##_set(void *data, u64 val) \ if (val > (TYPE)~0ull) \ return -EOVERFLOW; \ \ - xe_pm_runtime_get(xe); \ + guard(xe_pm_runtime)(xe); \ err = xe_sriov_pf_wait_ready(xe) ?: \ xe_gt_sriov_pf_config_set_##CONFIG(gt, vfid, val); \ if (!err) \ xe_sriov_pf_provision_set_custom_mode(xe); \ - xe_pm_runtime_put(xe); \ \ return err; \ } \ From 3a344ddce25eb8b7cf63de8b5c54de10e5bb764f Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:44:04 -0800 Subject: [PATCH 0083/1610] drm/xe/tests: Use scope-based runtime PM Use scope-based handling of runtime PM in the kunit tests for consistency with other parts of the driver. Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-54-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/tests/xe_bo.c | 10 ++-------- drivers/gpu/drm/xe/tests/xe_dma_buf.c | 3 +-- drivers/gpu/drm/xe/tests/xe_migrate.c | 10 ++-------- drivers/gpu/drm/xe/tests/xe_mocs.c | 10 ++-------- 4 files changed, 7 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/xe/tests/xe_bo.c b/drivers/gpu/drm/xe/tests/xe_bo.c index 2294cf89f3e1..2278e589a493 100644 --- a/drivers/gpu/drm/xe/tests/xe_bo.c +++ b/drivers/gpu/drm/xe/tests/xe_bo.c @@ -185,8 +185,7 @@ static int ccs_test_run_device(struct xe_device *xe) return 0; } - xe_pm_runtime_get(xe); - + guard(xe_pm_runtime)(xe); for_each_tile(tile, xe, id) { /* For igfx run only for primary tile */ if (!IS_DGFX(xe) && id > 0) @@ -194,8 +193,6 @@ static int ccs_test_run_device(struct xe_device *xe) ccs_test_run_tile(xe, tile, test); } - xe_pm_runtime_put(xe); - return 0; } @@ -356,13 +353,10 @@ static int evict_test_run_device(struct xe_device *xe) return 0; } - xe_pm_runtime_get(xe); - + guard(xe_pm_runtime)(xe); for_each_tile(tile, xe, id) evict_test_run_tile(xe, tile, test); - xe_pm_runtime_put(xe); - return 0; } diff --git a/drivers/gpu/drm/xe/tests/xe_dma_buf.c b/drivers/gpu/drm/xe/tests/xe_dma_buf.c index 5df98de5ba3c..954b6b911ea0 100644 --- a/drivers/gpu/drm/xe/tests/xe_dma_buf.c +++ b/drivers/gpu/drm/xe/tests/xe_dma_buf.c @@ -266,7 +266,7 @@ static int dma_buf_run_device(struct xe_device *xe) const struct dma_buf_test_params *params; struct kunit *test = kunit_get_current_test(); - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); for (params = test_params; params->mem_mask; ++params) { struct dma_buf_test_params p = *params; @@ -274,7 +274,6 @@ static int dma_buf_run_device(struct xe_device *xe) test->priv = &p; xe_test_dmabuf_import_same_driver(xe); } - xe_pm_runtime_put(xe); /* A non-zero return would halt iteration over driver devices */ return 0; diff --git a/drivers/gpu/drm/xe/tests/xe_migrate.c b/drivers/gpu/drm/xe/tests/xe_migrate.c index 5904d658d1f2..34e2f0f4631f 100644 --- a/drivers/gpu/drm/xe/tests/xe_migrate.c +++ b/drivers/gpu/drm/xe/tests/xe_migrate.c @@ -344,8 +344,7 @@ static int migrate_test_run_device(struct xe_device *xe) struct xe_tile *tile; int id; - xe_pm_runtime_get(xe); - + guard(xe_pm_runtime)(xe); for_each_tile(tile, xe, id) { struct xe_migrate *m = tile->migrate; struct drm_exec *exec = XE_VALIDATION_OPT_OUT; @@ -356,8 +355,6 @@ static int migrate_test_run_device(struct xe_device *xe) xe_vm_unlock(m->q->vm); } - xe_pm_runtime_put(xe); - return 0; } @@ -759,13 +756,10 @@ static int validate_ccs_test_run_device(struct xe_device *xe) return 0; } - xe_pm_runtime_get(xe); - + guard(xe_pm_runtime)(xe); for_each_tile(tile, xe, id) validate_ccs_test_run_tile(xe, tile, test); - xe_pm_runtime_put(xe); - return 0; } diff --git a/drivers/gpu/drm/xe/tests/xe_mocs.c b/drivers/gpu/drm/xe/tests/xe_mocs.c index 28374330b894..daf3c6836c75 100644 --- a/drivers/gpu/drm/xe/tests/xe_mocs.c +++ b/drivers/gpu/drm/xe/tests/xe_mocs.c @@ -115,8 +115,7 @@ static int mocs_kernel_test_run_device(struct xe_device *xe) unsigned int flags; int id; - xe_pm_runtime_get(xe); - + guard(xe_pm_runtime)(xe); for_each_gt(gt, xe, id) { flags = live_mocs_init(&mocs, gt); if (flags & HAS_GLOBAL_MOCS) @@ -125,8 +124,6 @@ static int mocs_kernel_test_run_device(struct xe_device *xe) read_l3cc_table(gt, &mocs.table); } - xe_pm_runtime_put(xe); - return 0; } @@ -150,8 +147,7 @@ static int mocs_reset_test_run_device(struct xe_device *xe) int id; struct kunit *test = kunit_get_current_test(); - xe_pm_runtime_get(xe); - + guard(xe_pm_runtime)(xe); for_each_gt(gt, xe, id) { flags = live_mocs_init(&mocs, gt); kunit_info(test, "mocs_reset_test before reset\n"); @@ -169,8 +165,6 @@ static int mocs_reset_test_run_device(struct xe_device *xe) read_l3cc_table(gt, &mocs.table); } - xe_pm_runtime_put(xe); - return 0; } From f50c11ba35da84450b3206b50618ecb6482968dc Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:44:05 -0800 Subject: [PATCH 0084/1610] drm/xe/sysfs: Use scope-based runtime power management Switch sysfs to use scope-based runtime power management to slightly simplify the code. v2: - Drop unnecessary local variables. (Gustavo) Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-55-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_device_sysfs.c | 33 ++++++++----------- drivers/gpu/drm/xe/xe_gt_freq.c | 27 +++++---------- drivers/gpu/drm/xe/xe_gt_throttle.c | 9 ++--- drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c | 16 ++++----- 4 files changed, 31 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_device_sysfs.c b/drivers/gpu/drm/xe/xe_device_sysfs.c index ec9c06b06fb5..a73e0e957cb0 100644 --- a/drivers/gpu/drm/xe/xe_device_sysfs.c +++ b/drivers/gpu/drm/xe/xe_device_sysfs.c @@ -57,9 +57,8 @@ vram_d3cold_threshold_store(struct device *dev, struct device_attribute *attr, drm_dbg(&xe->drm, "vram_d3cold_threshold: %u\n", vram_d3cold_threshold); - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); ret = xe_pm_set_vram_threshold(xe, vram_d3cold_threshold); - xe_pm_runtime_put(xe); return ret ?: count; } @@ -84,33 +83,31 @@ lb_fan_control_version_show(struct device *dev, struct device_attribute *attr, c u16 major = 0, minor = 0, hotfix = 0, build = 0; int ret; - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); ret = xe_pcode_read(root, PCODE_MBOX(PCODE_LATE_BINDING, GET_CAPABILITY_STATUS, 0), &cap, NULL); if (ret) - goto out; + return ret; if (REG_FIELD_GET(V1_FAN_PROVISIONED, cap)) { ret = xe_pcode_read(root, PCODE_MBOX(PCODE_LATE_BINDING, GET_VERSION_LOW, 0), &ver_low, NULL); if (ret) - goto out; + return ret; ret = xe_pcode_read(root, PCODE_MBOX(PCODE_LATE_BINDING, GET_VERSION_HIGH, 0), &ver_high, NULL); if (ret) - goto out; + return ret; major = REG_FIELD_GET(MAJOR_VERSION_MASK, ver_low); minor = REG_FIELD_GET(MINOR_VERSION_MASK, ver_low); hotfix = REG_FIELD_GET(HOTFIX_VERSION_MASK, ver_high); build = REG_FIELD_GET(BUILD_VERSION_MASK, ver_high); } -out: - xe_pm_runtime_put(xe); - return ret ?: sysfs_emit(buf, "%u.%u.%u.%u\n", major, minor, hotfix, build); + return sysfs_emit(buf, "%u.%u.%u.%u\n", major, minor, hotfix, build); } static DEVICE_ATTR_ADMIN_RO(lb_fan_control_version); @@ -123,33 +120,31 @@ lb_voltage_regulator_version_show(struct device *dev, struct device_attribute *a u16 major = 0, minor = 0, hotfix = 0, build = 0; int ret; - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); ret = xe_pcode_read(root, PCODE_MBOX(PCODE_LATE_BINDING, GET_CAPABILITY_STATUS, 0), &cap, NULL); if (ret) - goto out; + return ret; if (REG_FIELD_GET(VR_PARAMS_PROVISIONED, cap)) { ret = xe_pcode_read(root, PCODE_MBOX(PCODE_LATE_BINDING, GET_VERSION_LOW, 0), &ver_low, NULL); if (ret) - goto out; + return ret; ret = xe_pcode_read(root, PCODE_MBOX(PCODE_LATE_BINDING, GET_VERSION_HIGH, 0), &ver_high, NULL); if (ret) - goto out; + return ret; major = REG_FIELD_GET(MAJOR_VERSION_MASK, ver_low); minor = REG_FIELD_GET(MINOR_VERSION_MASK, ver_low); hotfix = REG_FIELD_GET(HOTFIX_VERSION_MASK, ver_high); build = REG_FIELD_GET(BUILD_VERSION_MASK, ver_high); } -out: - xe_pm_runtime_put(xe); - return ret ?: sysfs_emit(buf, "%u.%u.%u.%u\n", major, minor, hotfix, build); + return sysfs_emit(buf, "%u.%u.%u.%u\n", major, minor, hotfix, build); } static DEVICE_ATTR_ADMIN_RO(lb_voltage_regulator_version); @@ -233,9 +228,8 @@ auto_link_downgrade_capable_show(struct device *dev, struct device_attribute *at struct xe_device *xe = pdev_to_xe_device(pdev); u32 cap, val; - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); val = xe_mmio_read32(xe_root_tile_mmio(xe), BMG_PCIE_CAP); - xe_pm_runtime_put(xe); cap = REG_FIELD_GET(LINK_DOWNGRADE, val); return sysfs_emit(buf, "%u\n", cap == DOWNGRADE_CAPABLE); @@ -251,11 +245,10 @@ auto_link_downgrade_status_show(struct device *dev, struct device_attribute *att u32 val = 0; int ret; - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); ret = xe_pcode_read(xe_device_get_root_tile(xe), PCODE_MBOX(DGFX_PCODE_STATUS, DGFX_GET_INIT_STATUS, 0), &val, NULL); - xe_pm_runtime_put(xe); return ret ?: sysfs_emit(buf, "%u\n", REG_FIELD_GET(DGFX_LINK_DOWNGRADE_STATUS, val)); } diff --git a/drivers/gpu/drm/xe/xe_gt_freq.c b/drivers/gpu/drm/xe/xe_gt_freq.c index 849ea6c86e8e..6284a4daf00a 100644 --- a/drivers/gpu/drm/xe/xe_gt_freq.c +++ b/drivers/gpu/drm/xe/xe_gt_freq.c @@ -70,9 +70,8 @@ static ssize_t act_freq_show(struct kobject *kobj, struct xe_guc_pc *pc = dev_to_pc(dev); u32 freq; - xe_pm_runtime_get(dev_to_xe(dev)); + guard(xe_pm_runtime)(dev_to_xe(dev)); freq = xe_guc_pc_get_act_freq(pc); - xe_pm_runtime_put(dev_to_xe(dev)); return sysfs_emit(buf, "%d\n", freq); } @@ -86,9 +85,8 @@ static ssize_t cur_freq_show(struct kobject *kobj, u32 freq; ssize_t ret; - xe_pm_runtime_get(dev_to_xe(dev)); + guard(xe_pm_runtime)(dev_to_xe(dev)); ret = xe_guc_pc_get_cur_freq(pc, &freq); - xe_pm_runtime_put(dev_to_xe(dev)); if (ret) return ret; @@ -113,9 +111,8 @@ static ssize_t rpe_freq_show(struct kobject *kobj, struct xe_guc_pc *pc = dev_to_pc(dev); u32 freq; - xe_pm_runtime_get(dev_to_xe(dev)); + guard(xe_pm_runtime)(dev_to_xe(dev)); freq = xe_guc_pc_get_rpe_freq(pc); - xe_pm_runtime_put(dev_to_xe(dev)); return sysfs_emit(buf, "%d\n", freq); } @@ -128,9 +125,8 @@ static ssize_t rpa_freq_show(struct kobject *kobj, struct xe_guc_pc *pc = dev_to_pc(dev); u32 freq; - xe_pm_runtime_get(dev_to_xe(dev)); + guard(xe_pm_runtime)(dev_to_xe(dev)); freq = xe_guc_pc_get_rpa_freq(pc); - xe_pm_runtime_put(dev_to_xe(dev)); return sysfs_emit(buf, "%d\n", freq); } @@ -154,9 +150,8 @@ static ssize_t min_freq_show(struct kobject *kobj, u32 freq; ssize_t ret; - xe_pm_runtime_get(dev_to_xe(dev)); + guard(xe_pm_runtime)(dev_to_xe(dev)); ret = xe_guc_pc_get_min_freq(pc, &freq); - xe_pm_runtime_put(dev_to_xe(dev)); if (ret) return ret; @@ -175,9 +170,8 @@ static ssize_t min_freq_store(struct kobject *kobj, if (ret) return ret; - xe_pm_runtime_get(dev_to_xe(dev)); + guard(xe_pm_runtime)(dev_to_xe(dev)); ret = xe_guc_pc_set_min_freq(pc, freq); - xe_pm_runtime_put(dev_to_xe(dev)); if (ret) return ret; @@ -193,9 +187,8 @@ static ssize_t max_freq_show(struct kobject *kobj, u32 freq; ssize_t ret; - xe_pm_runtime_get(dev_to_xe(dev)); + guard(xe_pm_runtime)(dev_to_xe(dev)); ret = xe_guc_pc_get_max_freq(pc, &freq); - xe_pm_runtime_put(dev_to_xe(dev)); if (ret) return ret; @@ -214,9 +207,8 @@ static ssize_t max_freq_store(struct kobject *kobj, if (ret) return ret; - xe_pm_runtime_get(dev_to_xe(dev)); + guard(xe_pm_runtime)(dev_to_xe(dev)); ret = xe_guc_pc_set_max_freq(pc, freq); - xe_pm_runtime_put(dev_to_xe(dev)); if (ret) return ret; @@ -243,9 +235,8 @@ static ssize_t power_profile_store(struct kobject *kobj, struct xe_guc_pc *pc = dev_to_pc(dev); int err; - xe_pm_runtime_get(dev_to_xe(dev)); + guard(xe_pm_runtime)(dev_to_xe(dev)); err = xe_guc_pc_set_power_profile(pc, buff); - xe_pm_runtime_put(dev_to_xe(dev)); return err ?: count; } diff --git a/drivers/gpu/drm/xe/xe_gt_throttle.c b/drivers/gpu/drm/xe/xe_gt_throttle.c index 82c5fbcdfbe3..096a6187ff12 100644 --- a/drivers/gpu/drm/xe/xe_gt_throttle.c +++ b/drivers/gpu/drm/xe/xe_gt_throttle.c @@ -85,7 +85,7 @@ u32 xe_gt_throttle_get_limit_reasons(struct xe_gt *gt) { struct xe_device *xe = gt_to_xe(gt); struct xe_reg reg; - u32 val, mask; + u32 mask; if (xe_gt_is_media_type(gt)) reg = MTL_MEDIA_PERF_LIMIT_REASONS; @@ -97,11 +97,8 @@ u32 xe_gt_throttle_get_limit_reasons(struct xe_gt *gt) else mask = GT0_PERF_LIMIT_REASONS_MASK; - xe_pm_runtime_get(xe); - val = xe_mmio_read32(>->mmio, reg) & mask; - xe_pm_runtime_put(xe); - - return val; + guard(xe_pm_runtime)(xe); + return xe_mmio_read32(>->mmio, reg) & mask; } static bool is_throttled_by(struct xe_gt *gt, u32 mask) diff --git a/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c b/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c index 640950172088..cb45cdceef67 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c +++ b/drivers/gpu/drm/xe/xe_hw_engine_class_sysfs.c @@ -43,16 +43,14 @@ static ssize_t xe_hw_engine_class_sysfs_attr_show(struct kobject *kobj, { struct xe_device *xe = kobj_to_xe(kobj); struct kobj_attribute *kattr; - ssize_t ret = -EIO; kattr = container_of(attr, struct kobj_attribute, attr); if (kattr->show) { - xe_pm_runtime_get(xe); - ret = kattr->show(kobj, kattr, buf); - xe_pm_runtime_put(xe); + guard(xe_pm_runtime)(xe); + return kattr->show(kobj, kattr, buf); } - return ret; + return -EIO; } static ssize_t xe_hw_engine_class_sysfs_attr_store(struct kobject *kobj, @@ -62,16 +60,14 @@ static ssize_t xe_hw_engine_class_sysfs_attr_store(struct kobject *kobj, { struct xe_device *xe = kobj_to_xe(kobj); struct kobj_attribute *kattr; - ssize_t ret = -EIO; kattr = container_of(attr, struct kobj_attribute, attr); if (kattr->store) { - xe_pm_runtime_get(xe); - ret = kattr->store(kobj, kattr, buf, count); - xe_pm_runtime_put(xe); + guard(xe_pm_runtime)(xe); + return kattr->store(kobj, kattr, buf, count); } - return ret; + return -EIO; } static const struct sysfs_ops xe_hw_engine_class_sysfs_ops = { From 423fb66fac7dbb5ee2b26c40e0d21c0ffb0d7533 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 18 Nov 2025 08:44:06 -0800 Subject: [PATCH 0085/1610] drm/xe/debugfs: Use scope-based runtime PM Switch the debugfs code to use scope-based runtime PM where possible, for consistency with other parts of the driver. v2: - Drop unnecessary 'ret' variables. (Gustavo) Reviewed-by: Gustavo Sousa Link: https://patch.msgid.link/20251118164338.3572146-56-matthew.d.roper@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/xe/xe_debugfs.c | 16 +++++----------- drivers/gpu/drm/xe/xe_gsc_debugfs.c | 3 +-- drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c | 12 ++++-------- drivers/gpu/drm/xe/xe_guc_debugfs.c | 8 ++------ drivers/gpu/drm/xe/xe_huc_debugfs.c | 3 +-- drivers/gpu/drm/xe/xe_tile_debugfs.c | 8 ++------ 6 files changed, 15 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c index e91da9589c5f..1d5a2a43a9d7 100644 --- a/drivers/gpu/drm/xe/xe_debugfs.c +++ b/drivers/gpu/drm/xe/xe_debugfs.c @@ -68,7 +68,7 @@ static int info(struct seq_file *m, void *data) struct xe_gt *gt; u8 id; - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); drm_printf(&p, "graphics_verx100 %d\n", xe->info.graphics_verx100); drm_printf(&p, "media_verx100 %d\n", xe->info.media_verx100); @@ -95,7 +95,6 @@ static int info(struct seq_file *m, void *data) gt->info.engine_mask); } - xe_pm_runtime_put(xe); return 0; } @@ -110,9 +109,8 @@ static int sriov_info(struct seq_file *m, void *data) static int workarounds(struct xe_device *xe, struct drm_printer *p) { - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); xe_wa_device_dump(xe, p); - xe_pm_runtime_put(xe); return 0; } @@ -134,7 +132,7 @@ static int dgfx_pkg_residencies_show(struct seq_file *m, void *data) xe = node_to_xe(m->private); p = drm_seq_file_printer(m); - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); mmio = xe_root_tile_mmio(xe); static const struct { u32 offset; @@ -151,7 +149,6 @@ static int dgfx_pkg_residencies_show(struct seq_file *m, void *data) for (int i = 0; i < ARRAY_SIZE(residencies); i++) read_residency_counter(xe, mmio, residencies[i].offset, residencies[i].name, &p); - xe_pm_runtime_put(xe); return 0; } @@ -163,7 +160,7 @@ static int dgfx_pcie_link_residencies_show(struct seq_file *m, void *data) xe = node_to_xe(m->private); p = drm_seq_file_printer(m); - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); mmio = xe_root_tile_mmio(xe); static const struct { @@ -178,7 +175,6 @@ static int dgfx_pcie_link_residencies_show(struct seq_file *m, void *data) for (int i = 0; i < ARRAY_SIZE(residencies); i++) read_residency_counter(xe, mmio, residencies[i].offset, residencies[i].name, &p); - xe_pm_runtime_put(xe); return 0; } @@ -277,16 +273,14 @@ static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf, xe->wedged.mode = wedged_mode; - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); for_each_gt(gt, xe, id) { ret = xe_guc_ads_scheduler_policy_toggle_reset(>->uc.guc.ads); if (ret) { xe_gt_err(gt, "Failed to update GuC ADS scheduler policy. GuC may still cause engine reset even with wedged_mode=2\n"); - xe_pm_runtime_put(xe); return -EIO; } } - xe_pm_runtime_put(xe); return size; } diff --git a/drivers/gpu/drm/xe/xe_gsc_debugfs.c b/drivers/gpu/drm/xe/xe_gsc_debugfs.c index 461d7e99c2b3..b13928b50eb9 100644 --- a/drivers/gpu/drm/xe/xe_gsc_debugfs.c +++ b/drivers/gpu/drm/xe/xe_gsc_debugfs.c @@ -37,9 +37,8 @@ static int gsc_info(struct seq_file *m, void *data) struct xe_device *xe = gsc_to_xe(gsc); struct drm_printer p = drm_seq_file_printer(m); - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); xe_gsc_print_info(gsc, &p); - xe_pm_runtime_put(xe); return 0; } diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c index 5278ea4fd655..0fd863609848 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c @@ -123,11 +123,10 @@ static int POLICY##_set(void *data, u64 val) \ if (val > (TYPE)~0ull) \ return -EOVERFLOW; \ \ - xe_pm_runtime_get(xe); \ + guard(xe_pm_runtime)(xe); \ err = xe_gt_sriov_pf_policy_set_##POLICY(gt, val); \ if (!err) \ xe_sriov_pf_provision_set_custom_mode(xe); \ - xe_pm_runtime_put(xe); \ \ return err; \ } \ @@ -189,12 +188,11 @@ static int CONFIG##_set(void *data, u64 val) \ if (val > (TYPE)~0ull) \ return -EOVERFLOW; \ \ - xe_pm_runtime_get(xe); \ + guard(xe_pm_runtime)(xe); \ err = xe_sriov_pf_wait_ready(xe) ?: \ xe_gt_sriov_pf_config_set_##CONFIG(gt, vfid, val); \ if (!err) \ xe_sriov_pf_provision_set_custom_mode(xe); \ - xe_pm_runtime_put(xe); \ \ return err; \ } \ @@ -249,11 +247,10 @@ static int set_threshold(void *data, u64 val, enum xe_guc_klv_threshold_index in if (val > (u32)~0ull) return -EOVERFLOW; - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); err = xe_gt_sriov_pf_config_set_threshold(gt, vfid, index, val); if (!err) xe_sriov_pf_provision_set_custom_mode(xe); - xe_pm_runtime_put(xe); return err; } @@ -358,9 +355,8 @@ static ssize_t control_write(struct file *file, const char __user *buf, size_t c xe_gt_assert(gt, sizeof(cmd) > strlen(control_cmds[n].cmd)); if (sysfs_streq(cmd, control_cmds[n].cmd)) { - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); ret = control_cmds[n].fn ? (*control_cmds[n].fn)(gt, vfid) : 0; - xe_pm_runtime_put(xe); break; } } diff --git a/drivers/gpu/drm/xe/xe_guc_debugfs.c b/drivers/gpu/drm/xe/xe_guc_debugfs.c index 0b102ab46c4d..efaca259d3e8 100644 --- a/drivers/gpu/drm/xe/xe_guc_debugfs.c +++ b/drivers/gpu/drm/xe/xe_guc_debugfs.c @@ -70,13 +70,9 @@ static int guc_debugfs_show(struct seq_file *m, void *data) struct xe_gt *gt = grandparent->d_inode->i_private; struct xe_device *xe = gt_to_xe(gt); int (*print)(struct xe_guc *, struct drm_printer *) = node->info_ent->data; - int ret; - xe_pm_runtime_get(xe); - ret = print(>->uc.guc, &p); - xe_pm_runtime_put(xe); - - return ret; + guard(xe_pm_runtime)(xe); + return print(>->uc.guc, &p); } static int guc_log(struct xe_guc *guc, struct drm_printer *p) diff --git a/drivers/gpu/drm/xe/xe_huc_debugfs.c b/drivers/gpu/drm/xe/xe_huc_debugfs.c index 3a888a40188b..df9c4d79b710 100644 --- a/drivers/gpu/drm/xe/xe_huc_debugfs.c +++ b/drivers/gpu/drm/xe/xe_huc_debugfs.c @@ -37,9 +37,8 @@ static int huc_info(struct seq_file *m, void *data) struct xe_device *xe = huc_to_xe(huc); struct drm_printer p = drm_seq_file_printer(m); - xe_pm_runtime_get(xe); + guard(xe_pm_runtime)(xe); xe_huc_print_info(huc, &p); - xe_pm_runtime_put(xe); return 0; } diff --git a/drivers/gpu/drm/xe/xe_tile_debugfs.c b/drivers/gpu/drm/xe/xe_tile_debugfs.c index fff242a5ae56..39eeca75dded 100644 --- a/drivers/gpu/drm/xe/xe_tile_debugfs.c +++ b/drivers/gpu/drm/xe/xe_tile_debugfs.c @@ -82,13 +82,9 @@ int xe_tile_debugfs_show_with_rpm(struct seq_file *m, void *data) struct drm_info_node *node = m->private; struct xe_tile *tile = node_to_tile(node); struct xe_device *xe = tile_to_xe(tile); - int ret; - xe_pm_runtime_get(xe); - ret = xe_tile_debugfs_simple_show(m, data); - xe_pm_runtime_put(xe); - - return ret; + guard(xe_pm_runtime)(xe); + return xe_tile_debugfs_simple_show(m, data); } static int ggtt(struct xe_tile *tile, struct drm_printer *p) From 28aeaed130e8e587fd1b73b6d66ca41ccc5a1a31 Mon Sep 17 00:00:00 2001 From: Sanjay Yadav Date: Tue, 18 Nov 2025 17:19:00 +0530 Subject: [PATCH 0086/1610] drm/xe/oa: Fix potential UAF in xe_oa_add_config_ioctl() In xe_oa_add_config_ioctl(), we accessed oa_config->id after dropping metrics_lock. Since this lock protects the lifetime of oa_config, an attacker could guess the id and call xe_oa_remove_config_ioctl() with perfect timing, freeing oa_config before we dereference it, leading to a potential use-after-free. Fix this by caching the id in a local variable while holding the lock. v2: (Matt A) - Dropped mutex_unlock(&oa->metrics_lock) ordering change from xe_oa_remove_config_ioctl() Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/6614 Fixes: cdf02fe1a94a7 ("drm/xe/oa/uapi: Add/remove OA config perf ops") Cc: # v6.11+ Suggested-by: Matthew Auld Signed-off-by: Sanjay Yadav Reviewed-by: Matthew Auld Signed-off-by: Matthew Auld Link: https://patch.msgid.link/20251118114859.3379952-2-sanjay.kumar.yadav@intel.com --- drivers/gpu/drm/xe/xe_oa.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c index 87a2bf53d661..890c363282ae 100644 --- a/drivers/gpu/drm/xe/xe_oa.c +++ b/drivers/gpu/drm/xe/xe_oa.c @@ -2403,11 +2403,13 @@ int xe_oa_add_config_ioctl(struct drm_device *dev, u64 data, struct drm_file *fi goto sysfs_err; } + id = oa_config->id; + + drm_dbg(&oa->xe->drm, "Added config %s id=%i\n", oa_config->uuid, id); + mutex_unlock(&oa->metrics_lock); - drm_dbg(&oa->xe->drm, "Added config %s id=%i\n", oa_config->uuid, oa_config->id); - - return oa_config->id; + return id; sysfs_err: mutex_unlock(&oa->metrics_lock); From e2b1c3a127665fbca7099c886e4f755785ea1118 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:40 +0200 Subject: [PATCH 0087/1610] drm/i915/edram: extract i915_edram.[ch] for edram detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While edram detection ostensibly belongs with the rest of the dram stuff in soc/intel_dram.c, it's only required by i915 core, not display. Extract it to a separate i915_edram.[ch] file. This allows us to drop the edram_size_mb member from struct xe_device. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/612edb7b70755655fbf193ba8af1c539fb93b698.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_driver.c | 3 +- drivers/gpu/drm/i915/i915_edram.c | 44 +++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_edram.h | 11 +++++++ drivers/gpu/drm/i915/soc/intel_dram.c | 36 ---------------------- drivers/gpu/drm/i915/soc/intel_dram.h | 1 - drivers/gpu/drm/xe/xe_device_types.h | 6 ---- 7 files changed, 58 insertions(+), 44 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_edram.c create mode 100644 drivers/gpu/drm/i915/i915_edram.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 477278aee831..4e263ab520c1 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -27,6 +27,7 @@ i915-y += \ i915_config.o \ i915_driver.o \ i915_drm_client.o \ + i915_edram.o \ i915_getparam.o \ i915_ioctl.o \ i915_irq.o \ diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 7c60b6873934..44a17ffc3058 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -94,6 +94,7 @@ #include "i915_driver.h" #include "i915_drm_client.h" #include "i915_drv.h" +#include "i915_edram.h" #include "i915_file_private.h" #include "i915_getparam.h" #include "i915_hwmon.h" @@ -493,7 +494,7 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv) } /* needs to be done before ggtt probe */ - intel_dram_edram_detect(dev_priv); + i915_edram_detect(dev_priv); ret = i915_set_dma_info(dev_priv); if (ret) diff --git a/drivers/gpu/drm/i915/i915_edram.c b/drivers/gpu/drm/i915/i915_edram.c new file mode 100644 index 000000000000..5818ec396d1e --- /dev/null +++ b/drivers/gpu/drm/i915/i915_edram.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +/* Copyright © 2025 Intel Corporation */ + +#include + +#include "i915_drv.h" +#include "i915_edram.h" +#include "i915_reg.h" + +static u32 gen9_edram_size_mb(struct drm_i915_private *i915, u32 cap) +{ + static const u8 ways[8] = { 4, 8, 12, 16, 16, 16, 16, 16 }; + static const u8 sets[4] = { 1, 1, 2, 2 }; + + return EDRAM_NUM_BANKS(cap) * + ways[EDRAM_WAYS_IDX(cap)] * + sets[EDRAM_SETS_IDX(cap)]; +} + +void i915_edram_detect(struct drm_i915_private *i915) +{ + u32 edram_cap = 0; + + if (!(IS_HASWELL(i915) || IS_BROADWELL(i915) || GRAPHICS_VER(i915) >= 9)) + return; + + edram_cap = intel_uncore_read_fw(&i915->uncore, HSW_EDRAM_CAP); + + /* NB: We can't write IDICR yet because we don't have gt funcs set up */ + + if (!(edram_cap & EDRAM_ENABLED)) + return; + + /* + * The needed capability bits for size calculation are not there with + * pre gen9 so return 128MB always. + */ + if (GRAPHICS_VER(i915) < 9) + i915->edram_size_mb = 128; + else + i915->edram_size_mb = gen9_edram_size_mb(i915, edram_cap); + + drm_info(&i915->drm, "Found %uMB of eDRAM\n", i915->edram_size_mb); +} diff --git a/drivers/gpu/drm/i915/i915_edram.h b/drivers/gpu/drm/i915/i915_edram.h new file mode 100644 index 000000000000..8319422ace9d --- /dev/null +++ b/drivers/gpu/drm/i915/i915_edram.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2025 Intel Corporation */ + +#ifndef __I915_DRAM_H__ +#define __I915_DRAM_H__ + +struct drm_i915_private; + +void i915_edram_detect(struct drm_i915_private *i915); + +#endif /* __I915_DRAM_H__ */ diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index 739cfe48f6db..cfe96c3c1b1a 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -861,39 +861,3 @@ const struct dram_info *intel_dram_info(struct drm_device *drm) return i915->dram_info; } - -static u32 gen9_edram_size_mb(struct drm_i915_private *i915, u32 cap) -{ - static const u8 ways[8] = { 4, 8, 12, 16, 16, 16, 16, 16 }; - static const u8 sets[4] = { 1, 1, 2, 2 }; - - return EDRAM_NUM_BANKS(cap) * - ways[EDRAM_WAYS_IDX(cap)] * - sets[EDRAM_SETS_IDX(cap)]; -} - -void intel_dram_edram_detect(struct drm_i915_private *i915) -{ - u32 edram_cap = 0; - - if (!(IS_HASWELL(i915) || IS_BROADWELL(i915) || GRAPHICS_VER(i915) >= 9)) - return; - - edram_cap = intel_uncore_read_fw(&i915->uncore, HSW_EDRAM_CAP); - - /* NB: We can't write IDICR yet because we don't have gt funcs set up */ - - if (!(edram_cap & EDRAM_ENABLED)) - return; - - /* - * The needed capability bits for size calculation are not there with - * pre gen9 so return 128MB always. - */ - if (GRAPHICS_VER(i915) < 9) - i915->edram_size_mb = 128; - else - i915->edram_size_mb = gen9_edram_size_mb(i915, edram_cap); - - drm_info(&i915->drm, "Found %uMB of eDRAM\n", i915->edram_size_mb); -} diff --git a/drivers/gpu/drm/i915/soc/intel_dram.h b/drivers/gpu/drm/i915/soc/intel_dram.h index 8475ee379daa..58aaf2f91afe 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.h +++ b/drivers/gpu/drm/i915/soc/intel_dram.h @@ -35,7 +35,6 @@ struct dram_info { bool has_16gb_dimms; }; -void intel_dram_edram_detect(struct drm_i915_private *i915); int intel_dram_detect(struct drm_i915_private *i915); unsigned int intel_fsb_freq(struct drm_i915_private *i915); unsigned int intel_mem_freq(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index e772851c08e9..430ac085c22b 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -639,12 +639,6 @@ struct xe_device { */ const struct dram_info *dram_info; - /* - * edram size in MB. - * Cannot be determined by PCIID. You must always read a register. - */ - u32 edram_size_mb; - struct intel_uncore { spinlock_t lock; } uncore; From 2d74a09360a920d87a4e9538797068a0f9e5e2e1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:41 +0200 Subject: [PATCH 0088/1610] drm/i915: split out i915_freq.[ch] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The i915 core only needs three rather specific functions from soc/intel_dram.[ch]: i9xx_fsb_freq(), ilk_fsb_freq(), and ilk_mem_freq(). Add new i915_freq.[ch] and duplicate those functions for i915 to reduce the dependency on soc/ code. Wile duplication in general is bad, here it's a tradeoff to simplify the i915, xe and display interactions. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/7bac1b194afdc20cd45e625a0a32fcbcd0b1136e.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 1 + .../gpu/drm/i915/gt/intel_gt_clock_utils.c | 4 +- drivers/gpu/drm/i915/gt/intel_rps.c | 6 +- drivers/gpu/drm/i915/i915_freq.c | 111 ++++++++++++++++++ drivers/gpu/drm/i915/i915_freq.h | 13 ++ 5 files changed, 130 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_freq.c create mode 100644 drivers/gpu/drm/i915/i915_freq.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 4e263ab520c1..8dc75174fcbc 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -28,6 +28,7 @@ i915-y += \ i915_driver.o \ i915_drm_client.o \ i915_edram.o \ + i915_freq.o \ i915_getparam.o \ i915_ioctl.o \ i915_irq.o \ diff --git a/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c b/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c index c90b35881a26..aecd120972ea 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c @@ -4,12 +4,12 @@ */ #include "i915_drv.h" +#include "i915_freq.h" #include "i915_reg.h" #include "intel_gt.h" #include "intel_gt_clock_utils.h" #include "intel_gt_print.h" #include "intel_gt_regs.h" -#include "soc/intel_dram.h" static u32 read_reference_ts_freq(struct intel_uncore *uncore) { @@ -148,7 +148,7 @@ static u32 gen4_read_clock_frequency(struct intel_uncore *uncore) * * Testing on actual hardware has shown there is no /16. */ - return DIV_ROUND_CLOSEST(intel_fsb_freq(uncore->i915), 4) * 1000; + return DIV_ROUND_CLOSEST(i9xx_fsb_freq(uncore->i915), 4) * 1000; } static u32 read_clock_frequency(struct intel_uncore *uncore) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index d233dc122bd7..90b7eee78f1f 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -10,9 +10,9 @@ #include "display/intel_display_rps.h" #include "display/vlv_clock.h" -#include "soc/intel_dram.h" #include "i915_drv.h" +#include "i915_freq.h" #include "i915_irq.h" #include "i915_reg.h" #include "i915_wait_util.h" @@ -285,8 +285,8 @@ static void gen5_rps_init(struct intel_rps *rps) u32 rgvmodectl; int c_m, i; - fsb_freq = intel_fsb_freq(i915); - mem_freq = intel_mem_freq(i915); + fsb_freq = ilk_fsb_freq(i915); + mem_freq = ilk_mem_freq(i915); if (fsb_freq <= 3200000) c_m = 0; diff --git a/drivers/gpu/drm/i915/i915_freq.c b/drivers/gpu/drm/i915/i915_freq.c new file mode 100644 index 000000000000..9bdaea34aef9 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_freq.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: MIT +/* Copyright © 2025 Intel Corporation */ + +#include + +#include "i915_drv.h" +#include "i915_freq.h" +#include "intel_mchbar_regs.h" + +unsigned int i9xx_fsb_freq(struct drm_i915_private *i915) +{ + u32 fsb; + + /* + * Note that this only reads the state of the FSB + * straps, not the actual FSB frequency. Some BIOSen + * let you configure each independently. Ideally we'd + * read out the actual FSB frequency but sadly we + * don't know which registers have that information, + * and all the relevant docs have gone to bit heaven :( + */ + fsb = intel_uncore_read(&i915->uncore, CLKCFG) & CLKCFG_FSB_MASK; + + if (IS_PINEVIEW(i915) || IS_MOBILE(i915)) { + switch (fsb) { + case CLKCFG_FSB_400: + return 400000; + case CLKCFG_FSB_533: + return 533333; + case CLKCFG_FSB_667: + return 666667; + case CLKCFG_FSB_800: + return 800000; + case CLKCFG_FSB_1067: + return 1066667; + case CLKCFG_FSB_1333: + return 1333333; + default: + MISSING_CASE(fsb); + return 1333333; + } + } else { + switch (fsb) { + case CLKCFG_FSB_400_ALT: + return 400000; + case CLKCFG_FSB_533: + return 533333; + case CLKCFG_FSB_667: + return 666667; + case CLKCFG_FSB_800: + return 800000; + case CLKCFG_FSB_1067_ALT: + return 1066667; + case CLKCFG_FSB_1333_ALT: + return 1333333; + case CLKCFG_FSB_1600_ALT: + return 1600000; + default: + MISSING_CASE(fsb); + return 1333333; + } + } +} + +unsigned int ilk_fsb_freq(struct drm_i915_private *i915) +{ + u16 fsb; + + fsb = intel_uncore_read16(&i915->uncore, CSIPLL0) & 0x3ff; + + switch (fsb) { + case 0x00c: + return 3200000; + case 0x00e: + return 3733333; + case 0x010: + return 4266667; + case 0x012: + return 4800000; + case 0x014: + return 5333333; + case 0x016: + return 5866667; + case 0x018: + return 6400000; + default: + drm_dbg(&i915->drm, "unknown fsb frequency 0x%04x\n", fsb); + return 0; + } +} + +unsigned int ilk_mem_freq(struct drm_i915_private *i915) +{ + u16 ddrpll; + + ddrpll = intel_uncore_read16(&i915->uncore, DDRMPLL1); + switch (ddrpll & 0xff) { + case 0xc: + return 800000; + case 0x10: + return 1066667; + case 0x14: + return 1333333; + case 0x18: + return 1600000; + default: + drm_dbg(&i915->drm, "unknown memory frequency 0x%02x\n", + ddrpll & 0xff); + return 0; + } +} diff --git a/drivers/gpu/drm/i915/i915_freq.h b/drivers/gpu/drm/i915/i915_freq.h new file mode 100644 index 000000000000..53b0ecb95440 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_freq.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2025 Intel Corporation */ + +#ifndef __I915_FREQ_H__ +#define __I915_FREQ_H__ + +struct drm_i915_private; + +unsigned int i9xx_fsb_freq(struct drm_i915_private *i915); +unsigned int ilk_fsb_freq(struct drm_i915_private *i915); +unsigned int ilk_mem_freq(struct drm_i915_private *i915); + +#endif /* __I915_FREQ_H__ */ From ed46f724b725e7692cee18f26901c6dbde33dff1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:42 +0200 Subject: [PATCH 0089/1610] drm/i915: move intel_dram.[ch] from soc/ to display/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The remaining users of intel_dram.[ch] are all in display. Move them under display. This allows us to remove the compat soc/intel_dram.h from xe. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/4c0fbdab989a70d287536a7eafb002dc836ced12.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 2 +- drivers/gpu/drm/i915/display/i9xx_wm.c | 3 +-- drivers/gpu/drm/i915/display/intel_bw.c | 3 +-- drivers/gpu/drm/i915/display/intel_cdclk.c | 3 +-- drivers/gpu/drm/i915/display/intel_display_power.c | 3 +-- drivers/gpu/drm/i915/{soc => display}/intel_dram.c | 5 ++--- drivers/gpu/drm/i915/{soc => display}/intel_dram.h | 0 drivers/gpu/drm/i915/display/skl_watermark.c | 2 +- drivers/gpu/drm/i915/i915_driver.c | 2 +- drivers/gpu/drm/xe/Makefile | 2 +- drivers/gpu/drm/xe/compat-i915-headers/soc/intel_dram.h | 6 ------ drivers/gpu/drm/xe/display/xe_display.c | 2 +- 12 files changed, 11 insertions(+), 22 deletions(-) rename drivers/gpu/drm/i915/{soc => display}/intel_dram.c (99%) rename drivers/gpu/drm/i915/{soc => display}/intel_dram.h (100%) delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/soc/intel_dram.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 8dc75174fcbc..57d150765784 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -58,7 +58,6 @@ i915-y += \ # core peripheral code i915-y += \ - soc/intel_dram.o \ soc/intel_gmch.o \ soc/intel_rom.o @@ -268,6 +267,7 @@ i915-y += \ display/intel_dpll_mgr.o \ display/intel_dpt.o \ display/intel_dpt_common.o \ + display/intel_dram.o \ display/intel_drrs.o \ display/intel_dsb.o \ display/intel_dsb_buffer.o \ diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 01f3803fa09f..27e2d73bc505 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -7,8 +7,6 @@ #include -#include "soc/intel_dram.h" - #include "i915_drv.h" #include "i915_reg.h" #include "i9xx_wm.h" @@ -19,6 +17,7 @@ #include "intel_display.h" #include "intel_display_regs.h" #include "intel_display_trace.h" +#include "intel_dram.h" #include "intel_fb.h" #include "intel_mchbar_regs.h" #include "intel_wm.h" diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 1f6461be50ef..957c90e62569 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -6,8 +6,6 @@ #include #include -#include "soc/intel_dram.h" - #include "i915_drv.h" #include "i915_reg.h" #include "intel_bw.h" @@ -16,6 +14,7 @@ #include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_display_utils.h" +#include "intel_dram.h" #include "intel_mchbar_regs.h" #include "intel_pcode.h" #include "intel_uncore.h" diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 37801c744b05..531819391c8c 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -28,8 +28,6 @@ #include #include -#include "soc/intel_dram.h" - #include "hsw_ips.h" #include "i915_drv.h" #include "i915_reg.h" @@ -42,6 +40,7 @@ #include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_display_utils.h" +#include "intel_dram.h" #include "intel_mchbar_regs.h" #include "intel_pci_config.h" #include "intel_pcode.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index a383ef23391d..9c5f0277d8c2 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -8,8 +8,6 @@ #include -#include "soc/intel_dram.h" - #include "i915_drv.h" #include "i915_reg.h" #include "intel_backlight_regs.h" @@ -25,6 +23,7 @@ #include "intel_display_types.h" #include "intel_display_utils.h" #include "intel_dmc.h" +#include "intel_dram.h" #include "intel_mchbar_regs.h" #include "intel_parent.h" #include "intel_pch_refclk.h" diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/display/intel_dram.c similarity index 99% rename from drivers/gpu/drm/i915/soc/intel_dram.c rename to drivers/gpu/drm/i915/display/intel_dram.c index cfe96c3c1b1a..7142772f2a6e 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/display/intel_dram.c @@ -8,11 +8,10 @@ #include #include -#include "../display/intel_display_core.h" /* FIXME */ - #include "i915_drv.h" #include "i915_reg.h" -#include "i915_utils.h" +#include "intel_display_core.h" +#include "intel_display_utils.h" #include "intel_dram.h" #include "intel_mchbar_regs.h" #include "intel_pcode.h" diff --git a/drivers/gpu/drm/i915/soc/intel_dram.h b/drivers/gpu/drm/i915/display/intel_dram.h similarity index 100% rename from drivers/gpu/drm/i915/soc/intel_dram.h rename to drivers/gpu/drm/i915/display/intel_dram.h diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 54e9e0be019d..a33e0cec8cba 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -8,7 +8,6 @@ #include #include -#include "soc/intel_dram.h" #include "i915_reg.h" #include "i9xx_wm.h" #include "intel_atomic.h" @@ -23,6 +22,7 @@ #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_display_utils.h" +#include "intel_dram.h" #include "intel_fb.h" #include "intel_fixed.h" #include "intel_flipq.h" diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 44a17ffc3058..d1f573f1b6cc 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -59,6 +59,7 @@ #include "display/intel_dmc.h" #include "display/intel_dp.h" #include "display/intel_dpt.h" +#include "display/intel_dram.h" #include "display/intel_encoder.h" #include "display/intel_fbdev.h" #include "display/intel_gmbus.h" @@ -87,7 +88,6 @@ #include "pxp/intel_pxp_debugfs.h" #include "pxp/intel_pxp_pm.h" -#include "soc/intel_dram.h" #include "soc/intel_gmch.h" #include "i915_debugfs.h" diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 8b60fc72fe50..f296a00e4dc9 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -220,7 +220,6 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ # SOC code shared with i915 xe-$(CONFIG_DRM_XE_DISPLAY) += \ - i915-soc/intel_dram.o \ i915-soc/intel_rom.o # Display code shared with i915 @@ -272,6 +271,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_dpll.o \ i915-display/intel_dpll_mgr.o \ i915-display/intel_dpt_common.o \ + i915-display/intel_dram.o \ i915-display/intel_drrs.o \ i915-display/intel_dsb.o \ i915-display/intel_dsi.o \ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_dram.h b/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_dram.h deleted file mode 100644 index 65707e20c557..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_dram.h +++ /dev/null @@ -1,6 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#include "../../../i915/soc/intel_dram.h" diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index e3320d9e6314..9b1d21e03df0 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -17,7 +17,6 @@ #include #include -#include "soc/intel_dram.h" #include "intel_acpi.h" #include "intel_audio.h" #include "intel_bw.h" @@ -29,6 +28,7 @@ #include "intel_dmc.h" #include "intel_dmc_wl.h" #include "intel_dp.h" +#include "intel_dram.h" #include "intel_encoder.h" #include "intel_fbdev.h" #include "intel_hdcp.h" From 1178b860605891dc728404dadff4dd6adeadb444 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:43 +0200 Subject: [PATCH 0090/1610] drm/xe: remove MISSING_CASE() from compat i915_utils.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are no longer users for MISSING_CASE() in the compat i915_utils.h. Remove it to prevent new users from showing up. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/b967e605ff9d9ad459f3d12a9dfc9244458d83a1.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h index bcd441dc0fce..3639721f0bf8 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h @@ -3,11 +3,5 @@ * Copyright © 2023 Intel Corporation */ -/* for soc/ */ -#ifndef MISSING_CASE -#define MISSING_CASE(x) WARN(1, "Missing case (%s == %ld)\n", \ - __stringify(x), (long)(x)) -#endif - /* for a couple of users under i915/display */ #define i915_inject_probe_failure(unused) ((unused) && 0) From b8660fa66207ff36efcc0f1747845e423c7ad987 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 20 Nov 2025 18:18:46 +0200 Subject: [PATCH 0091/1610] drm/i915/dram: convert to struct intel_display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert everything except uncore access to struct intel_display. Converting the graphics version checks to display version checks needs a tweak for display version 13, which have graphics version 12. While at it, convert logging to drm_dbg_kms(). v2: Handle display version 13 Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/20251120161846.3128999-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/i9xx_wm.c | 2 +- drivers/gpu/drm/i915/display/intel_bw.c | 2 +- drivers/gpu/drm/i915/display/intel_cdclk.c | 4 +- .../drm/i915/display/intel_display_power.c | 2 +- drivers/gpu/drm/i915/display/intel_dram.c | 205 +++++++++--------- drivers/gpu/drm/i915/display/intel_dram.h | 11 +- drivers/gpu/drm/i915/display/skl_watermark.c | 4 +- drivers/gpu/drm/i915/i915_driver.c | 2 +- drivers/gpu/drm/xe/display/xe_display.c | 2 +- 9 files changed, 120 insertions(+), 114 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 27e2d73bc505..167277cd8877 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -90,7 +90,7 @@ static const struct cxsr_latency cxsr_latency_table[] = { static const struct cxsr_latency *pnv_get_cxsr_latency(struct intel_display *display) { - const struct dram_info *dram_info = intel_dram_info(display->drm); + const struct dram_info *dram_info = intel_dram_info(display); bool is_ddr3 = dram_info->type == INTEL_DRAM_DDR3; int i; diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 957c90e62569..d27835ed49c2 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -799,7 +799,7 @@ static unsigned int icl_qgv_bw(struct intel_display *display, void intel_bw_init_hw(struct intel_display *display) { - const struct dram_info *dram_info = intel_dram_info(display->drm); + const struct dram_info *dram_info = intel_dram_info(display); if (!HAS_DISPLAY(display)) return; diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 531819391c8c..5c90e53b4e46 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -3737,10 +3737,8 @@ static int pch_rawclk(struct intel_display *display) static int i9xx_hrawclk(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - /* hrawclock is 1/4 the FSB frequency */ - return DIV_ROUND_CLOSEST(intel_fsb_freq(i915), 4); + return DIV_ROUND_CLOSEST(intel_fsb_freq(display), 4); } /** diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 9c5f0277d8c2..08db9bbbfcb1 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -1616,7 +1616,7 @@ static const struct buddy_page_mask wa_1409767108_buddy_page_masks[] = { static void tgl_bw_buddy_init(struct intel_display *display) { - const struct dram_info *dram_info = intel_dram_info(display->drm); + const struct dram_info *dram_info = intel_dram_info(display); const struct buddy_page_mask *table; unsigned long abox_mask = DISPLAY_INFO(display)->abox_mask; int config, i; diff --git a/drivers/gpu/drm/i915/display/intel_dram.c b/drivers/gpu/drm/i915/display/intel_dram.c index 7142772f2a6e..b4fa1fe8709c 100644 --- a/drivers/gpu/drm/i915/display/intel_dram.c +++ b/drivers/gpu/drm/i915/display/intel_dram.c @@ -56,14 +56,17 @@ const char *intel_dram_type_str(enum intel_dram_type type) #undef DRAM_TYPE_STR -static enum intel_dram_type pnv_dram_type(struct drm_i915_private *i915) +static enum intel_dram_type pnv_dram_type(struct intel_display *display) { + struct drm_i915_private *i915 = to_i915(display->drm); + return intel_uncore_read(&i915->uncore, CSHRDDR3CTL) & CSHRDDR3CTL_DDR3 ? INTEL_DRAM_DDR3 : INTEL_DRAM_DDR2; } -static unsigned int pnv_mem_freq(struct drm_i915_private *dev_priv) +static unsigned int pnv_mem_freq(struct intel_display *display) { + struct drm_i915_private *dev_priv = to_i915(display->drm); u32 tmp; tmp = intel_uncore_read(&dev_priv->uncore, CLKCFG); @@ -80,8 +83,9 @@ static unsigned int pnv_mem_freq(struct drm_i915_private *dev_priv) return 0; } -static unsigned int ilk_mem_freq(struct drm_i915_private *dev_priv) +static unsigned int ilk_mem_freq(struct intel_display *display) { + struct drm_i915_private *dev_priv = to_i915(display->drm); u16 ddrpll; ddrpll = intel_uncore_read16(&dev_priv->uncore, DDRMPLL1); @@ -95,19 +99,19 @@ static unsigned int ilk_mem_freq(struct drm_i915_private *dev_priv) case 0x18: return 1600000; default: - drm_dbg(&dev_priv->drm, "unknown memory frequency 0x%02x\n", - ddrpll & 0xff); + drm_dbg_kms(display->drm, "unknown memory frequency 0x%02x\n", + ddrpll & 0xff); return 0; } } -static unsigned int chv_mem_freq(struct drm_i915_private *i915) +static unsigned int chv_mem_freq(struct intel_display *display) { u32 val; - vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_CCK)); - val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_CCK, CCK_FUSE_REG); - vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_CCK)); + vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_CCK)); + val = vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_CCK, CCK_FUSE_REG); + vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_CCK)); switch ((val >> 2) & 0x7) { case 3: @@ -117,13 +121,13 @@ static unsigned int chv_mem_freq(struct drm_i915_private *i915) } } -static unsigned int vlv_mem_freq(struct drm_i915_private *i915) +static unsigned int vlv_mem_freq(struct intel_display *display) { u32 val; - vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); - val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_PUNIT)); + val = vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); + vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_PUNIT)); switch ((val >> 6) & 3) { case 0: @@ -138,22 +142,23 @@ static unsigned int vlv_mem_freq(struct drm_i915_private *i915) return 0; } -unsigned int intel_mem_freq(struct drm_i915_private *i915) +unsigned int intel_mem_freq(struct intel_display *display) { - if (IS_PINEVIEW(i915)) - return pnv_mem_freq(i915); - else if (GRAPHICS_VER(i915) == 5) - return ilk_mem_freq(i915); - else if (IS_CHERRYVIEW(i915)) - return chv_mem_freq(i915); - else if (IS_VALLEYVIEW(i915)) - return vlv_mem_freq(i915); + if (display->platform.pineview) + return pnv_mem_freq(display); + else if (DISPLAY_VER(display) == 5) + return ilk_mem_freq(display); + else if (display->platform.cherryview) + return chv_mem_freq(display); + else if (display->platform.valleyview) + return vlv_mem_freq(display); else return 0; } -static unsigned int i9xx_fsb_freq(struct drm_i915_private *i915) +static unsigned int i9xx_fsb_freq(struct intel_display *display) { + struct drm_i915_private *i915 = to_i915(display->drm); u32 fsb; /* @@ -166,7 +171,7 @@ static unsigned int i9xx_fsb_freq(struct drm_i915_private *i915) */ fsb = intel_uncore_read(&i915->uncore, CLKCFG) & CLKCFG_FSB_MASK; - if (IS_PINEVIEW(i915) || IS_MOBILE(i915)) { + if (display->platform.pineview || display->platform.mobile) { switch (fsb) { case CLKCFG_FSB_400: return 400000; @@ -207,8 +212,9 @@ static unsigned int i9xx_fsb_freq(struct drm_i915_private *i915) } } -static unsigned int ilk_fsb_freq(struct drm_i915_private *dev_priv) +static unsigned int ilk_fsb_freq(struct intel_display *display) { + struct drm_i915_private *dev_priv = to_i915(display->drm); u16 fsb; fsb = intel_uncore_read16(&dev_priv->uncore, CSIPLL0) & 0x3ff; @@ -229,33 +235,33 @@ static unsigned int ilk_fsb_freq(struct drm_i915_private *dev_priv) case 0x018: return 6400000; default: - drm_dbg(&dev_priv->drm, "unknown fsb frequency 0x%04x\n", fsb); + drm_dbg_kms(display->drm, "unknown fsb frequency 0x%04x\n", fsb); return 0; } } -unsigned int intel_fsb_freq(struct drm_i915_private *i915) +unsigned int intel_fsb_freq(struct intel_display *display) { - if (GRAPHICS_VER(i915) == 5) - return ilk_fsb_freq(i915); - else if (GRAPHICS_VER(i915) == 3 || GRAPHICS_VER(i915) == 4) - return i9xx_fsb_freq(i915); + if (DISPLAY_VER(display) == 5) + return ilk_fsb_freq(display); + else if (IS_DISPLAY_VER(display, 3, 4)) + return i9xx_fsb_freq(display); else return 0; } -static int i915_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +static int i915_get_dram_info(struct intel_display *display, struct dram_info *dram_info) { - dram_info->fsb_freq = intel_fsb_freq(i915); + dram_info->fsb_freq = intel_fsb_freq(display); if (dram_info->fsb_freq) - drm_dbg(&i915->drm, "FSB frequency: %d kHz\n", dram_info->fsb_freq); + drm_dbg_kms(display->drm, "FSB frequency: %d kHz\n", dram_info->fsb_freq); - dram_info->mem_freq = intel_mem_freq(i915); + dram_info->mem_freq = intel_mem_freq(display); if (dram_info->mem_freq) - drm_dbg(&i915->drm, "DDR speed: %d kHz\n", dram_info->mem_freq); + drm_dbg_kms(display->drm, "DDR speed: %d kHz\n", dram_info->mem_freq); - if (IS_PINEVIEW(i915)) - dram_info->type = pnv_dram_type(i915); + if (display->platform.pineview) + dram_info->type = pnv_dram_type(display); return 0; } @@ -391,22 +397,22 @@ skl_is_16gb_dimm(const struct dram_dimm_info *dimm) } static void -skl_dram_print_dimm_info(struct drm_i915_private *i915, +skl_dram_print_dimm_info(struct intel_display *display, struct dram_dimm_info *dimm, int channel, char dimm_name) { - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "CH%u DIMM %c size: %u Gb, width: X%u, ranks: %u, 16Gb+ DIMMs: %s\n", channel, dimm_name, dimm->size, dimm->width, dimm->ranks, str_yes_no(skl_is_16gb_dimm(dimm))); } static void -skl_dram_get_dimm_l_info(struct drm_i915_private *i915, +skl_dram_get_dimm_l_info(struct intel_display *display, struct dram_dimm_info *dimm, int channel, u32 val) { - if (GRAPHICS_VER(i915) >= 11) { + if (DISPLAY_VER(display) >= 11) { dimm->size = icl_get_dimm_l_size(val); dimm->width = icl_get_dimm_l_width(val); dimm->ranks = icl_get_dimm_l_ranks(val); @@ -416,15 +422,15 @@ skl_dram_get_dimm_l_info(struct drm_i915_private *i915, dimm->ranks = skl_get_dimm_l_ranks(val); } - skl_dram_print_dimm_info(i915, dimm, channel, 'L'); + skl_dram_print_dimm_info(display, dimm, channel, 'L'); } static void -skl_dram_get_dimm_s_info(struct drm_i915_private *i915, +skl_dram_get_dimm_s_info(struct intel_display *display, struct dram_dimm_info *dimm, int channel, u32 val) { - if (GRAPHICS_VER(i915) >= 11) { + if (DISPLAY_VER(display) >= 11) { dimm->size = icl_get_dimm_s_size(val); dimm->width = icl_get_dimm_s_width(val); dimm->ranks = icl_get_dimm_s_ranks(val); @@ -434,19 +440,19 @@ skl_dram_get_dimm_s_info(struct drm_i915_private *i915, dimm->ranks = skl_get_dimm_s_ranks(val); } - skl_dram_print_dimm_info(i915, dimm, channel, 'S'); + skl_dram_print_dimm_info(display, dimm, channel, 'S'); } static int -skl_dram_get_channel_info(struct drm_i915_private *i915, +skl_dram_get_channel_info(struct intel_display *display, struct dram_channel_info *ch, int channel, u32 val) { - skl_dram_get_dimm_l_info(i915, &ch->dimm_l, channel, val); - skl_dram_get_dimm_s_info(i915, &ch->dimm_s, channel, val); + skl_dram_get_dimm_l_info(display, &ch->dimm_l, channel, val); + skl_dram_get_dimm_s_info(display, &ch->dimm_s, channel, val); if (ch->dimm_l.size == 0 && ch->dimm_s.size == 0) { - drm_dbg_kms(&i915->drm, "CH%u not populated\n", channel); + drm_dbg_kms(display->drm, "CH%u not populated\n", channel); return -EINVAL; } @@ -460,7 +466,7 @@ skl_dram_get_channel_info(struct drm_i915_private *i915, ch->is_16gb_dimm = skl_is_16gb_dimm(&ch->dimm_l) || skl_is_16gb_dimm(&ch->dimm_s); - drm_dbg_kms(&i915->drm, "CH%u ranks: %u, 16Gb+ DIMMs: %s\n", + drm_dbg_kms(display->drm, "CH%u ranks: %u, 16Gb+ DIMMs: %s\n", channel, ch->ranks, str_yes_no(ch->is_16gb_dimm)); return 0; @@ -476,8 +482,9 @@ intel_is_dram_symmetric(const struct dram_channel_info *ch0, } static int -skl_dram_get_channels_info(struct drm_i915_private *i915, struct dram_info *dram_info) +skl_dram_get_channels_info(struct intel_display *display, struct dram_info *dram_info) { + struct drm_i915_private *i915 = to_i915(display->drm); struct dram_channel_info ch0 = {}, ch1 = {}; u32 val; int ret; @@ -487,23 +494,23 @@ skl_dram_get_channels_info(struct drm_i915_private *i915, struct dram_info *dram val = intel_uncore_read(&i915->uncore, SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); - ret = skl_dram_get_channel_info(i915, &ch0, 0, val); + ret = skl_dram_get_channel_info(display, &ch0, 0, val); if (ret == 0) dram_info->num_channels++; val = intel_uncore_read(&i915->uncore, SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); - ret = skl_dram_get_channel_info(i915, &ch1, 1, val); + ret = skl_dram_get_channel_info(display, &ch1, 1, val); if (ret == 0) dram_info->num_channels++; if (dram_info->num_channels == 0) { - drm_info(&i915->drm, "Number of memory channels is zero\n"); + drm_info(display->drm, "Number of memory channels is zero\n"); return -EINVAL; } if (ch0.ranks == 0 && ch1.ranks == 0) { - drm_info(&i915->drm, "couldn't get memory rank information\n"); + drm_info(display->drm, "couldn't get memory rank information\n"); return -EINVAL; } @@ -511,18 +518,19 @@ skl_dram_get_channels_info(struct drm_i915_private *i915, struct dram_info *dram dram_info->symmetric_memory = intel_is_dram_symmetric(&ch0, &ch1); - drm_dbg_kms(&i915->drm, "Memory configuration is symmetric? %s\n", + drm_dbg_kms(display->drm, "Memory configuration is symmetric? %s\n", str_yes_no(dram_info->symmetric_memory)); - drm_dbg_kms(&i915->drm, "16Gb+ DIMMs: %s\n", + drm_dbg_kms(display->drm, "16Gb+ DIMMs: %s\n", str_yes_no(dram_info->has_16gb_dimms)); return 0; } static enum intel_dram_type -skl_get_dram_type(struct drm_i915_private *i915) +skl_get_dram_type(struct intel_display *display) { + struct drm_i915_private *i915 = to_i915(display->drm); u32 val; val = intel_uncore_read(&i915->uncore, @@ -544,13 +552,13 @@ skl_get_dram_type(struct drm_i915_private *i915) } static int -skl_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +skl_get_dram_info(struct intel_display *display, struct dram_info *dram_info) { int ret; - dram_info->type = skl_get_dram_type(i915); + dram_info->type = skl_get_dram_type(display); - ret = skl_dram_get_channels_info(i915, dram_info); + ret = skl_dram_get_channels_info(display, dram_info); if (ret) return ret; @@ -635,8 +643,9 @@ static void bxt_get_dimm_info(struct dram_dimm_info *dimm, u32 val) dimm->size = bxt_get_dimm_size(val) * intel_dimm_num_devices(dimm); } -static int bxt_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +static int bxt_get_dram_info(struct intel_display *display, struct dram_info *dram_info) { + struct drm_i915_private *i915 = to_i915(display->drm); u32 val; u8 valid_ranks = 0; int i; @@ -657,11 +666,11 @@ static int bxt_get_dram_info(struct drm_i915_private *i915, struct dram_info *dr bxt_get_dimm_info(&dimm, val); type = bxt_get_dimm_type(val); - drm_WARN_ON(&i915->drm, type != INTEL_DRAM_UNKNOWN && + drm_WARN_ON(display->drm, type != INTEL_DRAM_UNKNOWN && dram_info->type != INTEL_DRAM_UNKNOWN && dram_info->type != type); - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "CH%u DIMM size: %u Gb, width: X%u, ranks: %u\n", i - BXT_D_CR_DRP0_DUNIT_START, dimm.size, dimm.width, dimm.ranks); @@ -674,25 +683,25 @@ static int bxt_get_dram_info(struct drm_i915_private *i915, struct dram_info *dr } if (dram_info->type == INTEL_DRAM_UNKNOWN || valid_ranks == 0) { - drm_info(&i915->drm, "couldn't get memory information\n"); + drm_info(display->drm, "couldn't get memory information\n"); return -EINVAL; } return 0; } -static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv, +static int icl_pcode_read_mem_global_info(struct intel_display *display, struct dram_info *dram_info) { u32 val = 0; int ret; - ret = intel_pcode_read(&dev_priv->drm, ICL_PCODE_MEM_SUBSYSYSTEM_INFO | + ret = intel_pcode_read(display->drm, ICL_PCODE_MEM_SUBSYSYSTEM_INFO | ICL_PCODE_MEM_SS_READ_GLOBAL_INFO, &val, NULL); if (ret) return ret; - if (GRAPHICS_VER(dev_priv) == 12) { + if (DISPLAY_VER(display) >= 12) { switch (val & 0xf) { case 0: dram_info->type = INTEL_DRAM_DDR4; @@ -743,25 +752,25 @@ static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv, return 0; } -static int gen11_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +static int gen11_get_dram_info(struct intel_display *display, struct dram_info *dram_info) { int ret; - ret = skl_dram_get_channels_info(i915, dram_info); + ret = skl_dram_get_channels_info(display, dram_info); if (ret) return ret; - return icl_pcode_read_mem_global_info(i915, dram_info); + return icl_pcode_read_mem_global_info(display, dram_info); } -static int gen12_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +static int gen12_get_dram_info(struct intel_display *display, struct dram_info *dram_info) { - return icl_pcode_read_mem_global_info(i915, dram_info); + return icl_pcode_read_mem_global_info(display, dram_info); } -static int xelpdp_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +static int xelpdp_get_dram_info(struct intel_display *display, struct dram_info *dram_info) { - struct intel_display *display = i915->display; + struct drm_i915_private *i915 = to_i915(display->drm); u32 val = intel_uncore_read(&i915->uncore, MTL_MEM_SS_INFO_GLOBAL); switch (REG_FIELD_GET(MTL_DDR_TYPE_MASK, val)) { @@ -784,11 +793,11 @@ static int xelpdp_get_dram_info(struct drm_i915_private *i915, struct dram_info dram_info->type = INTEL_DRAM_LPDDR3; break; case 8: - drm_WARN_ON(&i915->drm, !IS_DGFX(i915)); + drm_WARN_ON(display->drm, !display->platform.dgfx); dram_info->type = INTEL_DRAM_GDDR; break; case 9: - drm_WARN_ON(&i915->drm, !IS_DGFX(i915)); + drm_WARN_ON(display->drm, !display->platform.dgfx); dram_info->type = INTEL_DRAM_GDDR_ECC; break; default: @@ -806,41 +815,41 @@ static int xelpdp_get_dram_info(struct drm_i915_private *i915, struct dram_info return 0; } -int intel_dram_detect(struct drm_i915_private *i915) +int intel_dram_detect(struct intel_display *display) { - struct intel_display *display = i915->display; + struct drm_i915_private *i915 = to_i915(display->drm); struct dram_info *dram_info; int ret; - if (IS_DG2(i915) || !intel_display_device_present(display)) + if (display->platform.dg2 || !HAS_DISPLAY(display)) return 0; - dram_info = drmm_kzalloc(&i915->drm, sizeof(*dram_info), GFP_KERNEL); + dram_info = drmm_kzalloc(display->drm, sizeof(*dram_info), GFP_KERNEL); if (!dram_info) return -ENOMEM; i915->dram_info = dram_info; if (DISPLAY_VER(display) >= 14) - ret = xelpdp_get_dram_info(i915, dram_info); - else if (GRAPHICS_VER(i915) >= 12) - ret = gen12_get_dram_info(i915, dram_info); - else if (GRAPHICS_VER(i915) >= 11) - ret = gen11_get_dram_info(i915, dram_info); - else if (IS_BROXTON(i915) || IS_GEMINILAKE(i915)) - ret = bxt_get_dram_info(i915, dram_info); - else if (GRAPHICS_VER(i915) >= 9) - ret = skl_get_dram_info(i915, dram_info); + ret = xelpdp_get_dram_info(display, dram_info); + else if (DISPLAY_VER(display) >= 12) + ret = gen12_get_dram_info(display, dram_info); + else if (DISPLAY_VER(display) >= 11) + ret = gen11_get_dram_info(display, dram_info); + else if (display->platform.broxton || display->platform.geminilake) + ret = bxt_get_dram_info(display, dram_info); + else if (DISPLAY_VER(display) >= 9) + ret = skl_get_dram_info(display, dram_info); else - ret = i915_get_dram_info(i915, dram_info); + ret = i915_get_dram_info(display, dram_info); - drm_dbg_kms(&i915->drm, "DRAM type: %s\n", + drm_dbg_kms(display->drm, "DRAM type: %s\n", intel_dram_type_str(dram_info->type)); - drm_dbg_kms(&i915->drm, "DRAM channels: %u\n", dram_info->num_channels); + drm_dbg_kms(display->drm, "DRAM channels: %u\n", dram_info->num_channels); - drm_dbg_kms(&i915->drm, "Num QGV points %u\n", dram_info->num_qgv_points); - drm_dbg_kms(&i915->drm, "Num PSF GV points %u\n", dram_info->num_psf_gv_points); + drm_dbg_kms(display->drm, "Num QGV points %u\n", dram_info->num_qgv_points); + drm_dbg_kms(display->drm, "Num PSF GV points %u\n", dram_info->num_psf_gv_points); /* TODO: Do we want to abort probe on dram detection failures? */ if (ret) @@ -854,9 +863,9 @@ int intel_dram_detect(struct drm_i915_private *i915) * checks, and prefer not dereferencing on platforms that shouldn't look at dram * info, to catch accidental and incorrect dram info checks. */ -const struct dram_info *intel_dram_info(struct drm_device *drm) +const struct dram_info *intel_dram_info(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(drm); + struct drm_i915_private *i915 = to_i915(display->drm); return i915->dram_info; } diff --git a/drivers/gpu/drm/i915/display/intel_dram.h b/drivers/gpu/drm/i915/display/intel_dram.h index 58aaf2f91afe..5800b7b4e614 100644 --- a/drivers/gpu/drm/i915/display/intel_dram.h +++ b/drivers/gpu/drm/i915/display/intel_dram.h @@ -8,8 +8,7 @@ #include -struct drm_i915_private; -struct drm_device; +struct intel_display; struct dram_info { enum intel_dram_type { @@ -35,10 +34,10 @@ struct dram_info { bool has_16gb_dimms; }; -int intel_dram_detect(struct drm_i915_private *i915); -unsigned int intel_fsb_freq(struct drm_i915_private *i915); -unsigned int intel_mem_freq(struct drm_i915_private *i915); -const struct dram_info *intel_dram_info(struct drm_device *drm); +int intel_dram_detect(struct intel_display *display); +unsigned int intel_fsb_freq(struct intel_display *display); +unsigned int intel_mem_freq(struct intel_display *display); +const struct dram_info *intel_dram_info(struct intel_display *display); const char *intel_dram_type_str(enum intel_dram_type type); #endif /* __INTEL_DRAM_H__ */ diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index a33e0cec8cba..7964cfffdaae 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -3125,7 +3125,7 @@ static bool skl_watermark_ipc_can_enable(struct intel_display *display) if (display->platform.kabylake || display->platform.coffeelake || display->platform.cometlake) { - const struct dram_info *dram_info = intel_dram_info(display->drm); + const struct dram_info *dram_info = intel_dram_info(display); return dram_info->symmetric_memory; } @@ -3169,7 +3169,7 @@ static void increase_wm_latency(struct intel_display *display, int inc) static bool need_16gb_dimm_wa(struct intel_display *display) { - const struct dram_info *dram_info = intel_dram_info(display->drm); + const struct dram_info *dram_info = intel_dram_info(display); return (display->platform.skylake || display->platform.kabylake || display->platform.coffeelake || display->platform.cometlake || diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index d1f573f1b6cc..2369e2b55096 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -574,7 +574,7 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv) * Fill the dram structure to get the system dram info. This will be * used for memory latency calculation. */ - ret = intel_dram_detect(dev_priv); + ret = intel_dram_detect(display); if (ret) goto err_opregion; diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 9b1d21e03df0..793115077615 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -122,7 +122,7 @@ int xe_display_init_early(struct xe_device *xe) * Fill the dram structure to get the system dram info. This will be * used for memory latency calculation. */ - err = intel_dram_detect(xe); + err = intel_dram_detect(display); if (err) goto err_opregion; From de4ca6f8e9277fed49192454b7940681977ab1e5 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:45 +0200 Subject: [PATCH 0092/1610] drm/i915: move dram_info to struct intel_display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With all of dram code under display, also move dram_info to struct intel_display. This further cleans up struct xe_device from display related members. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/cbbca93003952ea24ae60e66d79d901dba78ccd8.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_core.h | 4 ++++ drivers/gpu/drm/i915/display/intel_dram.c | 7 ++----- drivers/gpu/drm/i915/i915_drv.h | 3 --- drivers/gpu/drm/xe/xe_device_types.h | 2 -- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 9b8414b77c15..9b36654b593d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -394,6 +394,10 @@ struct intel_display { u32 mmio_base; } dsi; + struct { + const struct dram_info *info; + } dram; + struct { /* list of fbdev register on this device */ struct intel_fbdev *fbdev; diff --git a/drivers/gpu/drm/i915/display/intel_dram.c b/drivers/gpu/drm/i915/display/intel_dram.c index b4fa1fe8709c..019a722a38bf 100644 --- a/drivers/gpu/drm/i915/display/intel_dram.c +++ b/drivers/gpu/drm/i915/display/intel_dram.c @@ -817,7 +817,6 @@ static int xelpdp_get_dram_info(struct intel_display *display, struct dram_info int intel_dram_detect(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); struct dram_info *dram_info; int ret; @@ -828,7 +827,7 @@ int intel_dram_detect(struct intel_display *display) if (!dram_info) return -ENOMEM; - i915->dram_info = dram_info; + display->dram.info = dram_info; if (DISPLAY_VER(display) >= 14) ret = xelpdp_get_dram_info(display, dram_info); @@ -865,7 +864,5 @@ int intel_dram_detect(struct intel_display *display) */ const struct dram_info *intel_dram_info(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - - return i915->dram_info; + return display->dram.info; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5381a934a671..96af7776bee5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -60,7 +60,6 @@ #include "intel_step.h" #include "intel_uncore.h" -struct dram_info; struct drm_i915_clock_gating_funcs; struct intel_display; struct intel_pxp; @@ -279,8 +278,6 @@ struct drm_i915_private { u32 suspend_count; struct vlv_s0ix_state *vlv_s0ix_state; - const struct dram_info *dram_info; - struct intel_runtime_pm runtime_pm; struct i915_perf perf; diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 430ac085c22b..10b91dac96ad 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -34,7 +34,6 @@ #define TEST_VM_OPS_ERROR #endif -struct dram_info; struct intel_display; struct intel_dg_nvm_dev; struct xe_ggtt; @@ -637,7 +636,6 @@ struct xe_device { * drm_i915_private during build. After cleanup these should go away, * migrating to the right sub-structs */ - const struct dram_info *dram_info; struct intel_uncore { spinlock_t lock; From b3d3c83e00c7846bfa6c4aa12f64321849dd3819 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:46 +0200 Subject: [PATCH 0093/1610] drm/i915: move intel_rom.[ch] from soc/ to display/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sole user of intel_rom.[ch] has always been in display. Move them under display. This allows us to remove the compat soc/intel_rom.h from xe, as well as the Makefile rules to build anything from soc/. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/352ec255a6e9b81c7d1e35d8fbf7018d4049d4d3.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 4 ++-- drivers/gpu/drm/i915/display/intel_bios.c | 3 +-- drivers/gpu/drm/i915/{soc => display}/intel_rom.c | 0 drivers/gpu/drm/i915/{soc => display}/intel_rom.h | 0 drivers/gpu/drm/xe/Makefile | 10 +--------- drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h | 6 ------ 6 files changed, 4 insertions(+), 19 deletions(-) rename drivers/gpu/drm/i915/{soc => display}/intel_rom.c (100%) rename drivers/gpu/drm/i915/{soc => display}/intel_rom.h (100%) delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 57d150765784..42f2d9294142 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -58,8 +58,7 @@ i915-y += \ # core peripheral code i915-y += \ - soc/intel_gmch.o \ - soc/intel_rom.o + soc/intel_gmch.o # core library code i915-y += \ @@ -303,6 +302,7 @@ i915-y += \ display/intel_pmdemand.o \ display/intel_psr.o \ display/intel_quirks.o \ + display/intel_rom.o \ display/intel_sbi.o \ display/intel_sprite.o \ display/intel_sprite_uapi.o \ diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 4b41068e9e35..a639c5eb3245 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -34,14 +34,13 @@ #include #include -#include "soc/intel_rom.h" - #include "intel_display.h" #include "intel_display_core.h" #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_display_utils.h" #include "intel_gmbus.h" +#include "intel_rom.h" #define _INTEL_BIOS_PRIVATE #include "intel_vbt_defs.h" diff --git a/drivers/gpu/drm/i915/soc/intel_rom.c b/drivers/gpu/drm/i915/display/intel_rom.c similarity index 100% rename from drivers/gpu/drm/i915/soc/intel_rom.c rename to drivers/gpu/drm/i915/display/intel_rom.c diff --git a/drivers/gpu/drm/i915/soc/intel_rom.h b/drivers/gpu/drm/i915/display/intel_rom.h similarity index 100% rename from drivers/gpu/drm/i915/soc/intel_rom.h rename to drivers/gpu/drm/i915/display/intel_rom.h diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index f296a00e4dc9..f4315b014826 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -191,11 +191,6 @@ subdir-ccflags-$(CONFIG_DRM_XE_DISPLAY) += \ -I$(srctree)/drivers/gpu/drm/i915/display/ \ -Ddrm_i915_private=xe_device -# Rule to build SOC code shared with i915 -$(obj)/i915-soc/%.o: $(srctree)/drivers/gpu/drm/i915/soc/%.c FORCE - $(call cmd,force_checksrc) - $(call if_changed_rule,cc_o_c) - # Rule to build display code shared with i915 $(obj)/i915-display/%.o: $(srctree)/drivers/gpu/drm/i915/display/%.c FORCE $(call cmd,force_checksrc) @@ -218,10 +213,6 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ display/xe_stolen.o \ display/xe_tdf.o -# SOC code shared with i915 -xe-$(CONFIG_DRM_XE_DISPLAY) += \ - i915-soc/intel_rom.o - # Display code shared with i915 xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/icl_dsi.o \ @@ -308,6 +299,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_psr.o \ i915-display/intel_qp_tables.o \ i915-display/intel_quirks.o \ + i915-display/intel_rom.o \ i915-display/intel_snps_hdmi_pll.o \ i915-display/intel_snps_phy.o \ i915-display/intel_tc.o \ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h b/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h deleted file mode 100644 index 05cbfb697b2b..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h +++ /dev/null @@ -1,6 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2024 Intel Corporation - */ - -#include "../../../i915/soc/intel_rom.h" From 1807d61541d003eee90f7661d6b40245f6966e3a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:47 +0200 Subject: [PATCH 0094/1610] drm/xe: remove remaining platform checks from compat i915_drv.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With xe no longer building anything from soc/, we can remove the compat platform checks from i915_drv.h, reducing the file to just the to_i915() pointer conversion helper. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/a9947337f81e04db342bae6af727e4f75f9818ae.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h index 3e79a74ff7de..04d1925f9a19 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h @@ -19,19 +19,4 @@ static inline struct drm_i915_private *to_i915(const struct drm_device *dev) return container_of(dev, struct drm_i915_private, drm); } -/* compat platform checks only for soc/ usage */ -#define IS_PLATFORM(xe, x) ((xe)->info.platform == x) -#define IS_I915G(dev_priv) (dev_priv && 0) -#define IS_I915GM(dev_priv) (dev_priv && 0) -#define IS_PINEVIEW(dev_priv) (dev_priv && 0) -#define IS_VALLEYVIEW(dev_priv) (dev_priv && 0) -#define IS_CHERRYVIEW(dev_priv) (dev_priv && 0) -#define IS_HASWELL(dev_priv) (dev_priv && 0) -#define IS_BROADWELL(dev_priv) (dev_priv && 0) -#define IS_BROXTON(dev_priv) (dev_priv && 0) -#define IS_GEMINILAKE(dev_priv) (dev_priv && 0) -#define IS_DG2(dev_priv) IS_PLATFORM(dev_priv, XE_DG2) - -#define IS_MOBILE(xe) (xe && 0) - #endif From eef67acfffd8debdd8c7a3f08ee759cd6bf58fbe Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:48 +0200 Subject: [PATCH 0095/1610] drm/i915/gmch: split out i915_gmch.[ch] from soc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of the soc/intel_gmch.[ch] code is i915 core specific. Split it out to i915_gmch.[ch]. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/f4f8cc931ef2a5958cebe3ca44d40aedad01626f.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_driver.c | 11 +- drivers/gpu/drm/i915/i915_gmch.c | 141 ++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_gmch.h | 13 +++ drivers/gpu/drm/i915/soc/intel_gmch.c | 132 ------------------------ drivers/gpu/drm/i915/soc/intel_gmch.h | 3 - 6 files changed, 160 insertions(+), 141 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_gmch.c create mode 100644 drivers/gpu/drm/i915/i915_gmch.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 42f2d9294142..1b169ae8f72c 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -30,6 +30,7 @@ i915-y += \ i915_edram.o \ i915_freq.o \ i915_getparam.o \ + i915_gmch.o \ i915_ioctl.o \ i915_irq.o \ i915_mitigations.o \ diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 2369e2b55096..2e837865f829 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -88,8 +88,6 @@ #include "pxp/intel_pxp_debugfs.h" #include "pxp/intel_pxp_pm.h" -#include "soc/intel_gmch.h" - #include "i915_debugfs.h" #include "i915_driver.h" #include "i915_drm_client.h" @@ -97,6 +95,7 @@ #include "i915_edram.h" #include "i915_file_private.h" #include "i915_getparam.h" +#include "i915_gmch.h" #include "i915_hwmon.h" #include "i915_ioc32.h" #include "i915_ioctl.h" @@ -323,7 +322,7 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) if (i915_inject_probe_failure(dev_priv)) return -ENODEV; - ret = intel_gmch_bridge_setup(dev_priv); + ret = i915_gmch_bridge_setup(dev_priv); if (ret < 0) return ret; @@ -340,7 +339,7 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) } /* Try to make sure MCHBAR is enabled before poking at it */ - intel_gmch_bar_setup(dev_priv); + i915_gmch_bar_setup(dev_priv); intel_device_info_runtime_init(dev_priv); intel_display_device_info_runtime_init(display); @@ -356,7 +355,7 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) return 0; err_uncore: - intel_gmch_bar_teardown(dev_priv); + i915_gmch_bar_teardown(dev_priv); return ret; } @@ -367,7 +366,7 @@ err_uncore: */ static void i915_driver_mmio_release(struct drm_i915_private *dev_priv) { - intel_gmch_bar_teardown(dev_priv); + i915_gmch_bar_teardown(dev_priv); } /** diff --git a/drivers/gpu/drm/i915/i915_gmch.c b/drivers/gpu/drm/i915/i915_gmch.c new file mode 100644 index 000000000000..2d55831b3c58 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gmch.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: MIT +/* Copyright © 2025 Intel Corporation */ + +#include + +#include +#include + +#include "i915_drv.h" +#include "i915_gmch.h" +#include "intel_pci_config.h" + +static void i915_gmch_bridge_release(struct drm_device *dev, void *bridge) +{ + pci_dev_put(bridge); +} + +int i915_gmch_bridge_setup(struct drm_i915_private *i915) +{ + int domain = pci_domain_nr(to_pci_dev(i915->drm.dev)->bus); + + i915->gmch.pdev = pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(0, 0)); + if (!i915->gmch.pdev) { + drm_err(&i915->drm, "bridge device not found\n"); + return -EIO; + } + + return drmm_add_action_or_reset(&i915->drm, i915_gmch_bridge_release, + i915->gmch.pdev); +} + +static int mchbar_reg(struct drm_i915_private *i915) +{ + return GRAPHICS_VER(i915) >= 4 ? MCHBAR_I965 : MCHBAR_I915; +} + +/* Allocate space for the MCH regs if needed, return nonzero on error */ +static int +intel_alloc_mchbar_resource(struct drm_i915_private *i915) +{ + u32 temp_lo, temp_hi = 0; + u64 mchbar_addr; + int ret; + + if (GRAPHICS_VER(i915) >= 4) + pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915) + 4, &temp_hi); + pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), &temp_lo); + mchbar_addr = ((u64)temp_hi << 32) | temp_lo; + + /* If ACPI doesn't have it, assume we need to allocate it ourselves */ + if (IS_ENABLED(CONFIG_PNP) && mchbar_addr && + pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) + return 0; + + /* Get some space for it */ + i915->gmch.mch_res.name = "i915 MCHBAR"; + i915->gmch.mch_res.flags = IORESOURCE_MEM; + ret = pci_bus_alloc_resource(i915->gmch.pdev->bus, + &i915->gmch.mch_res, + MCHBAR_SIZE, MCHBAR_SIZE, + PCIBIOS_MIN_MEM, + 0, pcibios_align_resource, + i915->gmch.pdev); + if (ret) { + drm_dbg(&i915->drm, "failed bus alloc: %d\n", ret); + i915->gmch.mch_res.start = 0; + return ret; + } + + if (GRAPHICS_VER(i915) >= 4) + pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915) + 4, + upper_32_bits(i915->gmch.mch_res.start)); + + pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915), + lower_32_bits(i915->gmch.mch_res.start)); + return 0; +} + +/* Setup MCHBAR if possible, return true if we should disable it again */ +void i915_gmch_bar_setup(struct drm_i915_private *i915) +{ + u32 temp; + bool enabled; + + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + return; + + i915->gmch.mchbar_need_disable = false; + + if (IS_I915G(i915) || IS_I915GM(i915)) { + pci_read_config_dword(i915->gmch.pdev, DEVEN, &temp); + enabled = !!(temp & DEVEN_MCHBAR_EN); + } else { + pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), &temp); + enabled = temp & 1; + } + + /* If it's already enabled, don't have to do anything */ + if (enabled) + return; + + if (intel_alloc_mchbar_resource(i915)) + return; + + i915->gmch.mchbar_need_disable = true; + + /* Space is allocated or reserved, so enable it. */ + if (IS_I915G(i915) || IS_I915GM(i915)) { + pci_write_config_dword(i915->gmch.pdev, DEVEN, + temp | DEVEN_MCHBAR_EN); + } else { + pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), &temp); + pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915), temp | 1); + } +} + +void i915_gmch_bar_teardown(struct drm_i915_private *i915) +{ + if (i915->gmch.mchbar_need_disable) { + if (IS_I915G(i915) || IS_I915GM(i915)) { + u32 deven_val; + + pci_read_config_dword(i915->gmch.pdev, DEVEN, + &deven_val); + deven_val &= ~DEVEN_MCHBAR_EN; + pci_write_config_dword(i915->gmch.pdev, DEVEN, + deven_val); + } else { + u32 mchbar_val; + + pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), + &mchbar_val); + mchbar_val &= ~1; + pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915), + mchbar_val); + } + } + + if (i915->gmch.mch_res.start) + release_resource(&i915->gmch.mch_res); +} diff --git a/drivers/gpu/drm/i915/i915_gmch.h b/drivers/gpu/drm/i915/i915_gmch.h new file mode 100644 index 000000000000..3ae50bef04ea --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gmch.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2025 Intel Corporation */ + +#ifndef __I915_GMCH_H__ +#define __I915_GMCH_H__ + +struct drm_i915_private; + +int i915_gmch_bridge_setup(struct drm_i915_private *i915); +void i915_gmch_bar_setup(struct drm_i915_private *i915); +void i915_gmch_bar_teardown(struct drm_i915_private *i915); + +#endif /* __I915_GMCH_H__ */ diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.c b/drivers/gpu/drm/i915/soc/intel_gmch.c index 271da30c8290..30f489417064 100644 --- a/drivers/gpu/drm/i915/soc/intel_gmch.c +++ b/drivers/gpu/drm/i915/soc/intel_gmch.c @@ -4,10 +4,8 @@ */ #include -#include #include -#include #include #include @@ -17,136 +15,6 @@ #include "intel_gmch.h" #include "intel_pci_config.h" -static void intel_gmch_bridge_release(struct drm_device *dev, void *bridge) -{ - pci_dev_put(bridge); -} - -int intel_gmch_bridge_setup(struct drm_i915_private *i915) -{ - int domain = pci_domain_nr(to_pci_dev(i915->drm.dev)->bus); - - i915->gmch.pdev = pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(0, 0)); - if (!i915->gmch.pdev) { - drm_err(&i915->drm, "bridge device not found\n"); - return -EIO; - } - - return drmm_add_action_or_reset(&i915->drm, intel_gmch_bridge_release, - i915->gmch.pdev); -} - -static int mchbar_reg(struct drm_i915_private *i915) -{ - return GRAPHICS_VER(i915) >= 4 ? MCHBAR_I965 : MCHBAR_I915; -} - -/* Allocate space for the MCH regs if needed, return nonzero on error */ -static int -intel_alloc_mchbar_resource(struct drm_i915_private *i915) -{ - u32 temp_lo, temp_hi = 0; - u64 mchbar_addr; - int ret; - - if (GRAPHICS_VER(i915) >= 4) - pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915) + 4, &temp_hi); - pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), &temp_lo); - mchbar_addr = ((u64)temp_hi << 32) | temp_lo; - - /* If ACPI doesn't have it, assume we need to allocate it ourselves */ - if (IS_ENABLED(CONFIG_PNP) && mchbar_addr && - pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) - return 0; - - /* Get some space for it */ - i915->gmch.mch_res.name = "i915 MCHBAR"; - i915->gmch.mch_res.flags = IORESOURCE_MEM; - ret = pci_bus_alloc_resource(i915->gmch.pdev->bus, - &i915->gmch.mch_res, - MCHBAR_SIZE, MCHBAR_SIZE, - PCIBIOS_MIN_MEM, - 0, pcibios_align_resource, - i915->gmch.pdev); - if (ret) { - drm_dbg(&i915->drm, "failed bus alloc: %d\n", ret); - i915->gmch.mch_res.start = 0; - return ret; - } - - if (GRAPHICS_VER(i915) >= 4) - pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915) + 4, - upper_32_bits(i915->gmch.mch_res.start)); - - pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915), - lower_32_bits(i915->gmch.mch_res.start)); - return 0; -} - -/* Setup MCHBAR if possible, return true if we should disable it again */ -void intel_gmch_bar_setup(struct drm_i915_private *i915) -{ - u32 temp; - bool enabled; - - if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) - return; - - i915->gmch.mchbar_need_disable = false; - - if (IS_I915G(i915) || IS_I915GM(i915)) { - pci_read_config_dword(i915->gmch.pdev, DEVEN, &temp); - enabled = !!(temp & DEVEN_MCHBAR_EN); - } else { - pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), &temp); - enabled = temp & 1; - } - - /* If it's already enabled, don't have to do anything */ - if (enabled) - return; - - if (intel_alloc_mchbar_resource(i915)) - return; - - i915->gmch.mchbar_need_disable = true; - - /* Space is allocated or reserved, so enable it. */ - if (IS_I915G(i915) || IS_I915GM(i915)) { - pci_write_config_dword(i915->gmch.pdev, DEVEN, - temp | DEVEN_MCHBAR_EN); - } else { - pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), &temp); - pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915), temp | 1); - } -} - -void intel_gmch_bar_teardown(struct drm_i915_private *i915) -{ - if (i915->gmch.mchbar_need_disable) { - if (IS_I915G(i915) || IS_I915GM(i915)) { - u32 deven_val; - - pci_read_config_dword(i915->gmch.pdev, DEVEN, - &deven_val); - deven_val &= ~DEVEN_MCHBAR_EN; - pci_write_config_dword(i915->gmch.pdev, DEVEN, - deven_val); - } else { - u32 mchbar_val; - - pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), - &mchbar_val); - mchbar_val &= ~1; - pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915), - mchbar_val); - } - } - - if (i915->gmch.mch_res.start) - release_resource(&i915->gmch.mch_res); -} - int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode) { struct intel_display *display = i915->display; diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.h b/drivers/gpu/drm/i915/soc/intel_gmch.h index 23be2d113afd..907e1ae921e0 100644 --- a/drivers/gpu/drm/i915/soc/intel_gmch.h +++ b/drivers/gpu/drm/i915/soc/intel_gmch.h @@ -11,9 +11,6 @@ struct pci_dev; struct drm_i915_private; -int intel_gmch_bridge_setup(struct drm_i915_private *i915); -void intel_gmch_bar_setup(struct drm_i915_private *i915); -void intel_gmch_bar_teardown(struct drm_i915_private *i915); int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode); unsigned int intel_gmch_vga_set_decode(struct pci_dev *pdev, bool enable_decode); From 3018e582da321c5f6d2f03847f9adb44e44cb0ee Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:49 +0200 Subject: [PATCH 0096/1610] drm/i915/gmch: switch to use pci_bus_{read,write}_config_word() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to use pci_bus_{read,write}_config_word(), and stop using i915->gmch.pdev reference for the bridge. Suggested-by: Ville Syrjälä Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/5c432540e254108bf73dbdec347d69ad87682fc9.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/soc/intel_gmch.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.c b/drivers/gpu/drm/i915/soc/intel_gmch.c index 30f489417064..d43b5d89cae7 100644 --- a/drivers/gpu/drm/i915/soc/intel_gmch.c +++ b/drivers/gpu/drm/i915/soc/intel_gmch.c @@ -18,10 +18,11 @@ int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode) { struct intel_display *display = i915->display; + struct pci_dev *pdev = to_pci_dev(display->drm->dev); unsigned int reg = DISPLAY_VER(display) >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL; u16 gmch_ctrl; - if (pci_read_config_word(i915->gmch.pdev, reg, &gmch_ctrl)) { + if (pci_bus_read_config_word(pdev->bus, PCI_DEVFN(0, 0), reg, &gmch_ctrl)) { drm_err(&i915->drm, "failed to read control word\n"); return -EIO; } @@ -34,7 +35,7 @@ int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode) else gmch_ctrl |= INTEL_GMCH_VGA_DISABLE; - if (pci_write_config_word(i915->gmch.pdev, reg, gmch_ctrl)) { + if (pci_bus_write_config_word(pdev->bus, PCI_DEVFN(0, 0), reg, gmch_ctrl)) { drm_err(&i915->drm, "failed to write control word\n"); return -EIO; } From fff15f68eb06af4a77e349d419717bc9a2f4b37b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:50 +0200 Subject: [PATCH 0097/1610] drm/i915/gmch: convert intel_gmch.c to struct intel_display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert intel_gmch.[ch] to struct intel_display. Remove the final dependency on struct drm_i915_private and i915_drv.h. This is in preparation of moving the code under display/. intel_gmch_vga_set_state() is only used internally, make it static while at it. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/a4b317656eef0781d4f53ae337083fb05ce602bc.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/soc/intel_gmch.c | 13 ++++++------- drivers/gpu/drm/i915/soc/intel_gmch.h | 2 -- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.c b/drivers/gpu/drm/i915/soc/intel_gmch.c index d43b5d89cae7..4e7abe056551 100644 --- a/drivers/gpu/drm/i915/soc/intel_gmch.c +++ b/drivers/gpu/drm/i915/soc/intel_gmch.c @@ -10,20 +10,19 @@ #include #include "../display/intel_display_core.h" /* FIXME */ +#include "../display/intel_display_types.h" /* FIXME */ -#include "i915_drv.h" #include "intel_gmch.h" #include "intel_pci_config.h" -int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode) +static int intel_gmch_vga_set_state(struct intel_display *display, bool enable_decode) { - struct intel_display *display = i915->display; struct pci_dev *pdev = to_pci_dev(display->drm->dev); unsigned int reg = DISPLAY_VER(display) >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL; u16 gmch_ctrl; if (pci_bus_read_config_word(pdev->bus, PCI_DEVFN(0, 0), reg, &gmch_ctrl)) { - drm_err(&i915->drm, "failed to read control word\n"); + drm_err(display->drm, "failed to read control word\n"); return -EIO; } @@ -36,7 +35,7 @@ int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode) gmch_ctrl |= INTEL_GMCH_VGA_DISABLE; if (pci_bus_write_config_word(pdev->bus, PCI_DEVFN(0, 0), reg, gmch_ctrl)) { - drm_err(&i915->drm, "failed to write control word\n"); + drm_err(display->drm, "failed to write control word\n"); return -EIO; } @@ -45,9 +44,9 @@ int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode) unsigned int intel_gmch_vga_set_decode(struct pci_dev *pdev, bool enable_decode) { - struct drm_i915_private *i915 = pdev_to_i915(pdev); + struct intel_display *display = to_intel_display(pdev); - intel_gmch_vga_set_state(i915, enable_decode); + intel_gmch_vga_set_state(display, enable_decode); if (enable_decode) return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.h b/drivers/gpu/drm/i915/soc/intel_gmch.h index 907e1ae921e0..bc3421ab5ba6 100644 --- a/drivers/gpu/drm/i915/soc/intel_gmch.h +++ b/drivers/gpu/drm/i915/soc/intel_gmch.h @@ -9,9 +9,7 @@ #include struct pci_dev; -struct drm_i915_private; -int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode); unsigned int intel_gmch_vga_set_decode(struct pci_dev *pdev, bool enable_decode); #endif /* __INTEL_GMCH_H__ */ From aa4dc3eeff6d5c47ed08905e5cf7b9b77a646fea Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:51 +0200 Subject: [PATCH 0098/1610] drm/i915: merge soc/intel_gmch.[ch] to display/intel_vga.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sole user of the remaining functions in intel_gmch.[ch] is in intel_vga.c. Move everything there. Since intel_gmch.c hasn't been part of xe, use a dummy function relocated from xe_display_misc.c, with #ifdef. This is purely to keep this change non-functional. This allows us to remove soc/intel_gmch.[ch] from i915, compat soc/intel_gmch.h from xe, and xe_display_misc.c from xe. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/b0f853ad7eae686738defa9e8f08a8848df8f226.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 4 -- drivers/gpu/drm/i915/display/intel_vga.c | 52 ++++++++++++++++- drivers/gpu/drm/i915/soc/intel_gmch.c | 56 ------------------- drivers/gpu/drm/i915/soc/intel_gmch.h | 15 ----- drivers/gpu/drm/xe/Makefile | 1 - .../xe/compat-i915-headers/soc/intel_gmch.h | 6 -- drivers/gpu/drm/xe/display/xe_display_misc.c | 16 ------ 7 files changed, 50 insertions(+), 100 deletions(-) delete mode 100644 drivers/gpu/drm/i915/soc/intel_gmch.c delete mode 100644 drivers/gpu/drm/i915/soc/intel_gmch.h delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/soc/intel_gmch.h delete mode 100644 drivers/gpu/drm/xe/display/xe_display_misc.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 1b169ae8f72c..83d70038c337 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -57,10 +57,6 @@ i915-y += \ vlv_iosf_sb.o \ vlv_suspend.o -# core peripheral code -i915-y += \ - soc/intel_gmch.o - # core library code i915-y += \ i915_memcpy.o \ diff --git a/drivers/gpu/drm/i915/display/intel_vga.c b/drivers/gpu/drm/i915/display/intel_vga.c index 6e125564db34..5e516c79e2f7 100644 --- a/drivers/gpu/drm/i915/display/intel_vga.c +++ b/drivers/gpu/drm/i915/display/intel_vga.c @@ -9,12 +9,12 @@ #include #include +#include #include