From: Greg Kroah-Hartman Date: Wed, 29 Jul 2026 10:54:26 +0000 (+0200) Subject: 7.1-stable patches X-Git-Tag: v6.1.179~75 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=d02c78a1fe32b4c23ecdf785cff28cb6b48c3462;p=thirdparty%2Fkernel%2Fstable-queue.git 7.1-stable patches added patches: drm-amd-display-restore-periodic-detection-for-dcn35.patch drm-amdgpu-fix-amdgpu_bo_move-when-old_mem-and-new_mem-are-both-gtt.patch drm-amdgpu-fix-context-pstate-override-handling.patch drm-amdgpu-gfx9-fix-ring-and-ib-test-fail-after-mode2.patch drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch drm-amdgpu-validate-cp_gfx_shadow-chunk-size-in-cs-pass1.patch drm-amdkfd-use-exclusive-bounds-for-svm-split-alignment-checks.patch drm-displayid-fix-tiled-display-topology-id-size.patch drm-i915-gem-add-missing-nospec-on-parallel-submit-slot.patch drm-i915-mtl-enable-pps-before-pll.patch drm-nouveau-acr-fix-missing-nvkm_done-in-error-path-of-nvkm_acr_oneinit.patch drm-nouveau-fix-reversed-error-cleanup-order-in-ucopy-functions.patch drm-radeon-fix-r100_copy_blit-for-large-bos.patch drm-sysfb-avoid-possible-truncation-with-calculating-visible-size.patch drm-sysfb-avoid-truncating-maximum-stride.patch drm-sysfb-do-not-page-align-visible-size-of-the-framebuffer.patch drm-sysfb-return-errno-code-from-drm_sysfb_get_visible_size.patch drm-xe-add-compact-pt-and-addr-mask-handling-for-page-reclaim.patch drm-xe-display-skip-force_wc-and-vm_bound-check-for-external-dma-bufs.patch drm-xe-guc-fix-buffer-overflow-in-steered-register-list-allocation.patch --- diff --git a/queue-7.1/drm-amd-display-restore-periodic-detection-for-dcn35.patch b/queue-7.1/drm-amd-display-restore-periodic-detection-for-dcn35.patch new file mode 100644 index 0000000000..6c25a5b4ee --- /dev/null +++ b/queue-7.1/drm-amd-display-restore-periodic-detection-for-dcn35.patch @@ -0,0 +1,92 @@ +From 5cc0f35d83e2c72f70edaf7478db350af3082a17 Mon Sep 17 00:00:00 2001 +From: Ivan Lipski +Date: Thu, 28 May 2026 12:28:51 -0400 +Subject: drm/amd/display: Restore periodic detection for DCN35 + +From: Ivan Lipski + +commit 5cc0f35d83e2c72f70edaf7478db350af3082a17 upstream. + +[Why&How] +Periodic detection callbacks from DCN35 was removed for higher IPS +residency causing some displays to fail to recover after DPMS sleep. The +monitors bounces HPD ~1.2s after link training, and without periodic +detection the system enters IPS with no mechanism to wake and rediscover +the display. + +Restore the periodic detection calls in dcn35_clk_mgr for now. It should +be replaced with a proper IPS-aware solution long term using DMUB. + +Also remove it from dcn31 and dcn314_clk_mgr.c since they do not have IPS, +thus should not affect them. + +Fixes: 3f6c060846be ("drm/amd/display: Remove periodic detection callbacks from dcn35+") +Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/5318 +Reviewed-by: Nicholas Kazlauskas +Signed-off-by: Ivan Lipski +Signed-off-by: Aurabindo Pillai +Tested-by: Dan Wheeler +Signed-off-by: Alex Deucher +(cherry picked from commit 0c300e6a76916e944b6b18a64c73f7895a0fee87) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 2 -- + drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c | 2 -- + drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 2 ++ + 3 files changed, 2 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +@@ -155,7 +155,6 @@ void dcn31_update_clocks(struct clk_mgr + if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW && + new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) { + dcn31_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support); +- dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true); + clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; + } + +@@ -181,7 +180,6 @@ void dcn31_update_clocks(struct clk_mgr + if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW && + new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) { + dcn31_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW); +- dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false); + clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; + } + +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c +@@ -227,7 +227,6 @@ void dcn314_update_clocks(struct clk_mgr + if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW && + new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) { + dcn314_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support); +- dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true); + clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; + } + +@@ -252,7 +251,6 @@ void dcn314_update_clocks(struct clk_mgr + if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW && + new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) { + dcn314_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW); +- dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false); + clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; + } + +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +@@ -405,6 +405,7 @@ void dcn35_update_clocks(struct clk_mgr + if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW && + new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) { + dcn35_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support); ++ dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true); + clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; + } + +@@ -424,6 +425,7 @@ void dcn35_update_clocks(struct clk_mgr + if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW && + new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) { + dcn35_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW); ++ dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false); + clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; + } + diff --git a/queue-7.1/drm-amdgpu-fix-amdgpu_bo_move-when-old_mem-and-new_mem-are-both-gtt.patch b/queue-7.1/drm-amdgpu-fix-amdgpu_bo_move-when-old_mem-and-new_mem-are-both-gtt.patch new file mode 100644 index 0000000000..acf29011c3 --- /dev/null +++ b/queue-7.1/drm-amdgpu-fix-amdgpu_bo_move-when-old_mem-and-new_mem-are-both-gtt.patch @@ -0,0 +1,60 @@ +From ee94a65f192c05c543b4d3ad7137cd696b5c18fc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timur=20Krist=C3=B3f?= +Date: Mon, 25 May 2026 13:33:18 +0200 +Subject: drm/amdgpu: Fix amdgpu_bo_move() when old_mem and new_mem are both GTT +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Timur Kristóf + +commit ee94a65f192c05c543b4d3ad7137cd696b5c18fc upstream. + +The UVD code relies on GTT to GTT moves in order to ensure +that its BOs don't cross 256M segments. + +Fixes: bfe5e585b44f ("drm/ttm: move last binding into the drivers.") +Signed-off-by: Timur Kristóf +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +(cherry picked from commit 21fd45e5e2628d00b478590bcc3d14d3de5d45b6) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +@@ -515,6 +515,15 @@ static int amdgpu_bo_move(struct ttm_buf + + if (new_mem->mem_type == TTM_PL_TT || + new_mem->mem_type == AMDGPU_PL_PREEMPT) { ++ if (old_mem && (old_mem->mem_type == TTM_PL_TT || ++ old_mem->mem_type == AMDGPU_PL_PREEMPT)) { ++ r = ttm_bo_wait_ctx(bo, ctx); ++ if (r) ++ return r; ++ ++ amdgpu_ttm_backend_unbind(bo->bdev, bo->ttm); ++ } ++ + r = amdgpu_ttm_backend_bind(bo->bdev, bo->ttm, new_mem); + if (r) + return r; +@@ -547,6 +556,15 @@ static int amdgpu_bo_move(struct ttm_buf + amdgpu_bo_move_notify(bo, evict, new_mem); + ttm_resource_free(bo, &bo->resource); + ttm_bo_assign_mem(bo, new_mem); ++ return 0; ++ } ++ if ((old_mem->mem_type == TTM_PL_TT || ++ old_mem->mem_type == AMDGPU_PL_PREEMPT) && ++ (new_mem->mem_type == TTM_PL_TT || ++ new_mem->mem_type == AMDGPU_PL_PREEMPT)) { ++ amdgpu_bo_move_notify(bo, evict, new_mem); ++ ttm_resource_free(bo, &bo->resource); ++ ttm_bo_assign_mem(bo, new_mem); + return 0; + } + diff --git a/queue-7.1/drm-amdgpu-fix-context-pstate-override-handling.patch b/queue-7.1/drm-amdgpu-fix-context-pstate-override-handling.patch new file mode 100644 index 0000000000..0164f03d34 --- /dev/null +++ b/queue-7.1/drm-amdgpu-fix-context-pstate-override-handling.patch @@ -0,0 +1,163 @@ +From c1dc4ccb82c9e56325d8e7514ca4c90bd1efb351 Mon Sep 17 00:00:00 2001 +From: Tvrtko Ursulin +Date: Mon, 1 Jun 2026 15:08:22 +0100 +Subject: drm/amdgpu: Fix context pstate override handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Tvrtko Ursulin + +commit c1dc4ccb82c9e56325d8e7514ca4c90bd1efb351 upstream. + +There are several problems in the context pstate handling code. + +The most serious ones are potential use-after-free and NULL pointer +dereferences at context initialization time. Both are due +amdgpu_ctx_init() not holding the adev->pm.stable_pstate_ctx_lock, which +is otherwise used from both sysfs and the context code itself for +modifying and clearing the stored context pointer. + +Second issue is that context fini can trample over the pstate +configuration set via sysfs. This is due the restore state +(ctx->stable_pstate) being saved at context init time, and not if, or when +the context actually changes the pstate. As the context exits it will +therefore incorrectly restore to what was set before the sysfs override +was requested. + +The simplest fix is to drastically simplify how the state is tracked, by +clearly defining the points at which pstate ownership is taken and +released, and to handle all transitions under the correct lock. + +Instead of at context init time, the previous state is saved only at the +point the context overrides the current state, and is restored on context +exit only if the context is still the owner of the current override state. + +Signed-off-by: Tvrtko Ursulin +Fixes: 79610d304133 ("drm/amdgpu: fix pstate setting issue") +Cc: Chengming Gui +Cc: Alex Deucher +Cc: "Christian König" +Signed-off-by: Alex Deucher +(cherry picked from commit 1b5e413713c0a93bc1818394d0ce49aaad21bd27) +Cc: # v6.1+ +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 71 ++++++++++++++++++-------------- + 1 file changed, 42 insertions(+), 29 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +@@ -326,7 +326,6 @@ static int amdgpu_ctx_init(struct amdgpu + struct drm_file *filp, struct amdgpu_ctx *ctx) + { + struct amdgpu_fpriv *fpriv = filp->driver_priv; +- u32 current_stable_pstate; + int r; + + r = amdgpu_ctx_priority_permit(filp, priority); +@@ -344,36 +343,21 @@ static int amdgpu_ctx_init(struct amdgpu + ctx->generation = amdgpu_vm_generation(mgr->adev, &fpriv->vm); + ctx->init_priority = priority; + ctx->override_priority = AMDGPU_CTX_PRIORITY_UNSET; +- +- r = amdgpu_ctx_get_stable_pstate(ctx, ¤t_stable_pstate); +- if (r) +- return r; +- +- if (mgr->adev->pm.stable_pstate_ctx) +- ctx->stable_pstate = mgr->adev->pm.stable_pstate_ctx->stable_pstate; +- else +- ctx->stable_pstate = current_stable_pstate; ++ ctx->stable_pstate = AMDGPU_CTX_STABLE_PSTATE_NONE; + + return 0; + } + +-static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx, +- u32 stable_pstate) ++static int __amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx, ++ u32 stable_pstate) + { + struct amdgpu_device *adev = ctx->mgr->adev; + enum amd_dpm_forced_level level; ++ struct amdgpu_ctx *current_ctx; + u32 current_stable_pstate; +- int r; +- +- mutex_lock(&adev->pm.stable_pstate_ctx_lock); +- if (adev->pm.stable_pstate_ctx && adev->pm.stable_pstate_ctx != ctx) { +- r = -EBUSY; +- goto done; +- } ++ int r = 0; + +- r = amdgpu_ctx_get_stable_pstate(ctx, ¤t_stable_pstate); +- if (r || (stable_pstate == current_stable_pstate)) +- goto done; ++ lockdep_assert_held(&adev->pm.stable_pstate_ctx_lock); + + switch (stable_pstate) { + case AMDGPU_CTX_STABLE_PSTATE_NONE: +@@ -392,17 +376,41 @@ static int amdgpu_ctx_set_stable_pstate( + level = AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; + break; + default: +- r = -EINVAL; +- goto done; ++ return -EINVAL; + } + ++ current_ctx = adev->pm.stable_pstate_ctx; ++ if (current_ctx && current_ctx != ctx) ++ return -EBUSY; ++ ++ r = amdgpu_ctx_get_stable_pstate(ctx, ¤t_stable_pstate); ++ if (r || current_stable_pstate == stable_pstate) ++ return r; ++ + r = amdgpu_dpm_force_performance_level(adev, level); ++ if (r) ++ return r; + +- if (level == AMD_DPM_FORCED_LEVEL_AUTO) +- adev->pm.stable_pstate_ctx = NULL; +- else ++ if (!current_ctx) { + adev->pm.stable_pstate_ctx = ctx; +-done: ++ /* ++ * Serialized by context taking ownership for the first time ++ * while holding adev->pm.stable_pstate_ctx_lock). ++ */ ++ WRITE_ONCE(ctx->stable_pstate, current_stable_pstate); ++ } ++ ++ return 0; ++} ++ ++static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx, ++ u32 stable_pstate) ++{ ++ struct amdgpu_device *adev = ctx->mgr->adev; ++ int r; ++ ++ mutex_lock(&adev->pm.stable_pstate_ctx_lock); ++ r = __amdgpu_ctx_set_stable_pstate(ctx, stable_pstate); + mutex_unlock(&adev->pm.stable_pstate_ctx_lock); + + return r; +@@ -428,7 +436,12 @@ static void amdgpu_ctx_fini(struct kref + } + + if (drm_dev_enter(adev_to_drm(adev), &idx)) { +- amdgpu_ctx_set_stable_pstate(ctx, ctx->stable_pstate); ++ mutex_lock(&adev->pm.stable_pstate_ctx_lock); ++ if (adev->pm.stable_pstate_ctx == ctx) { ++ __amdgpu_ctx_set_stable_pstate(ctx, ctx->stable_pstate); ++ adev->pm.stable_pstate_ctx = NULL; ++ } ++ mutex_unlock(&adev->pm.stable_pstate_ctx_lock); + drm_dev_exit(idx); + } + diff --git a/queue-7.1/drm-amdgpu-gfx9-fix-ring-and-ib-test-fail-after-mode2.patch b/queue-7.1/drm-amdgpu-gfx9-fix-ring-and-ib-test-fail-after-mode2.patch new file mode 100644 index 0000000000..b2a7011392 --- /dev/null +++ b/queue-7.1/drm-amdgpu-gfx9-fix-ring-and-ib-test-fail-after-mode2.patch @@ -0,0 +1,97 @@ +From 85ed06d990ff73212b5a91a406671cabd962e521 Mon Sep 17 00:00:00 2001 +From: Jiqian Chen +Date: Thu, 4 Jun 2026 18:30:23 +0800 +Subject: drm/amdgpu/gfx9: Fix Ring and IB test fail after mode2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jiqian Chen + +commit 85ed06d990ff73212b5a91a406671cabd962e521 upstream. + +For Renior APU with gfx9, in some test scenarios with disabling +ring_reset, like accessing an unmapped invalid address, it can +trigger a gpu job timeout event, then driver uses Mode2 reset +to reset GPU, but after Mode2 compute Ring test and IB test fail +randomly. It because the HQDs of MECs are always active before or +after Mode2, that causes MECs use stale HQDs when MECs are unhalted +before driver restore MQDs, and causes CPC and CPF are still stuck +after Mode2, then causes compute Ring and IB tests fail. + +So, add sequences to deactivate HQDs of MECs in suspend IP function +of the resetting process. + +v2: Move all sequences into a new function gfx_v9_0_cp_mode2_clear_state (Ray Huang) + To check reset Mode2 method in the if condition (Ray Huang) +v3: Move all sequences before Mode2 instead of after Mode2 (Timur Kristóf) +v4: Call amdgpu_gfx_rlc_enter/exit_safe_mode int the begin and end of + gfx_v9_0_deactivate_kcq_hqd (Alex Deucher) + +Signed-off-by: Jiqian Chen +Reviewed-by: Huang Rui +Reviewed-by: Timur Kristóf +Reviewed-by: Alex Deucher +Signed-off-by: Alex Deucher +(cherry picked from commit c3988a7ad4799514447294f04f063b422e0551df) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 39 ++++++++++++++++++++++++++++++++++ + 1 file changed, 39 insertions(+) + +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +@@ -4049,6 +4049,41 @@ static int gfx_v9_0_hw_init(struct amdgp + return r; + } + ++static void gfx_v9_0_deactivate_kcq_hqd(struct amdgpu_device *adev) ++{ ++ amdgpu_gfx_rlc_enter_safe_mode(adev, 0); ++ for (int i = 0; i < adev->gfx.num_compute_rings; i++) { ++ u32 tmp; ++ struct amdgpu_ring *ring = &adev->gfx.compute_ring[i]; ++ ++ mutex_lock(&adev->srbm_mutex); ++ soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0, 0); ++ tmp = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE); ++ /* disable the queue if it's active */ ++ if (tmp & CP_HQD_ACTIVE__ACTIVE_MASK) { ++ int j; ++ ++ WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST, 1); ++ for (j = 0; j < adev->usec_timeout; j++) { ++ tmp = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE); ++ if (!(tmp & CP_HQD_ACTIVE__ACTIVE_MASK)) ++ break; ++ udelay(1); ++ } ++ if (j == AMDGPU_MAX_USEC_TIMEOUT) { ++ DRM_DEBUG("comp_%u_%u_%u dequeue request failed.\n", ++ ring->me, ring->pipe, ring->queue); ++ /* Manual disable if dequeue request times out */ ++ WREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE, 0); ++ } ++ WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST, 0); ++ } ++ soc15_grbm_select(adev, 0, 0, 0, 0, 0); ++ mutex_unlock(&adev->srbm_mutex); ++ } ++ amdgpu_gfx_rlc_exit_safe_mode(adev, 0); ++} ++ + static int gfx_v9_0_hw_fini(struct amdgpu_ip_block *ip_block) + { + struct amdgpu_device *adev = ip_block->adev; +@@ -4075,6 +4110,10 @@ static int gfx_v9_0_hw_fini(struct amdgp + return 0; + } + ++ if ((adev->flags & AMD_IS_APU) && amdgpu_in_reset(adev) && ++ amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_MODE2) ++ gfx_v9_0_deactivate_kcq_hqd(adev); ++ + /* Use deinitialize sequence from CAIL when unbinding device from driver, + * otherwise KIQ is hanging when binding back + */ diff --git a/queue-7.1/drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch b/queue-7.1/drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch new file mode 100644 index 0000000000..ac3edd4e49 --- /dev/null +++ b/queue-7.1/drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch @@ -0,0 +1,74 @@ +From 8882f8897e554053af9e72f4c2da8b1e2cce56c7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timur=20Krist=C3=B3f?= +Date: Mon, 25 May 2026 13:33:17 +0200 +Subject: drm/amdgpu: Respect placement requirements in amdgpu_gtt_mgr functions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Timur Kristóf + +commit 8882f8897e554053af9e72f4c2da8b1e2cce56c7 upstream. + +When testing intersection and compatibility, respect +the actual placement requirements. This is a pre-requisite +for ensuring that UVD CS BOs do not cross 256M segments. + +Fixes: ded910f368a5 ("drm/amdgpu: Implement intersect/compatible functions") +Suggested-by: Christian König +Signed-off-by: Timur Kristóf +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +(cherry picked from commit bc06579ca29dee9c245a41b12e39c7bb6938af5d) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 30 ++++++++++++++++++++++++++-- + 1 file changed, 28 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +@@ -272,7 +272,20 @@ static bool amdgpu_gtt_mgr_intersects(st + const struct ttm_place *place, + size_t size) + { +- return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res); ++ const struct drm_mm_node *const node = &to_ttm_range_mgr_node(res)->mm_nodes[0]; ++ const u32 num_pages = PFN_UP(size); ++ ++ if (!place->lpfn) ++ return true; ++ ++ if (!amdgpu_gtt_mgr_has_gart_addr(res)) ++ return false; ++ ++ if (place->fpfn >= (node->start + num_pages) || ++ (place->lpfn && place->lpfn <= node->start)) ++ return false; ++ ++ return true; + } + + /** +@@ -290,7 +303,20 @@ static bool amdgpu_gtt_mgr_compatible(st + const struct ttm_place *place, + size_t size) + { +- return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res); ++ const struct drm_mm_node *const node = &to_ttm_range_mgr_node(res)->mm_nodes[0]; ++ const u32 num_pages = PFN_UP(size); ++ ++ if (!place->lpfn) ++ return true; ++ ++ if (!amdgpu_gtt_mgr_has_gart_addr(res)) ++ return false; ++ ++ if (node->start < place->fpfn || ++ (place->lpfn && (node->start + num_pages) > place->lpfn)) ++ return false; ++ ++ return true; + } + + /** diff --git a/queue-7.1/drm-amdgpu-validate-cp_gfx_shadow-chunk-size-in-cs-pass1.patch b/queue-7.1/drm-amdgpu-validate-cp_gfx_shadow-chunk-size-in-cs-pass1.patch new file mode 100644 index 0000000000..f5bf37d816 --- /dev/null +++ b/queue-7.1/drm-amdgpu-validate-cp_gfx_shadow-chunk-size-in-cs-pass1.patch @@ -0,0 +1,57 @@ +From 84c4c36acd5c4b2558b5069f869a165b2c655c84 Mon Sep 17 00:00:00 2001 +From: Mario Limonciello +Date: Fri, 12 Jun 2026 21:07:24 -0500 +Subject: drm/amdgpu: validate CP_GFX_SHADOW chunk size in CS pass1 + +From: Mario Limonciello + +commit 84c4c36acd5c4b2558b5069f869a165b2c655c84 upstream. + +Add a minimum-length check for the AMDGPU_CHUNK_ID_CP_GFX_SHADOW chunk in +amdgpu_cs_pass1(), matching the gate already present for the IB, FENCE and +BO_HANDLES chunk types. + +The CP_GFX_SHADOW case previously shared a bare break with the dependency +and syncobj chunk types, which do not dereference a fixed-size struct. When +userspace submits this chunk with length_dw == 0, vmemdup_array_user() is +called with size 0 and returns ZERO_SIZE_PTR, which passes the IS_ERR() +check. amdgpu_cs_p2_shadow() then dereferences chunk->kdata as a struct +drm_amdgpu_cs_chunk_cp_gfx_shadow (reading shadow->flags), faulting on the +ZERO_SIZE_PTR and causing a NULL-pointer dereference. + +This is reachable by an unprivileged process in the render group. Reject +undersized chunks with -EINVAL during pass1 so the bad submission is +rejected before pass2 ever dereferences the data. + +Fixes: ac9287055ff1 ("drm/amdgpu: add gfx shadow CS IOCTL support") +Reviewed-by: Alex Deucher +Signed-off-by: Mario Limonciello +Signed-off-by: Alex Deucher +(cherry picked from commit 7f61b2eef7415eccdb40850aca0de94211948657) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +@@ -252,13 +252,17 @@ static int amdgpu_cs_pass1(struct amdgpu + goto free_partial_kdata; + break; + ++ case AMDGPU_CHUNK_ID_CP_GFX_SHADOW: ++ if (size < sizeof(struct drm_amdgpu_cs_chunk_cp_gfx_shadow)) ++ goto free_partial_kdata; ++ break; ++ + case AMDGPU_CHUNK_ID_DEPENDENCIES: + case AMDGPU_CHUNK_ID_SYNCOBJ_IN: + case AMDGPU_CHUNK_ID_SYNCOBJ_OUT: + case AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES: + case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT: + case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL: +- case AMDGPU_CHUNK_ID_CP_GFX_SHADOW: + break; + + default: diff --git a/queue-7.1/drm-amdkfd-use-exclusive-bounds-for-svm-split-alignment-checks.patch b/queue-7.1/drm-amdkfd-use-exclusive-bounds-for-svm-split-alignment-checks.patch new file mode 100644 index 0000000000..7d02f80c91 --- /dev/null +++ b/queue-7.1/drm-amdkfd-use-exclusive-bounds-for-svm-split-alignment-checks.patch @@ -0,0 +1,84 @@ +From b89d58b6595d79dc3fe75e213e1f4c5efd0251d4 Mon Sep 17 00:00:00 2001 +From: Gerhard Schwanzer +Date: Tue, 16 Jun 2026 10:56:06 +0000 +Subject: drm/amdkfd: Use exclusive bounds for SVM split alignment checks + +From: Gerhard Schwanzer + +commit b89d58b6595d79dc3fe75e213e1f4c5efd0251d4 upstream. + +SVM ranges use inclusive page indices: prange->last is the last page in +the range. The split-remap logic introduced by commit 448ee45353ef +("drm/amdkfd: Use huge page size to check split svm range alignment") +uses ALIGN_DOWN(prange->last, 512) to determine whether the original +range can contain a 2MB huge-page mapping. + +That aligns the last page itself down. Thus a range ending one page +before the next 2MB boundary is classified as if the final 2MB block did +not exist. When such a range is split inside that final block, the +split head or tail can be left off the remap list even though it was +derived from an original range that may have PMD mappings. + +Use prange->last + 1 as the exclusive upper bound when computing the +original range's last 2MB-aligned boundary. Then use the actual split +boundary for the head and tail alignment checks: tail->start for a tail +split, and new_start for a head split. new_start is equivalent to +head->last + 1 and directly names the exclusive end of the split head. + +Using head->last for the head-side check can both remap a head that ends +exactly one page before a 2MB boundary and miss a head whose split +boundary is one page after such a boundary. Philip Yang pointed out in +the review of the original change that this condition should use +head->last + 1 or new_start. + +Xiaogang Chen identified the inclusive-last cause and posted the +candidate fix in the regression thread. With the culprit change active +and the local revert not applied, the unchanged C/HSA reproducer +completes 10/10 runs with this change on an RX 7600 XT. + +Fixes: 448ee45353ef ("drm/amdkfd: Use huge page size to check split svm range alignment") +Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/4914 +Link: https://lore.kernel.org/stable/IA1PR12MB85172F7FE9157C092EDA46A0E3112@IA1PR12MB8517.namprd12.prod.outlook.com/ +Link: https://lore.kernel.org/all/32ce2b72-aa16-4202-9f99-92e3cd4408bc@amd.com/ +Suggested-by: Xiaogang Chen +Acked-by: Alex Deucher +Signed-off-by: Gerhard Schwanzer +Signed-off-by: Alex Deucher +(cherry picked from commit a60ea15807126b148a328051636977a33ad0e9bb) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +@@ -1144,7 +1144,7 @@ static int + svm_range_split_tail(struct svm_range *prange, uint64_t new_last, + struct list_head *insert_list, struct list_head *remap_list) + { +- unsigned long last_align_down = ALIGN_DOWN(prange->last, 512); ++ unsigned long last_align_down = ALIGN_DOWN(prange->last + 1, 512); + unsigned long start_align = ALIGN(prange->start, 512); + bool huge_page_mapping = last_align_down > start_align; + struct svm_range *tail = NULL; +@@ -1168,7 +1168,7 @@ static int + svm_range_split_head(struct svm_range *prange, uint64_t new_start, + struct list_head *insert_list, struct list_head *remap_list) + { +- unsigned long last_align_down = ALIGN_DOWN(prange->last, 512); ++ unsigned long last_align_down = ALIGN_DOWN(prange->last + 1, 512); + unsigned long start_align = ALIGN(prange->start, 512); + bool huge_page_mapping = last_align_down > start_align; + struct svm_range *head = NULL; +@@ -1181,8 +1181,8 @@ svm_range_split_head(struct svm_range *p + + list_add(&head->list, insert_list); + +- if (huge_page_mapping && head->last + 1 > start_align && +- head->last + 1 < last_align_down && (!IS_ALIGNED(head->last, 512))) ++ if (huge_page_mapping && new_start > start_align && ++ new_start < last_align_down && !IS_ALIGNED(new_start, 512)) + list_add(&head->update_list, remap_list); + + return 0; diff --git a/queue-7.1/drm-displayid-fix-tiled-display-topology-id-size.patch b/queue-7.1/drm-displayid-fix-tiled-display-topology-id-size.patch new file mode 100644 index 0000000000..1342adc81d --- /dev/null +++ b/queue-7.1/drm-displayid-fix-tiled-display-topology-id-size.patch @@ -0,0 +1,129 @@ +From 90c0486a82e27393f9eaf3bb350f51a0bd38cb6b Mon Sep 17 00:00:00 2001 +From: Jani Nikula +Date: Wed, 10 Jun 2026 17:15:49 +0300 +Subject: drm/displayid: fix Tiled Display Topology ID size + +From: Jani Nikula + +commit 90c0486a82e27393f9eaf3bb350f51a0bd38cb6b upstream. + +The Tiled Display Topology ID of a DisplayID Tiled Display Topology Data +Block consists of three fields: + +- Tiled Display Manufacturer/Vendor ID Field (3 bytes) +- Tiled Display Product ID Code Field (2 bytes) +- Tiled Display Serial Number Field (4 bytes) + +i.e. a total of 9 bytes, not 8. + +The DisplayID Tiled Display Topology ID is used as the tile group +identifier. + +Update both struct displayid_tiled_block topology_id member and struct +drm_tile_group group_data member to full 9 bytes. + +The group data was missing the last byte of the serial number. I don't +know whether there are known bug reports that might be linked to this, +but it's plausible the last byte could be the differentiating part for +the tile groups, and fewer tile groups might have been created than +intended. + +Fixes: b49b55bd4fba ("drm/displayid: add displayid defines and edid extension (v2)") +Fixes: 138f9ebb9755 ("drm: add tile_group support. (v3)") +Cc: Dave Airlie +Cc: stable@vger.kernel.org # v3.19+ +Reviewed-by: Dave Airlie +Link: https://patch.msgid.link/20260610141549.555605-1-jani.nikula@intel.com +Signed-off-by: Jani Nikula +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/drm_connector.c | 12 ++++++------ + drivers/gpu/drm/drm_displayid_internal.h | 2 +- + include/drm/drm_connector.h | 6 +++--- + 3 files changed, 10 insertions(+), 10 deletions(-) + +--- a/drivers/gpu/drm/drm_connector.c ++++ b/drivers/gpu/drm/drm_connector.c +@@ -3576,7 +3576,7 @@ EXPORT_SYMBOL(drm_mode_put_tile_group); + /** + * drm_mode_get_tile_group - get a reference to an existing tile group + * @dev: DRM device +- * @topology: 8-bytes unique per monitor. ++ * @topology_id: 9-byte unique ID per monitor. + * + * Use the unique bytes to get a reference to an existing tile group. + * +@@ -3584,14 +3584,14 @@ EXPORT_SYMBOL(drm_mode_put_tile_group); + * tile group or NULL if not found. + */ + struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev, +- const char topology[8]) ++ const char topology_id[9]) + { + struct drm_tile_group *tg; + int id; + + mutex_lock(&dev->mode_config.idr_mutex); + idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) { +- if (!memcmp(tg->group_data, topology, 8)) { ++ if (!memcmp(tg->group_data, topology_id, sizeof(tg->group_data))) { + if (!kref_get_unless_zero(&tg->refcount)) + tg = NULL; + mutex_unlock(&dev->mode_config.idr_mutex); +@@ -3606,7 +3606,7 @@ EXPORT_SYMBOL(drm_mode_get_tile_group); + /** + * drm_mode_create_tile_group - create a tile group from a displayid description + * @dev: DRM device +- * @topology: 8-bytes unique per monitor. ++ * @topology_id: 9-byte unique ID per monitor. + * + * Create a tile group for the unique monitor, and get a unique + * identifier for the tile group. +@@ -3615,7 +3615,7 @@ EXPORT_SYMBOL(drm_mode_get_tile_group); + * new tile group or NULL. + */ + struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev, +- const char topology[8]) ++ const char topology_id[9]) + { + struct drm_tile_group *tg; + int ret; +@@ -3625,7 +3625,7 @@ struct drm_tile_group *drm_mode_create_t + return NULL; + + kref_init(&tg->refcount); +- memcpy(tg->group_data, topology, 8); ++ memcpy(tg->group_data, topology_id, sizeof(tg->group_data)); + tg->dev = dev; + + mutex_lock(&dev->mode_config.idr_mutex); +--- a/drivers/gpu/drm/drm_displayid_internal.h ++++ b/drivers/gpu/drm/drm_displayid_internal.h +@@ -109,7 +109,7 @@ struct displayid_tiled_block { + u8 topo[3]; + u8 tile_size[4]; + u8 tile_pixel_bezel[5]; +- u8 topology_id[8]; ++ u8 topology_id[9]; + } __packed; + + struct displayid_detailed_timings_1 { +--- a/include/drm/drm_connector.h ++++ b/include/drm/drm_connector.h +@@ -2608,13 +2608,13 @@ struct drm_tile_group { + struct kref refcount; + struct drm_device *dev; + int id; +- u8 group_data[8]; ++ u8 group_data[9]; + }; + + struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev, +- const char topology[8]); ++ const char topology_id[9]); + struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev, +- const char topology[8]); ++ const char topology_id[9]); + void drm_mode_put_tile_group(struct drm_device *dev, + struct drm_tile_group *tg); + diff --git a/queue-7.1/drm-i915-gem-add-missing-nospec-on-parallel-submit-slot.patch b/queue-7.1/drm-i915-gem-add-missing-nospec-on-parallel-submit-slot.patch new file mode 100644 index 0000000000..3aebeeae24 --- /dev/null +++ b/queue-7.1/drm-i915-gem-add-missing-nospec-on-parallel-submit-slot.patch @@ -0,0 +1,41 @@ +From 914a76a9f08366434bf595700f62026b7a19a9cc Mon Sep 17 00:00:00 2001 +From: Joonas Lahtinen +Date: Mon, 22 Jun 2026 16:25:39 +0300 +Subject: drm/i915/gem: Add missing nospec on parallel submit slot + +From: Joonas Lahtinen + +commit 914a76a9f08366434bf595700f62026b7a19a9cc upstream. + +Add missing Spectre mitigation for userspace controlled parallel +submission slot. + +Discovered using AI-assisted static analysis confirmed by Intel +Product Security. + +Reported-by: Martin Hodo +Fixes: e5e32171a2cf ("drm/i915/guc: Connect UAPI to GuC multi-lrc interface") +Cc: Matthew Brost +Cc: Tvrtko Ursulin +Signed-off-by: Joonas Lahtinen +Reviewed-by: Matthew Brost +Reviewed-by: Tvrtko Ursulin +Cc: # v5.16+ +Link: https://patch.msgid.link/20260622132539.165558-1-joonas.lahtinen@linux.intel.com +(cherry picked from commit 15b9353deff3cf72331c387780de3cf9c316b643) +Signed-off-by: Joonas Lahtinen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/gem/i915_gem_context.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c ++++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c +@@ -613,6 +613,7 @@ set_proto_ctx_engines_parallel_submit(st + return -EINVAL; + } + ++ slot = array_index_nospec(slot, set->num_engines); + if (set->engines[slot].type != I915_GEM_ENGINE_TYPE_INVALID) { + drm_dbg(&i915->drm, + "Invalid placement[%d], already occupied\n", slot); diff --git a/queue-7.1/drm-i915-mtl-enable-pps-before-pll.patch b/queue-7.1/drm-i915-mtl-enable-pps-before-pll.patch new file mode 100644 index 0000000000..7c4d3efeff --- /dev/null +++ b/queue-7.1/drm-i915-mtl-enable-pps-before-pll.patch @@ -0,0 +1,71 @@ +From 062499cc4813b5a3cbed5dd4fbe0177265858450 Mon Sep 17 00:00:00 2001 +From: Imre Deak +Date: Fri, 12 Jun 2026 20:26:17 +0300 +Subject: drm/i915/mtl+: Enable PPS before PLL +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Imre Deak + +commit 062499cc4813b5a3cbed5dd4fbe0177265858450 upstream. + +Enabling PPS after a display port's PLL is enabled leads to PLL / DDI +BUF timeouts during system resuming after a long (> 45 mins) suspended +state, at least on some ARL and MTL laptops, either all or some of them +also containing an Nvidia GPU. Enabling PPS first and then the PLL fixes +the problem for all the reporters. + +A similar issue is seen when enabling an external DP output on PHY B +(vs. PHY A in the above eDP cases), where this change will not have any +effect (since no PPS is used in that case). There isn't any direct +connection between PPS and PLL, so the fix for eDP works by some +side-effect only. However Bspec does seem to require enabling PPS first, +so let's do that. Further investigation continues on the actual root +cause and a cure for external panels. + +Fixes: 1a7fad2aea74 ("drm/i915/cx0: Enable dpll framework for MTL+") +Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/16098 +Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/16064 +Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/16042 +Cc: Mika Kahola +Cc: stable@vger.kernel.org # v7.0+ +Tested-by: Jouni Högander +Tested-by: Marco Nenciarini +Reviewed-by: Suraj Kandpal +Signed-off-by: Imre Deak +Link: https://patch.msgid.link/20260612172617.3427027-1-imre.deak@intel.com +(cherry picked from commit 28783a274e886dd6da61419be6020bd9d0384e9f) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/display/intel_ddi.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/i915/display/intel_ddi.c ++++ b/drivers/gpu/drm/i915/display/intel_ddi.c +@@ -2652,9 +2652,6 @@ static void mtl_ddi_pre_enable_dp(struct + /* 3. Select Thunderbolt */ + mtl_port_buf_ctl_io_selection(encoder); + +- /* 4. Enable Panel Power if PPS is required */ +- intel_pps_on(intel_dp); +- + /* 5. Enable the port PLL */ + intel_ddi_enable_clock(encoder, crtc_state); + +@@ -3710,6 +3707,14 @@ intel_ddi_pre_pll_enable(struct intel_at + else if (display->platform.geminilake || display->platform.broxton) + bxt_dpio_phy_set_lane_optim_mask(encoder, + crtc_state->lane_lat_optim_mask); ++ ++ /* ++ * There is no direct connection between the PLL and PPS, however ++ * enabling PPS before PLL is required to avoid PLL/DDI BUF timeouts ++ * during system resume. Do that matching the Bspec order as well. ++ */ ++ if (DISPLAY_VER(display) >= 14) ++ intel_pps_on(&dig_port->dp); + } + + static void adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder *encoder) diff --git a/queue-7.1/drm-nouveau-acr-fix-missing-nvkm_done-in-error-path-of-nvkm_acr_oneinit.patch b/queue-7.1/drm-nouveau-acr-fix-missing-nvkm_done-in-error-path-of-nvkm_acr_oneinit.patch new file mode 100644 index 0000000000..d6482119ee --- /dev/null +++ b/queue-7.1/drm-nouveau-acr-fix-missing-nvkm_done-in-error-path-of-nvkm_acr_oneinit.patch @@ -0,0 +1,44 @@ +From c3027973f692077a1b66a9fb26d6a7c46c0dc72c Mon Sep 17 00:00:00 2001 +From: Wentao Liang +Date: Sat, 6 Jun 2026 15:56:06 +0000 +Subject: drm/nouveau/acr: fix missing nvkm_done() in error path of nvkm_acr_oneinit() + +From: Wentao Liang + +commit c3027973f692077a1b66a9fb26d6a7c46c0dc72c upstream. + +In nvkm_acr_oneinit(), nvkm_kmap(acr->wpr) is invoked unconditionally +at line 309 to obtain a mapping reference. Additionally, when both +acr->wpr_fw and acr->wpr_comp are present, a second nvkm_kmap() is +called inside the conditional block. Both mappings are expected to be +released by nvkm_done(acr->wpr) at line 320 before the function returns +successfully. + +However, when a mismatch is detected during the loop within the +conditional block, the function returns -EINVAL at line 318 without +calling nvkm_done(). This results in a leak of the kmap reference(s) +acquired earlier. + +Fix the issue by invoking nvkm_done(acr->wpr) prior to the early return +to ensure proper release of the mapping references. + +Fixes: 22dcda45a3d1 ("drm/nouveau/acr: implement new subdev to replace "secure boot"") +Cc: stable@vger.kernel.org +Signed-off-by: Wentao Liang +Link: https://patch.msgid.link/20260606155606.77593-1-vulab@iscas.ac.cn +Signed-off-by: Danilo Krummrich +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c +@@ -315,6 +315,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *sub + i, us, fw); + } + } ++ nvkm_done(acr->wpr); + return -EINVAL; + } + nvkm_done(acr->wpr); diff --git a/queue-7.1/drm-nouveau-fix-reversed-error-cleanup-order-in-ucopy-functions.patch b/queue-7.1/drm-nouveau-fix-reversed-error-cleanup-order-in-ucopy-functions.patch new file mode 100644 index 0000000000..d9b02600bc --- /dev/null +++ b/queue-7.1/drm-nouveau-fix-reversed-error-cleanup-order-in-ucopy-functions.patch @@ -0,0 +1,66 @@ +From ab99ead646b1b833ecd57fe577a2816f2e848167 Mon Sep 17 00:00:00 2001 +From: Junrui Luo +Date: Wed, 10 Jun 2026 18:01:28 +0800 +Subject: drm/nouveau: fix reversed error cleanup order in ucopy functions + +From: Junrui Luo + +commit ab99ead646b1b833ecd57fe577a2816f2e848167 upstream. + +nouveau_uvmm_vm_bind_ucopy() and nouveau_exec_ucopy() place their error +cleanup labels in allocation order rather than reverse allocation order. +On a u_memcpya() failure for in_sync.s, the goto to err_free_ops (or +err_free_pushs) frees the first allocation and then falls through to +err_free_ins, which calls u_free() on args->in_sync.s. + +Since args->in_sync.s still holds the ERR_PTR returned by the failed +u_memcpya(), and ERR_PTR values are not caught by ZERO_OR_NULL_PTR(), +kvfree() proceeds to dereference it, which can result in a kernel oops. +A failure for out_sync.s instead jumps to err_free_ins and skips freeing +the first allocation, leading to a memory leak. + +Fix by swapping the cleanup label order so resources are freed in the +correct reverse allocation sequence. + +Fixes: b88baab82871 ("drm/nouveau: implement new VM_BIND uAPI") +Reported-by: Yuhao Jiang +Cc: stable@vger.kernel.org +Signed-off-by: Junrui Luo +Link: https://patch.msgid.link/SYBPR01MB7881484D91A6F80271415F71AF1A2@SYBPR01MB7881.ausprd01.prod.outlook.com +Signed-off-by: Danilo Krummrich +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/nouveau/nouveau_exec.c | 4 ++-- + drivers/gpu/drm/nouveau/nouveau_uvmm.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/nouveau/nouveau_exec.c ++++ b/drivers/gpu/drm/nouveau/nouveau_exec.c +@@ -331,10 +331,10 @@ nouveau_exec_ucopy(struct nouveau_exec_j + + return 0; + +-err_free_pushs: +- u_free(args->push.s); + err_free_ins: + u_free(args->in_sync.s); ++err_free_pushs: ++ u_free(args->push.s); + return ret; + } + +--- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c ++++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c +@@ -1779,10 +1779,10 @@ nouveau_uvmm_vm_bind_ucopy(struct nouvea + + return 0; + +-err_free_ops: +- u_free(args->op.s); + err_free_ins: + u_free(args->in_sync.s); ++err_free_ops: ++ u_free(args->op.s); + return ret; + } + diff --git a/queue-7.1/drm-radeon-fix-r100_copy_blit-for-large-bos.patch b/queue-7.1/drm-radeon-fix-r100_copy_blit-for-large-bos.patch new file mode 100644 index 0000000000..d7845fd95c --- /dev/null +++ b/queue-7.1/drm-radeon-fix-r100_copy_blit-for-large-bos.patch @@ -0,0 +1,82 @@ +From f896e86273dbbebb5eac966b4a201b5c62a02e9a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20Ondra=C4=8Dka?= +Date: Wed, 10 Jun 2026 10:32:45 +0200 +Subject: drm/radeon: fix r100_copy_blit for large BOs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pavel Ondračka + +commit f896e86273dbbebb5eac966b4a201b5c62a02e9a upstream. + +r100_copy_blit() copies BOs as 1024-pixel-wide ARGB8888 blits, so one +GPU page becomes one blit row. Large copies are split into chunks of at +most 8191 rows. + +The kernel register header names the packet coordinate dwords SRC_Y_X +and DST_Y_X. In the BITBLT_MULTI description in +R5xx_Acceleration_v1.5.pdf docs, these correspond to [SRC_X1 | SRC_Y1] +and [DST_X1 | DST_Y1], which are signed 13-bit coordinates in the +-8192..8191 range. The old code kept SRC/DST_PITCH_OFFSET at the BO base +and used SRC_Y_X/DST_Y_X as the chunk address, so large BO moves could +exceed that coordinate range. + +Compute per-chunk SRC/DST_PITCH_OFFSET bases and emit zero source and +destination coordinates. r100_copy_blit() already packs +SRC/DST_PITCH_OFFSET as pitch plus base offset, so large chunk addresses +belong there rather than in the coordinate fields. + +This fixes Prison Architect corruption with 4096x4096 mipped textures +after they are evicted to GTT under memory pressure on RV530. + +Closes: https://gitlab.freedesktop.org/mesa/mesa/-/work_items/6716 +Acked-by: Christian König +Signed-off-by: Pavel Ondračka +Signed-off-by: Alex Deucher +(cherry picked from commit 87be26aee76239c6da03e599f238a426897f78ad) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/radeon/r100.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/radeon/r100.c ++++ b/drivers/gpu/drm/radeon/r100.c +@@ -906,6 +906,7 @@ struct radeon_fence *r100_copy_blit(stru + { + struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + struct radeon_fence *fence; ++ uint64_t cur_src_offset, cur_dst_offset; + uint32_t cur_pages; + uint32_t stride_bytes = RADEON_GPU_PAGE_SIZE; + uint32_t pitch; +@@ -934,6 +935,10 @@ struct radeon_fence *r100_copy_blit(stru + cur_pages = 8191; + } + num_gpu_pages -= cur_pages; ++ cur_src_offset = src_offset + ++ (uint64_t)num_gpu_pages * RADEON_GPU_PAGE_SIZE; ++ cur_dst_offset = dst_offset + ++ (uint64_t)num_gpu_pages * RADEON_GPU_PAGE_SIZE; + + /* pages are in Y direction - height + page width in X direction - width */ +@@ -950,13 +955,13 @@ struct radeon_fence *r100_copy_blit(stru + RADEON_DP_SRC_SOURCE_MEMORY | + RADEON_GMC_CLR_CMP_CNTL_DIS | + RADEON_GMC_WR_MSK_DIS); +- radeon_ring_write(ring, (pitch << 22) | (src_offset >> 10)); +- radeon_ring_write(ring, (pitch << 22) | (dst_offset >> 10)); ++ radeon_ring_write(ring, (pitch << 22) | (cur_src_offset >> 10)); ++ radeon_ring_write(ring, (pitch << 22) | (cur_dst_offset >> 10)); + radeon_ring_write(ring, (0x1fff) | (0x1fff << 16)); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, (0x1fff) | (0x1fff << 16)); +- radeon_ring_write(ring, num_gpu_pages); +- radeon_ring_write(ring, num_gpu_pages); ++ radeon_ring_write(ring, 0); ++ radeon_ring_write(ring, 0); + radeon_ring_write(ring, cur_pages | (stride_pixels << 16)); + } + radeon_ring_write(ring, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0)); diff --git a/queue-7.1/drm-sysfb-avoid-possible-truncation-with-calculating-visible-size.patch b/queue-7.1/drm-sysfb-avoid-possible-truncation-with-calculating-visible-size.patch new file mode 100644 index 0000000000..329a09c941 --- /dev/null +++ b/queue-7.1/drm-sysfb-avoid-possible-truncation-with-calculating-visible-size.patch @@ -0,0 +1,49 @@ +From b771974988ec7ce077a7246fa0fa588c246fe581 Mon Sep 17 00:00:00 2001 +From: Thomas Zimmermann +Date: Thu, 18 Jun 2026 10:41:58 +0200 +Subject: drm/sysfb: Avoid possible truncation with calculating visible size + +From: Thomas Zimmermann + +commit b771974988ec7ce077a7246fa0fa588c246fe581 upstream. + +Calculating the visible size of the system framebuffer can result in +truncation of the result. The calculation uses 32-bit arithmetics, +which can overflow if the values for height and stride are large. Fix +the issue by multiplying with mul_u32_u32(). + +Signed-off-by: Thomas Zimmermann +Fixes: 32ae90c66fb6 ("drm/sysfb: Add efidrm for EFI displays") +Fixes: a84eb6abe2b6 ("drm/sysfb: Add vesadrm for VESA displays") +Reported-by: Sashiko +Closes: https://lore.kernel.org/dri-devel/20260617114027.1F2A71F000E9@smtp.kernel.org/ +Cc: Thomas Zimmermann +Cc: Javier Martinez Canillas +Cc: dri-devel@lists.freedesktop.org +Cc: # v6.16+ +Reviewed-by: Javier Martinez Canillas +Link: https://patch.msgid.link/20260618084327.46567-3-tzimmermann@suse.de +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c ++++ b/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c +@@ -2,6 +2,7 @@ + + #include + #include ++#include + #include + #include + +@@ -73,7 +74,7 @@ EXPORT_SYMBOL(drm_sysfb_get_stride_si); + u64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si, + unsigned int height, unsigned int stride, u64 size) + { +- u64 vsize = height * stride; ++ u64 vsize = mul_u32_u32(height, stride); + + return drm_sysfb_get_validated_size0(dev, "visible size", vsize, size); + } diff --git a/queue-7.1/drm-sysfb-avoid-truncating-maximum-stride.patch b/queue-7.1/drm-sysfb-avoid-truncating-maximum-stride.patch new file mode 100644 index 0000000000..c5783191ae --- /dev/null +++ b/queue-7.1/drm-sysfb-avoid-truncating-maximum-stride.patch @@ -0,0 +1,52 @@ +From 9206b22fb959f4a9cf1921f34aed0df1dcb1ab04 Mon Sep 17 00:00:00 2001 +From: Thomas Zimmermann +Date: Thu, 18 Jun 2026 10:42:00 +0200 +Subject: drm/sysfb: Avoid truncating maximum stride + +From: Thomas Zimmermann + +commit 9206b22fb959f4a9cf1921f34aed0df1dcb1ab04 upstream. + +Passing a maximum as 64-bit type to drm_sysfb_get_validated_int0() +can truncate the value to 32 bits. Use drm_sysfb_get_validated_size0(), +which uses 64-bit arithmetics. Then test the returned stride against +the limits of int to avoid truncations in the returned value. A valid +stride is in the range of [1, INT_MAX] inclusive. + +Signed-off-by: Thomas Zimmermann +Reported-by: Sashiko +Closes: https://lore.kernel.org/dri-devel/20260617114016.5A5991F000E9@smtp.kernel.org/ +Fixes: 32ae90c66fb6 ("drm/sysfb: Add efidrm for EFI displays") +Fixes: a84eb6abe2b6 ("drm/sysfb: Add vesadrm for VESA displays") +Cc: Thomas Zimmermann +Cc: Javier Martinez Canillas +Cc: dri-devel@lists.freedesktop.org +Cc: # v6.16+ +Reviewed-by: Javier Martinez Canillas +Link: https://patch.msgid.link/20260618084327.46567-5-tzimmermann@suse.de +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c ++++ b/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c +@@ -56,11 +56,17 @@ int drm_sysfb_get_stride_si(struct drm_d + unsigned int width, unsigned int height, u64 size) + { + u64 lfb_linelength = si->lfb_linelength; ++ s64 stride; + + if (!lfb_linelength) + lfb_linelength = drm_format_info_min_pitch(format, 0, width); + +- return drm_sysfb_get_validated_int0(dev, "stride", lfb_linelength, div64_u64(size, height)); ++ stride = drm_sysfb_get_validated_size0(dev, "stride", lfb_linelength, ++ div64_u64(size, height)); ++ if (stride < INT_MIN || stride > INT_MAX) ++ return -EINVAL; ++ ++ return (int)stride; /* stride or negative errno code */ + } + EXPORT_SYMBOL(drm_sysfb_get_stride_si); + diff --git a/queue-7.1/drm-sysfb-do-not-page-align-visible-size-of-the-framebuffer.patch b/queue-7.1/drm-sysfb-do-not-page-align-visible-size-of-the-framebuffer.patch new file mode 100644 index 0000000000..20f935a52d --- /dev/null +++ b/queue-7.1/drm-sysfb-do-not-page-align-visible-size-of-the-framebuffer.patch @@ -0,0 +1,39 @@ +From 134844856c399bfa9462a159dcf860bfdb748055 Mon Sep 17 00:00:00 2001 +From: Thomas Zimmermann +Date: Thu, 18 Jun 2026 10:41:57 +0200 +Subject: drm/sysfb: Do not page-align visible size of the framebuffer + +From: Thomas Zimmermann + +commit 134844856c399bfa9462a159dcf860bfdb748055 upstream. + +Only return the actually visible size of the system framebuffer in +drm_sysfb_get_visible_size_si(). Drivers use this size value for +reserving access to framebuffer memory. Increasing the value can +make later attempts to do so fail. + +Signed-off-by: Thomas Zimmermann +Fixes: 32ae90c66fb6 ("drm/sysfb: Add efidrm for EFI displays") +Fixes: a84eb6abe2b6 ("drm/sysfb: Add vesadrm for VESA displays") +Reviewed-by: Javier Martinez Canillas +Cc: Thomas Zimmermann +Cc: Javier Martinez Canillas +Cc: dri-devel@lists.freedesktop.org +Cc: # v6.16+ +Link: https://patch.msgid.link/20260618084327.46567-2-tzimmermann@suse.de +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c ++++ b/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c +@@ -67,7 +67,7 @@ EXPORT_SYMBOL(drm_sysfb_get_stride_si); + u64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si, + unsigned int height, unsigned int stride, u64 size) + { +- u64 vsize = PAGE_ALIGN(height * stride); ++ u64 vsize = height * stride; + + return drm_sysfb_get_validated_size0(dev, "visible size", vsize, size); + } diff --git a/queue-7.1/drm-sysfb-return-errno-code-from-drm_sysfb_get_visible_size.patch b/queue-7.1/drm-sysfb-return-errno-code-from-drm_sysfb_get_visible_size.patch new file mode 100644 index 0000000000..ecae1b443b --- /dev/null +++ b/queue-7.1/drm-sysfb-return-errno-code-from-drm_sysfb_get_visible_size.patch @@ -0,0 +1,105 @@ +From 7bab0f09d753f098977bbba3955d694c2e2c25da Mon Sep 17 00:00:00 2001 +From: Thomas Zimmermann +Date: Thu, 18 Jun 2026 10:41:59 +0200 +Subject: drm/sysfb: Return errno code from drm_sysfb_get_visible_size() + +From: Thomas Zimmermann + +commit 7bab0f09d753f098977bbba3955d694c2e2c25da upstream. + +Change the return type of drm_sysfb_get_visible_size() to s64 so +that it returns a possible errno code from _get_validated_size0(). +Fix callers to handle the errno code. + +The currently returned unsigned type converts an errno code to a +very large size value, which drivers interpret as visible size of +the system framebuffer. Later efforts to reserve the framebuffer +resource fail. + +The bug has been present since efidrm and vesadrm got merged. It +was then part of each driver. + +Signed-off-by: Thomas Zimmermann +Fixes: 32ae90c66fb6 ("drm/sysfb: Add efidrm for EFI displays") +Fixes: a84eb6abe2b6 ("drm/sysfb: Add vesadrm for VESA displays") +Reviewed-by: Javier Martinez Canillas +Cc: Thomas Zimmermann +Cc: Javier Martinez Canillas +Cc: dri-devel@lists.freedesktop.org +Cc: # v6.16+ +Link: https://patch.msgid.link/20260618084327.46567-4-tzimmermann@suse.de +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/sysfb/drm_sysfb_helper.h | 2 +- + drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c | 2 +- + drivers/gpu/drm/sysfb/efidrm.c | 7 ++++--- + drivers/gpu/drm/sysfb/vesadrm.c | 6 +++--- + 4 files changed, 9 insertions(+), 8 deletions(-) + +--- a/drivers/gpu/drm/sysfb/drm_sysfb_helper.h ++++ b/drivers/gpu/drm/sysfb/drm_sysfb_helper.h +@@ -50,7 +50,7 @@ struct resource *drm_sysfb_get_memory_si + int drm_sysfb_get_stride_si(struct drm_device *dev, const struct screen_info *si, + const struct drm_format_info *format, + unsigned int width, unsigned int height, u64 size); +-u64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si, ++s64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si, + unsigned int height, unsigned int stride, u64 size); + #endif + +--- a/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c ++++ b/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c +@@ -71,7 +71,7 @@ int drm_sysfb_get_stride_si(struct drm_d + } + EXPORT_SYMBOL(drm_sysfb_get_stride_si); + +-u64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si, ++s64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si, + unsigned int height, unsigned int stride, u64 size) + { + u64 vsize = mul_u32_u32(height, stride); +--- a/drivers/gpu/drm/sysfb/efidrm.c ++++ b/drivers/gpu/drm/sysfb/efidrm.c +@@ -150,7 +150,8 @@ static struct efidrm_device *efidrm_devi + const struct screen_info *si; + const struct drm_format_info *format; + int width, height, stride; +- u64 vsize, mem_flags; ++ s64 vsize; ++ u64 mem_flags; + struct resource resbuf; + struct resource *res; + struct efidrm_device *efi; +@@ -204,8 +205,8 @@ static struct efidrm_device *efidrm_devi + if (stride < 0) + return ERR_PTR(stride); + vsize = drm_sysfb_get_visible_size_si(dev, si, height, stride, resource_size(res)); +- if (!vsize) +- return ERR_PTR(-EINVAL); ++ if (vsize < 0) ++ return ERR_PTR(vsize); + + drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, stride=%d bytes\n", + &format->format, width, height, stride); +--- a/drivers/gpu/drm/sysfb/vesadrm.c ++++ b/drivers/gpu/drm/sysfb/vesadrm.c +@@ -400,7 +400,7 @@ static struct vesadrm_device *vesadrm_de + const struct screen_info *si; + const struct drm_format_info *format; + int width, height, stride; +- u64 vsize; ++ s64 vsize; + struct resource resbuf; + struct resource *res; + struct vesadrm_device *vesa; +@@ -455,8 +455,8 @@ static struct vesadrm_device *vesadrm_de + if (stride < 0) + return ERR_PTR(stride); + vsize = drm_sysfb_get_visible_size_si(dev, si, height, stride, resource_size(res)); +- if (!vsize) +- return ERR_PTR(-EINVAL); ++ if (vsize < 0) ++ return ERR_PTR(vsize); + + drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, stride=%d bytes\n", + &format->format, width, height, stride); diff --git a/queue-7.1/drm-xe-add-compact-pt-and-addr-mask-handling-for-page-reclaim.patch b/queue-7.1/drm-xe-add-compact-pt-and-addr-mask-handling-for-page-reclaim.patch new file mode 100644 index 0000000000..c7084c8391 --- /dev/null +++ b/queue-7.1/drm-xe-add-compact-pt-and-addr-mask-handling-for-page-reclaim.patch @@ -0,0 +1,288 @@ +From 0b5ed2756d45b04669502a1f13b1657ec7664571 Mon Sep 17 00:00:00 2001 +From: Brian Nguyen +Date: Fri, 5 Jun 2026 22:42:58 +0000 +Subject: drm/xe: Add compact-PT and addr mask handling for page reclaim + +From: Brian Nguyen + +commit 0b5ed2756d45b04669502a1f13b1657ec7664571 upstream. + +Current implementation of generate_reclaim_entry() overlooks some +differences between the different page implementations: address masking +and compact 64K page handling. + +Address masking of each leaf varies depending on the leaf entry size. +generate_reclaim_entry() is using XE_PTE_ADDR_MASK [51:12] for all leaf +entries. For 2MB PTEs, bit 12 (PAT) is part of the flags so the old mask +corrupts the physical address extraction. + +64K pages can be represented as PS64 and a compact PT, which the latter +was not handled. Compact pages aren't walked by the unbind walker, so we +separately walk through the compact PT to ensure none of the leaf 64K +PTEs are dropped. Previously, compact PT were causing an abort since it +was considered covered and not descended into. + +v2: + - Update 64K entry/unbind walker for 64K compact PT handling. (Matthew) + - Rework calculations of reclamation and address mask size. + - Add new func abstracting the error handling before generating the + reclaim entry. + +v3: + - Report finer addr granularity in abort debug print for compact. + (Zongyao) + - Add comments for ADDR_MASK usage. (Zongyao) + - Drop existing phys_addr asserts, the new XE_PAGE_ADDR_MASK clears + bits checked, so redundant asserts. (Sashiko) + - WARN_ON to verify compact pt and edge pt won't be possible. + +Fixes: b912138df299 ("drm/xe: Create page reclaim list on unbind") +Assisted-by: Sashiko-Review:gemini-3.1-pro-preview +Cc: stable@vger.kernel.org +Cc: Matthew Auld +Suggested-by: Zongyao Bai +Signed-off-by: Brian Nguyen +Reviewed-by: Matthew Auld +Reviewed-by: Zongyao Bai +Link: https://patch.msgid.link/20260605224257.2194194-2-brian3.nguyen@intel.com +Signed-off-by: Matt Roper +(cherry picked from commit 669252801a4aa4098fbc5dd9dd0bd93f0625abd7) +Signed-off-by: Matthew Brost +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/xe/regs/xe_gtt_defs.h | 6 + + drivers/gpu/drm/xe/xe_pt.c | 133 +++++++++++++++++++--------------- + 2 files changed, 83 insertions(+), 56 deletions(-) + +--- a/drivers/gpu/drm/xe/regs/xe_gtt_defs.h ++++ b/drivers/gpu/drm/xe/regs/xe_gtt_defs.h +@@ -9,7 +9,11 @@ + #define XELPG_GGTT_PTE_PAT0 BIT_ULL(52) + #define XELPG_GGTT_PTE_PAT1 BIT_ULL(53) + +-#define XE_PTE_ADDR_MASK GENMASK_ULL(51, 12) ++/* ++ * Mask for PTE address bits [51:shift]. ++ * shift is the lower address boundary of page. ++ */ ++#define XE_PAGE_ADDR_MASK(shift) GENMASK_ULL(51, (shift)) + #define GGTT_PTE_VFID GENMASK_ULL(11, 2) + + #define GUC_GGTT_TOP 0xFEE00000 +--- a/drivers/gpu/drm/xe/xe_pt.c ++++ b/drivers/gpu/drm/xe/xe_pt.c +@@ -1643,23 +1643,21 @@ static bool xe_pt_check_kill(u64 addr, u + return false; + } + +-/* page_size = 2^(reclamation_size + XE_PTE_SHIFT) */ +-#define COMPUTE_RECLAIM_ADDRESS_MASK(page_size) \ +-({ \ +- BUILD_BUG_ON(!__builtin_constant_p(page_size)); \ +- ilog2(page_size) - XE_PTE_SHIFT; \ +-}) +- + static int generate_reclaim_entry(struct xe_tile *tile, + struct xe_page_reclaim_list *prl, + u64 pte, struct xe_pt *xe_child) + { + struct xe_gt *gt = tile->primary_gt; + struct xe_guc_page_reclaim_entry *reclaim_entries = prl->entries; +- u64 phys_addr = pte & XE_PTE_ADDR_MASK; ++ bool is_2m = xe_child->level == 1 && (pte & XE_PDE_PS_2M); ++ bool is_64k = xe_child->level == 0 && ((pte & XE_PTE_PS64) || xe_child->is_compact); ++ u32 page_shift = is_2m ? ilog2(SZ_2M) : is_64k ? ilog2(SZ_64K) : ilog2(SZ_4K); ++ /* Physical address bits start at page shift: 2M->[51:21], 64K->[51:16], 4K->[51:12] */ ++ u64 phys_addr = pte & XE_PAGE_ADDR_MASK(page_shift); ++ /* Page address is relative to 4K page regardless of entry level */ + u64 phys_page = phys_addr >> XE_PTE_SHIFT; + int num_entries = prl->num_entries; +- u32 reclamation_size; ++ u32 reclamation_size = page_shift - XE_PTE_SHIFT; + + xe_tile_assert(tile, xe_child->level <= MAX_HUGEPTE_LEVEL); + xe_tile_assert(tile, reclaim_entries); +@@ -1674,18 +1672,12 @@ static int generate_reclaim_entry(struct + * Page size is computed as 2^(reclamation_size + XE_PTE_SHIFT) bytes. + * Only 4K, 64K (level 0), and 2M pages are supported by hardware for page reclaim + */ +- if (xe_child->level == 0 && !(pte & XE_PTE_PS64)) { +- xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_4K_ENTRY_COUNT, 1); +- reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_4K); /* reclamation_size = 0 */ +- xe_tile_assert(tile, phys_addr % SZ_4K == 0); +- } else if (xe_child->level == 0) { +- xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_64K_ENTRY_COUNT, 1); +- reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_64K); /* reclamation_size = 4 */ +- xe_tile_assert(tile, phys_addr % SZ_64K == 0); +- } else if (xe_child->level == 1 && pte & XE_PDE_PS_2M) { ++ if (is_2m) { + xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_2M_ENTRY_COUNT, 1); +- reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_2M); /* reclamation_size = 9 */ +- xe_tile_assert(tile, phys_addr % SZ_2M == 0); ++ } else if (is_64k) { ++ xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_64K_ENTRY_COUNT, 1); ++ } else if (xe_child->level == 0) { ++ xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_4K_ENTRY_COUNT, 1); + } else { + xe_page_reclaim_list_abort(tile->primary_gt, prl, + "unsupported PTE level=%u pte=%#llx", +@@ -1706,6 +1698,48 @@ static int generate_reclaim_entry(struct + return 0; + } + ++static int add_pte_to_prl(struct xe_tile *tile, struct xe_page_reclaim_list *prl, ++ struct xe_pt *xe_child, u64 pte, u64 addr) ++{ ++ /* ++ * In rare scenarios, pte may not be written yet due to racy conditions. ++ * In such cases, invalidate the PRL and fallback to full PPC invalidation. ++ */ ++ if (!pte) { ++ xe_page_reclaim_list_abort(tile->primary_gt, prl, ++ "found zero pte at addr=%#llx", addr); ++ return -EINVAL; ++ } ++ ++ /* Ensure it is a defined page */ ++ xe_tile_assert(tile, xe_child->level == 0 || ++ (pte & (XE_PDE_PS_2M | XE_PDPE_PS_1G))); ++ ++ /* Account for NULL terminated entry on end (-1) */ ++ if (prl->num_entries >= XE_PAGE_RECLAIM_MAX_ENTRIES - 1) { ++ xe_page_reclaim_list_abort(tile->primary_gt, prl, ++ "overflow while adding pte=%#llx", pte); ++ return -ENOSPC; ++ } ++ ++ return generate_reclaim_entry(tile, prl, pte, xe_child); ++} ++ ++static bool add_compact_pt_prl(struct xe_tile *tile, struct xe_page_reclaim_list *prl, ++ struct xe_device *xe, struct xe_pt *compact_pt, u64 addr) ++{ ++ struct iosys_map *map = &compact_pt->bo->vmap; ++ ++ for (pgoff_t i = 0; i < SZ_2M / SZ_64K && xe_page_reclaim_list_valid(prl); i++) { ++ u64 pte = xe_map_rd(xe, map, i * sizeof(u64), u64); ++ ++ if (add_pte_to_prl(tile, prl, compact_pt, pte, addr + i * SZ_64K)) ++ break; ++ } ++ ++ return xe_page_reclaim_list_valid(prl); ++} ++ + static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset, + unsigned int level, u64 addr, u64 next, + struct xe_ptw **child, +@@ -1715,21 +1749,22 @@ static int xe_pt_stage_unbind_entry(stru + struct xe_pt *xe_child = container_of(*child, typeof(*xe_child), base); + struct xe_pt_stage_unbind_walk *xe_walk = + container_of(walk, typeof(*xe_walk), base); +- struct xe_device *xe = tile_to_xe(xe_walk->tile); ++ struct xe_page_reclaim_list *prl = xe_walk->prl; ++ struct xe_tile *tile = xe_walk->tile; ++ struct xe_device *xe = tile_to_xe(tile); + pgoff_t first = xe_pt_offset(addr, xe_child->level, walk); + bool killed; + + XE_WARN_ON(!*child); + XE_WARN_ON(!level); + /* Check for leaf node */ +- if (xe_walk->prl && xe_page_reclaim_list_valid(xe_walk->prl) && ++ if (prl && xe_page_reclaim_list_valid(prl) && + xe_child->level <= MAX_HUGEPTE_LEVEL) { + struct iosys_map *leaf_map = &xe_child->bo->vmap; + pgoff_t count = xe_pt_num_entries(addr, next, xe_child->level, walk); + + for (pgoff_t i = 0; i < count; i++) { + u64 pte; +- int ret; + + /* + * If not a leaf pt, skip unless non-leaf pt is interleaved between +@@ -1739,10 +1774,23 @@ static int xe_pt_stage_unbind_entry(stru + u64 pt_size = 1ULL << walk->shifts[xe_child->level]; + bool edge_pt = (i == 0 && !IS_ALIGNED(addr, pt_size)) || + (i == count - 1 && !IS_ALIGNED(next, pt_size)); +- +- if (!edge_pt) { +- xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, +- xe_walk->prl, ++ struct xe_pt *child_pt = ++ container_of(xe_child->base.children[first + i], ++ struct xe_pt, base); ++ ++ /* Compact PTs always fill a full 2M-aligned slot, never an edge. */ ++ XE_WARN_ON(child_pt->is_compact && edge_pt); ++ if (edge_pt) ++ continue; ++ ++ /* Walker never descends into compact PTs, descend now */ ++ if (child_pt->is_compact) { ++ if (!add_compact_pt_prl(tile, prl, xe, child_pt, ++ addr + (u64)i * pt_size)) ++ break; ++ } else { ++ xe_page_reclaim_list_abort(tile->primary_gt, ++ prl, + "PT is skipped by walk at level=%u offset=%lu", + xe_child->level, first + i); + break; +@@ -1752,37 +1800,12 @@ static int xe_pt_stage_unbind_entry(stru + + pte = xe_map_rd(xe, leaf_map, (first + i) * sizeof(u64), u64); + +- /* +- * In rare scenarios, pte may not be written yet due to racy conditions. +- * In such cases, invalidate the PRL and fallback to full PPC invalidation. +- */ +- if (!pte) { +- xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, xe_walk->prl, +- "found zero pte at addr=%#llx", addr); ++ if (add_pte_to_prl(tile, prl, xe_child, pte, addr)) + break; +- } +- +- /* Ensure it is a defined page */ +- xe_tile_assert(xe_walk->tile, xe_child->level == 0 || +- (pte & (XE_PDE_PS_2M | XE_PDPE_PS_1G))); + + /* An entry should be added for 64KB but contigious 4K have XE_PTE_PS64 */ + if (pte & XE_PTE_PS64) + i += 15; /* Skip other 15 consecutive 4K pages in the 64K page */ +- +- /* Account for NULL terminated entry on end (-1) */ +- if (xe_walk->prl->num_entries < XE_PAGE_RECLAIM_MAX_ENTRIES - 1) { +- ret = generate_reclaim_entry(xe_walk->tile, xe_walk->prl, +- pte, xe_child); +- if (ret) +- break; +- } else { +- /* overflow, mark as invalid */ +- xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, xe_walk->prl, +- "overflow while adding pte=%#llx", +- pte); +- break; +- } + } + } + +@@ -1792,7 +1815,7 @@ static int xe_pt_stage_unbind_entry(stru + * Verify if any PTE are potentially dropped at non-leaf levels, either from being + * killed or the page walk covers the region. + */ +- if (xe_walk->prl && xe_page_reclaim_list_valid(xe_walk->prl) && ++ if (prl && xe_page_reclaim_list_valid(prl) && + xe_child->level > MAX_HUGEPTE_LEVEL && xe_child->num_live) { + bool covered = xe_pt_covers(addr, next, xe_child->level, &xe_walk->base); + +@@ -1801,7 +1824,7 @@ static int xe_pt_stage_unbind_entry(stru + * we need to invalidate the PRL. + */ + if (killed || covered) +- xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, xe_walk->prl, ++ xe_page_reclaim_list_abort(tile->primary_gt, prl, + "kill at level=%u addr=%#llx next=%#llx num_live=%u", + level, addr, next, xe_child->num_live); + } diff --git a/queue-7.1/drm-xe-display-skip-force_wc-and-vm_bound-check-for-external-dma-bufs.patch b/queue-7.1/drm-xe-display-skip-force_wc-and-vm_bound-check-for-external-dma-bufs.patch new file mode 100644 index 0000000000..aeb4cfcd4e --- /dev/null +++ b/queue-7.1/drm-xe-display-skip-force_wc-and-vm_bound-check-for-external-dma-bufs.patch @@ -0,0 +1,76 @@ +From d472497265374e895e31cf2af8a2c5f650019889 Mon Sep 17 00:00:00 2001 +From: Matthew Auld +Date: Fri, 12 Jun 2026 18:05:02 +0100 +Subject: drm/xe/display: skip FORCE_WC and vm_bound check for external dma-bufs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Matthew Auld + +commit d472497265374e895e31cf2af8a2c5f650019889 upstream. + +Currently, xe_display_bo_framebuffer_init() unconditionally attempts to +apply XE_BO_FLAG_FORCE_WC to the buffer and rejects the FB creation with +-EINVAL if the BO is already VM_BINDed. + +However, for imported dma-bufs (ttm_bo_type_sg), this check doesn't seem +to make much sense since CPU caching policy is entirely controlled by +the exporter. Plus there is no place to set this flag, in the first +place. Also this is not rejected if not yet vm_binded, but that seems +arbitrary since setting or not setting FORCE_WC should a noop either +way, at this stage, and whether it is currently VM_BINDed makes no +difference. + +Currently if we run an app and offload rendering to an external dGPU, +like NV or another xe device, the dma-buf passed back to the compositor +(igpu) will be an actual external import from xe pov, and it will be +missing FORCE_WC, and if the compositor side did a VM_BIND before +turning into it into an fb the whole thing gets rejected. + +So it looks like we either need to reject outright, no matter what, or +this usecase is valid and we need to loosen the restriction for sg +buffers. Proposing here to loosen the restriction. + +Assisted-by: Gemini:gemini-3.1-pro-preview +Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/work_items/7919 +Fixes: 44e694958b95 ("drm/xe/display: Implement display support") +Signed-off-by: Matthew Auld +Cc: Thomas Hellström +Cc: Matthew Brost +Cc: Maarten Lankhorst +Cc: # v6.12+ +Reviewed-by: Maarten Lankhorst +Link: https://patch.msgid.link/20260612170501.550816-2-matthew.auld@intel.com +(cherry picked from commit 3e493f88c84088ccd7b53cdd23ac5c875c9a60dd) +Signed-off-by: Thomas Hellström +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/xe/display/xe_display_bo.c | 3 ++- + drivers/gpu/drm/xe/display/xe_fb_pin.c | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/xe/display/xe_display_bo.c ++++ b/drivers/gpu/drm/xe/display/xe_display_bo.c +@@ -42,7 +42,8 @@ static int xe_display_bo_framebuffer_ini + if (ret) + goto err; + +- if (!(bo->flags & XE_BO_FLAG_FORCE_WC)) { ++ if (!(bo->flags & XE_BO_FLAG_FORCE_WC) && ++ bo->ttm.type != ttm_bo_type_sg) { + /* + * XE_BO_FLAG_FORCE_WC should ideally be set at creation, or is + * automatically set when creating FB. We cannot change caching +--- a/drivers/gpu/drm/xe/display/xe_fb_pin.c ++++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c +@@ -481,7 +481,8 @@ int intel_plane_pin_fb(struct intel_plan + return 0; + + /* We reject creating !SCANOUT fb's, so this is weird.. */ +- drm_WARN_ON(bo->ttm.base.dev, !(bo->flags & XE_BO_FLAG_FORCE_WC)); ++ drm_WARN_ON(bo->ttm.base.dev, !(bo->flags & XE_BO_FLAG_FORCE_WC) && ++ bo->ttm.type != ttm_bo_type_sg); + + vma = __xe_pin_fb_vma(intel_fb, &new_plane_state->view.gtt, alignment); + diff --git a/queue-7.1/drm-xe-guc-fix-buffer-overflow-in-steered-register-list-allocation.patch b/queue-7.1/drm-xe-guc-fix-buffer-overflow-in-steered-register-list-allocation.patch new file mode 100644 index 0000000000..7a6cb2cc0e --- /dev/null +++ b/queue-7.1/drm-xe-guc-fix-buffer-overflow-in-steered-register-list-allocation.patch @@ -0,0 +1,65 @@ +From 632ecc90e1ca5d3b6822bb4d08f84a175b6c42c0 Mon Sep 17 00:00:00 2001 +From: Tejas Upadhyay +Date: Fri, 12 Jun 2026 12:34:02 +0530 +Subject: drm/xe/guc: Fix buffer overflow in steered register list allocation + +From: Tejas Upadhyay + +commit 632ecc90e1ca5d3b6822bb4d08f84a175b6c42c0 upstream. + +The size calculation for the steered register extarray uses only the +geometry DSS mask (g_dss_mask) to determine the number of entries to +allocate: + + total = bitmap_weight(gt->fuse_topo.g_dss_mask, ...) * steer_reg_num; + +However, the filling loop uses for_each_dss_steering(), which iterates +over for_each_dss(), defined as the union of g_dss_mask and c_dss_mask +(geometry + compute DSS). On platforms with compute-only DSS bits, the +loop writes past the allocated buffer, corrupting adjacent slab objects. + +This manifests as list_del corruption and SLUB redzone overwrites during +drm_managed_release on device unbind, since the overflow corrupts the +drmres list_head of neighboring allocations. + +Fix by computing the allocation size using the union of both DSS masks, +matching the iteration pattern of for_each_dss_steering(). + +-- +v2: +- use bitmap_weighted_or() (Zhanjun) + +Fixes: b170d696c1e2 ("drm/xe/guc: Add XE_LP steered register lists") +Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/8049 +Cc: Zhanjun Dong +Cc: stable@vger.kernel.org +Assisted-by: GitHub-Copilot:claude-opus-4.6 +Reviewed-by: Zhanjun Dong +Link: https://patch.msgid.link/20260612070401.543305-2-tejas.upadhyay@intel.com +Signed-off-by: Tejas Upadhyay +(cherry picked from commit 0a78a44f4901aa6c9263e66be7fce02282f1109f) +Signed-off-by: Matthew Brost +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/xe/xe_guc_capture.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/xe/xe_guc_capture.c ++++ b/drivers/gpu/drm/xe/xe_guc_capture.c +@@ -461,8 +461,14 @@ static void guc_capture_alloc_steered_li + if (!list || guc->capture->extlists) + return; + +- total = bitmap_weight(gt->fuse_topo.g_dss_mask, sizeof(gt->fuse_topo.g_dss_mask) * 8) * +- guc_capture_get_steer_reg_num(guc_to_xe(guc)); ++ { ++ xe_dss_mask_t all_dss; ++ ++ total = bitmap_weighted_or(all_dss, gt->fuse_topo.g_dss_mask, ++ gt->fuse_topo.c_dss_mask, ++ XE_MAX_DSS_FUSE_BITS) * ++ guc_capture_get_steer_reg_num(guc_to_xe(guc)); ++ } + + if (!total) + return; diff --git a/queue-7.1/series b/queue-7.1/series index c9542bb021..fe805ad4df 100644 --- a/queue-7.1/series +++ b/queue-7.1/series @@ -378,3 +378,23 @@ drm-amdgpu-gfx-fix-cleaner-shader-ib-buffer-overflow.patch drm-amdgpu-uvd-fix-forcing-msg-fb-bos-into-vcpu-segment-when-it-isn-t-at-0-v2.patch drm-amdgpu-uvd-place-vcpu-bo-only-in-vram-for-uvd-4.x-and-older.patch drm-amdgpu-check-amdgpu_vm_bo_find-result-in-get_mapping_info.patch +drm-sysfb-do-not-page-align-visible-size-of-the-framebuffer.patch +drm-sysfb-avoid-truncating-maximum-stride.patch +drm-xe-guc-fix-buffer-overflow-in-steered-register-list-allocation.patch +drm-xe-add-compact-pt-and-addr-mask-handling-for-page-reclaim.patch +drm-amd-display-restore-periodic-detection-for-dcn35.patch +drm-amdgpu-gfx9-fix-ring-and-ib-test-fail-after-mode2.patch +drm-amdgpu-fix-amdgpu_bo_move-when-old_mem-and-new_mem-are-both-gtt.patch +drm-amdgpu-fix-context-pstate-override-handling.patch +drm-amdgpu-validate-cp_gfx_shadow-chunk-size-in-cs-pass1.patch +drm-nouveau-fix-reversed-error-cleanup-order-in-ucopy-functions.patch +drm-sysfb-avoid-possible-truncation-with-calculating-visible-size.patch +drm-sysfb-return-errno-code-from-drm_sysfb_get_visible_size.patch +drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch +drm-amdkfd-use-exclusive-bounds-for-svm-split-alignment-checks.patch +drm-displayid-fix-tiled-display-topology-id-size.patch +drm-i915-gem-add-missing-nospec-on-parallel-submit-slot.patch +drm-i915-mtl-enable-pps-before-pll.patch +drm-nouveau-acr-fix-missing-nvkm_done-in-error-path-of-nvkm_acr_oneinit.patch +drm-radeon-fix-r100_copy_blit-for-large-bos.patch +drm-xe-display-skip-force_wc-and-vm_bound-check-for-external-dma-bufs.patch