From c34e08ba6c0037a72a7433741225b020c989e4ae Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 23 Sep 2025 07:04:40 -0700 Subject: [PATCH 01/44] drm/msm: Fix GEM free for imported dma-bufs Imported dma-bufs also have obj->resv != &obj->_resv. So we should check both this condition in addition to flags for handling the _NO_SHARE case. Fixes this splat that was reported with IRIS video playback: ------------[ cut here ]------------ WARNING: CPU: 3 PID: 2040 at drivers/gpu/drm/msm/msm_gem.c:1127 msm_gem_free_object+0x1f8/0x264 [msm] CPU: 3 UID: 1000 PID: 2040 Comm: .gnome-shell-wr Not tainted 6.17.0-rc7 #1 PREEMPT pstate: 81400005 (Nzcv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--) pc : msm_gem_free_object+0x1f8/0x264 [msm] lr : msm_gem_free_object+0x138/0x264 [msm] sp : ffff800092a1bb30 x29: ffff800092a1bb80 x28: ffff800092a1bce8 x27: ffffbc702dbdbe08 x26: 0000000000000008 x25: 0000000000000009 x24: 00000000000000a6 x23: ffff00083c72f850 x22: ffff00083c72f868 x21: ffff00087e69f200 x20: ffff00087e69f330 x19: ffff00084d157ae0 x18: 0000000000000000 x17: 0000000000000000 x16: ffffbc704bd46b80 x15: 0000ffffd0959540 x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000 x11: ffffbc702e6cdb48 x10: 0000000000000000 x9 : 000000000000003f x8 : ffff800092a1ba90 x7 : 0000000000000000 x6 : 0000000000000020 x5 : ffffbc704bd46c40 x4 : fffffdffe102cf60 x3 : 0000000000400032 x2 : 0000000000020000 x1 : ffff00087e6978e8 x0 : ffff00087e6977e8 Call trace: msm_gem_free_object+0x1f8/0x264 [msm] (P) drm_gem_object_free+0x1c/0x30 [drm] drm_gem_object_handle_put_unlocked+0x138/0x150 [drm] drm_gem_object_release_handle+0x5c/0xcc [drm] drm_gem_handle_delete+0x68/0xbc [drm] drm_gem_close_ioctl+0x34/0x40 [drm] drm_ioctl_kernel+0xc0/0x130 [drm] drm_ioctl+0x360/0x4e0 [drm] __arm64_sys_ioctl+0xac/0x104 invoke_syscall+0x48/0x104 el0_svc_common.constprop.0+0x40/0xe0 do_el0_svc+0x1c/0x28 el0_svc+0x34/0xec el0t_64_sync_handler+0xa0/0xe4 el0t_64_sync+0x198/0x19c ---[ end trace 0000000000000000 ]--- ------------[ cut here ]------------ Reported-by: Stephan Gerhold Fixes: de651b6e040b ("drm/msm: Fix refcnt underflow in error path") Signed-off-by: Rob Clark Tested-by: Stephan Gerhold Tested-by: Luca Weiss Tested-by: Bryan O'Donoghue # qrb5165-rb5 Patchwork: https://patchwork.freedesktop.org/patch/676273/ Message-ID: <20250923140441.746081-1-robin.clark@oss.qualcomm.com> --- drivers/gpu/drm/msm/msm_gem.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index e6cb51f21d97..a9d21a7b8984 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -1121,12 +1121,16 @@ static void msm_gem_free_object(struct drm_gem_object *obj) put_pages(obj); } - if (obj->resv != &obj->_resv) { + /* + * In error paths, we could end up here before msm_gem_new_handle() + * has changed obj->resv to point to the shared resv. In this case, + * we don't want to drop a ref to the shared r_obj that we haven't + * taken yet. + */ + if ((msm_obj->flags & MSM_BO_NO_SHARE) && (obj->resv != &obj->_resv)) { struct drm_gem_object *r_obj = container_of(obj->resv, struct drm_gem_object, _resv); - WARN_ON(!(msm_obj->flags & MSM_BO_NO_SHARE)); - /* Drop reference we hold to shared resv obj: */ drm_gem_object_put(r_obj); } From 830d68f2cb8ab6fb798bb9555016709a9e012af0 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 6 Oct 2025 08:35:41 -0700 Subject: [PATCH 02/44] drm/msm: Fix pgtable prealloc error path The following splat was reported: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010 Mem abort info: ESR = 0x0000000096000004 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 FSC = 0x04: level 0 translation fault Data abort info: ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000 CM = 0, WnR = 0, TnD = 0, TagAccess = 0 GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 user pgtable: 4k pages, 48-bit VAs, pgdp=00000008d0fd8000 [0000000000000010] pgd=0000000000000000, p4d=0000000000000000 Internal error: Oops: 0000000096000004 [#1] SMP CPU: 5 UID: 1000 PID: 149076 Comm: Xwayland Tainted: G S 6.16.0-rc2-00809-g0b6974bb4134-dirty #367 PREEMPT Tainted: [S]=CPU_OUT_OF_SPEC Hardware name: Qualcomm Technologies, Inc. SM8650 HDK (DT) pstate: 83400005 (Nzcv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--) pc : build_detached_freelist+0x28/0x224 lr : kmem_cache_free_bulk.part.0+0x38/0x244 sp : ffff000a508c7a20 x29: ffff000a508c7a20 x28: ffff000a508c7d50 x27: ffffc4e49d16f350 x26: 0000000000000058 x25: 00000000fffffffc x24: 0000000000000000 x23: ffff00098c4e1450 x22: 00000000fffffffc x21: 0000000000000000 x20: ffff000a508c7af8 x19: 0000000000000002 x18: 00000000000003e8 x17: ffff000809523850 x16: ffff000809523820 x15: 0000000000401640 x14: ffff000809371140 x13: 0000000000000130 x12: ffff0008b5711e30 x11: 00000000001058fa x10: 0000000000000a80 x9 : ffff000a508c7940 x8 : ffff000809371ba0 x7 : 781fffe033087fff x6 : 0000000000000000 x5 : ffff0008003cd000 x4 : 781fffe033083fff x3 : ffff000a508c7af8 x2 : fffffdffc0000000 x1 : 0001000000000000 x0 : ffff0008001a6a00 Call trace: build_detached_freelist+0x28/0x224 (P) kmem_cache_free_bulk.part.0+0x38/0x244 kmem_cache_free_bulk+0x10/0x1c msm_iommu_pagetable_prealloc_cleanup+0x3c/0xd0 msm_vma_job_free+0x30/0x240 msm_ioctl_vm_bind+0x1d0/0x9a0 drm_ioctl_kernel+0x84/0x104 drm_ioctl+0x358/0x4d4 __arm64_sys_ioctl+0x8c/0xe0 invoke_syscall+0x44/0x100 el0_svc_common.constprop.0+0x3c/0xe0 do_el0_svc+0x18/0x20 el0_svc+0x30/0x100 el0t_64_sync_handler+0x104/0x130 el0t_64_sync+0x170/0x174 Code: aa0203f5 b26287e2 f2dfbfe2 aa0303f4 (f8737ab6) ---[ end trace 0000000000000000 ]--- Since msm_vma_job_free() is called directly from the ioctl, this looks like an error path cleanup issue. Which I think results from prealloc_cleanup() called without a preceding successful prealloc_allocate() call. So handle that case better. Reported-by: Connor Abbott Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/678677/ Message-ID: <20251006153542.419998-1-robin.clark@oss.qualcomm.com> --- drivers/gpu/drm/msm/msm_iommu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index 0e18619f96cb..a188617653e8 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -338,6 +338,8 @@ msm_iommu_pagetable_prealloc_allocate(struct msm_mmu *mmu, struct msm_mmu_preall ret = kmem_cache_alloc_bulk(pt_cache, GFP_KERNEL, p->count, p->pages); if (ret != p->count) { + kfree(p->pages); + p->pages = NULL; p->count = ret; return -ENOMEM; } @@ -351,6 +353,9 @@ msm_iommu_pagetable_prealloc_cleanup(struct msm_mmu *mmu, struct msm_mmu_preallo struct kmem_cache *pt_cache = get_pt_cache(mmu); uint32_t remaining_pt_count = p->count - p->ptr; + if (!p->pages) + return; + if (p->count > 0) trace_msm_mmu_prealloc_cleanup(p->count, remaining_pt_count); From b4789aac9d3441d9f830f0a4022d8dc122d6cab3 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Thu, 11 Sep 2025 02:14:05 +0530 Subject: [PATCH 03/44] drm/msm/a6xx: Fix GMU firmware parser Current parser logic for GMU firmware assumes a dword aligned payload size for every block. This is not true for all GMU firmwares. So, fix this by using correct 'size' value in the calculation for the offset for the next block's header. Fixes: c6ed04f856a4 ("drm/msm/a6xx: A640/A650 GMU firmware path") Signed-off-by: Akhil P Oommen Acked-by: Konrad Dybcio Patchwork: https://patchwork.freedesktop.org/patch/674040/ Message-ID: <20250911-assorted-sept-1-v2-2-a8bf1ee20792@oss.qualcomm.com> Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index fc62fef2fed8..4e6dc16e4a4c 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -780,6 +780,9 @@ static bool fw_block_mem(struct a6xx_gmu_bo *bo, const struct block_header *blk) return true; } +#define NEXT_BLK(blk) \ + ((const struct block_header *)((const char *)(blk) + sizeof(*(blk)) + (blk)->size)) + static int a6xx_gmu_fw_load(struct a6xx_gmu *gmu) { struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); @@ -811,7 +814,7 @@ static int a6xx_gmu_fw_load(struct a6xx_gmu *gmu) for (blk = (const struct block_header *) fw_image->data; (const u8*) blk < fw_image->data + fw_image->size; - blk = (const struct block_header *) &blk->data[blk->size >> 2]) { + blk = NEXT_BLK(blk)) { if (blk->size == 0) continue; From 86404a9e3013d814a772ac407573be5d3cd4ee0d Mon Sep 17 00:00:00 2001 From: Anna Maniscalco Date: Sat, 11 Oct 2025 15:45:10 +0200 Subject: [PATCH 04/44] drm/msm: make sure last_fence is always updated Update last_fence in the vm-bind path instead of kernel managed path. last_fence is used to wait for work to finish in vm_bind contexts but not used for kernel managed contexts. This fixes a bug where last_fence is not waited on context close leading to faults as resources are freed while in use. Fixes: 92395af63a99 ("drm/msm: Add VM_BIND submitqueue") Signed-off-by: Anna Maniscalco Patchwork: https://patchwork.freedesktop.org/patch/680080/ Message-ID: <20251011-close_fence_wait_fix-v3-1-5134787755ff@gmail.com> Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gem_submit.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 3ab3b27134f9..75d9f3574370 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -414,6 +414,11 @@ static void submit_attach_object_fences(struct msm_gem_submit *submit) submit->user_fence, DMA_RESV_USAGE_BOOKKEEP, DMA_RESV_USAGE_BOOKKEEP); + + last_fence = vm->last_fence; + vm->last_fence = dma_fence_unwrap_merge(submit->user_fence, last_fence); + dma_fence_put(last_fence); + return; } @@ -427,10 +432,6 @@ static void submit_attach_object_fences(struct msm_gem_submit *submit) dma_resv_add_fence(obj->resv, submit->user_fence, DMA_RESV_USAGE_READ); } - - last_fence = vm->last_fence; - vm->last_fence = dma_fence_unwrap_merge(submit->user_fence, last_fence); - dma_fence_put(last_fence); } static int submit_bo(struct msm_gem_submit *submit, uint32_t idx, From 7f9335f2d99815199d9d8d8e6687e68989728ce3 Mon Sep 17 00:00:00 2001 From: Vignesh Raman Date: Mon, 13 Oct 2025 11:32:10 +0530 Subject: [PATCH 05/44] drm/ci: disable broken MR check in sanity job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GitLab recently changed the required permissions for the are-developers-allowed-to-push-to-my-MR check: https://gitlab.freedesktop.org/freedesktop/ci-templates/-/issues/81 Until that’s resolved, disable the check - it’s mostly obsolete anyway. Based on https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37782 Signed-off-by: Vignesh Raman Reviewed-by: Daniel Stone Patchwork: https://patchwork.freedesktop.org/patch/680263/ Message-ID: <20251013060212.14583-1-vignesh.raman@collabora.com> Signed-off-by: Rob Clark --- drivers/gpu/drm/ci/gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ci/gitlab-ci.yml b/drivers/gpu/drm/ci/gitlab-ci.yml index d502d146b177..56638814bb28 100644 --- a/drivers/gpu/drm/ci/gitlab-ci.yml +++ b/drivers/gpu/drm/ci/gitlab-ci.yml @@ -280,7 +280,7 @@ sanity: GIT_STRATEGY: none script: # ci-fairy check-commits --junit-xml=check-commits.xml - - ci-fairy check-merge-request --require-allow-collaboration --junit-xml=check-merge-request.xml + # - ci-fairy check-merge-request --require-allow-collaboration --junit-xml=check-merge-request.xml - | set -eu image_tags=( From 033559473dd3b55558b535aa37b8848c207b5cbb Mon Sep 17 00:00:00 2001 From: Akash Goel Date: Tue, 21 Oct 2025 17:09:51 +0100 Subject: [PATCH 06/44] dma-fence: Fix safe access wrapper to call timeline name method This commit fixes the wrapper function dma_fence_timeline_name(), that was added for safe access, to actually call the timeline name method of dma_fence_ops. Cc: # v6.17+ Signed-off-by: Akash Goel Fixes: 506aa8b02a8d ("dma-fence: Add safe access helpers and document the rules") Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin Link: https://lore.kernel.org/r/20251021160951.1415603-1-akash.goel@arm.com --- drivers/dma-buf/dma-fence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c index 3f78c56b58dc..39e6f93dc310 100644 --- a/drivers/dma-buf/dma-fence.c +++ b/drivers/dma-buf/dma-fence.c @@ -1141,7 +1141,7 @@ const char __rcu *dma_fence_timeline_name(struct dma_fence *fence) "RCU protection is required for safe access to returned string"); if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) - return fence->ops->get_driver_name(fence); + return fence->ops->get_timeline_name(fence); else return "signaled-timeline"; } From 73b7e48a87c79fd6df40aeafcd3994287e31e25f Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 22 Oct 2025 15:20:51 -0700 Subject: [PATCH 07/44] drm/msm: Reject MAP_NULL op if no PRR We need PRR support in order to implement MAP_NULL. Userspace shouldn't be trying to use this if it is unsupported. Reported-by: Valentine Burley Link: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37935#note_3153730 Signed-off-by: Rob Clark Tested-by: Valentine Burley Patchwork: https://patchwork.freedesktop.org/patch/682941/ Message-ID: <20251022222051.10030-1-robin.clark@oss.qualcomm.com> --- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 7 ------- drivers/gpu/drm/msm/msm_gem_vma.c | 6 ++++++ drivers/gpu/drm/msm/msm_gpu.h | 11 +++++++++++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index afaa3cfefd35..4b5a4edd0702 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -348,13 +348,6 @@ int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags, return 0; } -static bool -adreno_smmu_has_prr(struct msm_gpu *gpu) -{ - struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(&gpu->pdev->dev); - return adreno_smmu && adreno_smmu->set_prr_addr; -} - int adreno_get_param(struct msm_gpu *gpu, struct msm_context *ctx, uint32_t param, uint64_t *value, uint32_t *len) { diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c index 381a0853c05b..0d219454f0e6 100644 --- a/drivers/gpu/drm/msm/msm_gem_vma.c +++ b/drivers/gpu/drm/msm/msm_gem_vma.c @@ -964,6 +964,7 @@ static int lookup_op(struct msm_vm_bind_job *job, const struct drm_msm_vm_bind_op *op) { struct drm_device *dev = job->vm->drm; + struct msm_drm_private *priv = dev->dev_private; int i = job->nr_ops++; int ret = 0; @@ -1010,6 +1011,11 @@ lookup_op(struct msm_vm_bind_job *job, const struct drm_msm_vm_bind_op *op) break; } + if ((op->op == MSM_VM_BIND_OP_MAP_NULL) && + !adreno_smmu_has_prr(priv->gpu)) { + ret = UERR(EINVAL, dev, "PRR not supported\n"); + } + return ret; } diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index a597f2bee30b..2894fc118485 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -299,6 +299,17 @@ static inline struct msm_gpu *dev_to_gpu(struct device *dev) return container_of(adreno_smmu, struct msm_gpu, adreno_smmu); } +static inline bool +adreno_smmu_has_prr(struct msm_gpu *gpu) +{ + struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(&gpu->pdev->dev); + + if (!adreno_smmu) + return false; + + return adreno_smmu && adreno_smmu->set_prr_addr; +} + /* It turns out that all targets use the same ringbuffer size */ #define MSM_GPU_RINGBUFFER_SZ SZ_32K #define MSM_GPU_RINGBUFFER_BLKSIZE 32 From 00d5f09719aa6c37545be5c05d25a1eaf8f3da7e Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 22 Oct 2025 15:20:38 -0700 Subject: [PATCH 08/44] drm/msm: Ensure vm is created in VM_BIND ioctl Since the vm is lazily created, to allow userspace to opt-in to a VM_BIND context, we can't assume it is already created. Fixes: 2e6a8a1fe2b2 ("drm/msm: Add VM_BIND ioctl") Signed-off-by: Rob Clark Patchwork: https://patchwork.freedesktop.org/patch/682939/ Message-ID: <20251022222039.9937-1-robin.clark@oss.qualcomm.com> --- drivers/gpu/drm/msm/msm_gem_vma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c index 0d219454f0e6..c112a46a5484 100644 --- a/drivers/gpu/drm/msm/msm_gem_vma.c +++ b/drivers/gpu/drm/msm/msm_gem_vma.c @@ -1407,7 +1407,7 @@ msm_ioctl_vm_bind(struct drm_device *dev, void *data, struct drm_file *file) * Maybe we could allow just UNMAP ops? OTOH userspace should just * immediately close the device file and all will be torn down. */ - if (to_msm_vm(ctx->vm)->unusable) + if (to_msm_vm(msm_context_vm(dev, ctx))->unusable) return UERR(EPIPE, dev, "context is unusable"); /* From 14e02ed3876f4ab0ed6d3f41972175f8b8df3d70 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 17 Oct 2025 11:13:36 +0200 Subject: [PATCH 09/44] drm/sysfb: Do not dereference NULL pointer in plane reset The plane state in __drm_gem_reset_shadow_plane() can be NULL. Do not deref that pointer, but forward NULL to the other plane-reset helpers. Clears plane->state to NULL. v2: - fix typo in commit description (Javier) Signed-off-by: Thomas Zimmermann Fixes: b71565022031 ("drm/gem: Export implementation of shadow-plane helpers") Reported-by: Dan Carpenter Closes: https://lore.kernel.org/dri-devel/aPIDAsHIUHp_qSW4@stanley.mountain/ Cc: Thomas Zimmermann Cc: Melissa Wen Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: David Airlie Cc: Simona Vetter Cc: dri-devel@lists.freedesktop.org Cc: # v5.15+ Reviewed-by: Javier Martinez Canillas Link: https://patch.msgid.link/20251017091407.58488-1-tzimmermann@suse.de --- drivers/gpu/drm/drm_gem_atomic_helper.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_atomic_helper.c b/drivers/gpu/drm/drm_gem_atomic_helper.c index ebf305fb24f0..6fb55601252f 100644 --- a/drivers/gpu/drm/drm_gem_atomic_helper.c +++ b/drivers/gpu/drm/drm_gem_atomic_helper.c @@ -310,8 +310,12 @@ EXPORT_SYMBOL(drm_gem_destroy_shadow_plane_state); void __drm_gem_reset_shadow_plane(struct drm_plane *plane, struct drm_shadow_plane_state *shadow_plane_state) { - __drm_atomic_helper_plane_reset(plane, &shadow_plane_state->base); - drm_format_conv_state_init(&shadow_plane_state->fmtcnv_state); + if (shadow_plane_state) { + __drm_atomic_helper_plane_reset(plane, &shadow_plane_state->base); + drm_format_conv_state_init(&shadow_plane_state->fmtcnv_state); + } else { + __drm_atomic_helper_plane_reset(plane, NULL); + } } EXPORT_SYMBOL(__drm_gem_reset_shadow_plane); From d25e3a610bae03bffc5c14b5d944a5d0cd844678 Mon Sep 17 00:00:00 2001 From: Philipp Stanner Date: Wed, 22 Oct 2025 08:34:03 +0200 Subject: [PATCH 10/44] drm/sched: Fix race in drm_sched_entity_select_rq() In a past bug fix it was forgotten that entity access must be protected by the entity lock. That's a data race and potentially UB. Move the spin_unlock() to the appropriate position. Cc: stable@vger.kernel.org # v5.13+ Fixes: ac4eb83ab255 ("drm/sched: select new rq even if there is only one v3") Reviewed-by: Tvrtko Ursulin Signed-off-by: Philipp Stanner Link: https://patch.msgid.link/20251022063402.87318-2-phasta@kernel.org --- drivers/gpu/drm/scheduler/sched_entity.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index 5a4697f636f2..aa222166de58 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -552,10 +552,11 @@ void drm_sched_entity_select_rq(struct drm_sched_entity *entity) drm_sched_rq_remove_entity(entity->rq, entity); entity->rq = rq; } - spin_unlock(&entity->lock); if (entity->num_sched_list == 1) entity->sched_list = NULL; + + spin_unlock(&entity->lock); } /** From e0023c8a74028739643aa14bd201c41a99866ca4 Mon Sep 17 00:00:00 2001 From: Philipp Stanner Date: Fri, 24 Oct 2025 18:12:22 +0200 Subject: [PATCH 11/44] drm/nouveau: Fix race in nouveau_sched_fini() nouveau_sched_fini() uses a memory barrier before wait_event(). wait_event(), however, is a macro which expands to a loop which might check the passed condition several times. The barrier would only take effect for the first check. Replace the barrier with a function which takes the spinlock. Cc: stable@vger.kernel.org # v6.8+ Fixes: 5f03a507b29e ("drm/nouveau: implement 1:1 scheduler - entity relationship") Acked-by: Danilo Krummrich Signed-off-by: Philipp Stanner Link: https://patch.msgid.link/20251024161221.196155-2-phasta@kernel.org --- drivers/gpu/drm/nouveau/nouveau_sched.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.c b/drivers/gpu/drm/nouveau/nouveau_sched.c index e60f7892f5ce..a7bf539e5d86 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sched.c +++ b/drivers/gpu/drm/nouveau/nouveau_sched.c @@ -482,6 +482,17 @@ nouveau_sched_create(struct nouveau_sched **psched, struct nouveau_drm *drm, return 0; } +static bool +nouveau_sched_job_list_empty(struct nouveau_sched *sched) +{ + bool empty; + + spin_lock(&sched->job.list.lock); + empty = list_empty(&sched->job.list.head); + spin_unlock(&sched->job.list.lock); + + return empty; +} static void nouveau_sched_fini(struct nouveau_sched *sched) @@ -489,8 +500,7 @@ nouveau_sched_fini(struct nouveau_sched *sched) struct drm_gpu_scheduler *drm_sched = &sched->base; struct drm_sched_entity *entity = &sched->entity; - rmb(); /* for list_empty to work without lock */ - wait_event(sched->job.wq, list_empty(&sched->job.list.head)); + wait_event(sched->job.wq, nouveau_sched_job_list_empty(sched)); drm_sched_entity_fini(entity); drm_sched_fini(drm_sched); From a042beac6e6f8ac1e923784cfff98b47cbabb185 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Tue, 21 Oct 2025 11:37:23 +0200 Subject: [PATCH 12/44] drm/etnaviv: fix flush sequence logic The current logic uses the flush sequence from the current address space. This is harmless when deducing the flush requirements for the current submit, as either the incoming address space is the same one as the currently active one or we switch context, in which case the flush is unconditional. However, this sequence is also stored as the current flush sequence of the GPU. If we switch context the stored flush sequence will no longer belong to the currently active address space. This incoherency can then cause missed flushes, resulting in translation errors. Fixes: 27b67278e007 ("drm/etnaviv: rework MMU handling") Signed-off-by: Tomeu Vizoso Signed-off-by: Lucas Stach Reviewed-by: Christian Gmeiner Link: https://lore.kernel.org/r/20251021093723.3887980-1-l.stach@pengutronix.de --- drivers/gpu/drm/etnaviv/etnaviv_buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c index b13a17276d07..88385dc3b30d 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c @@ -347,7 +347,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state, u32 link_target, link_dwords; bool switch_context = gpu->exec_state != exec_state; bool switch_mmu_context = gpu->mmu_context != mmu_context; - unsigned int new_flush_seq = READ_ONCE(gpu->mmu_context->flush_seq); + unsigned int new_flush_seq = READ_ONCE(mmu_context->flush_seq); bool need_flush = switch_mmu_context || gpu->flush_seq != new_flush_seq; bool has_blt = !!(gpu->identity.minor_features5 & chipMinorFeatures5_BLT_ENGINE); From 9e8b3201c7302d5b522ba3535630bed21cc03c27 Mon Sep 17 00:00:00 2001 From: David Rosca Date: Wed, 15 Oct 2025 16:01:28 +0200 Subject: [PATCH 13/44] drm/sched: avoid killing parent entity on child SIGKILL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DRM scheduler tracks who last uses an entity and when that process is killed blocks all further submissions to that entity. The problem is that we didn't track who initially created an entity, so when a process accidently leaked its file descriptor to a child and that child got killed, we killed the parent's entities. Avoid that and instead initialize the entities last user on entity creation. This also allows to drop the extra NULL check. Signed-off-by: David Rosca Signed-off-by: Christian König Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4568 Reviewed-by: Alex Deucher CC: stable@vger.kernel.org Acked-by: Philipp Stanner Link: https://lore.kernel.org/r/20251015140128.1470-1-christian.koenig@amd.com Signed-off-by: Philipp Stanner Link: https://patch.msgid.link/20251015140128.1470-1-christian.koenig@amd.com --- drivers/gpu/drm/scheduler/sched_entity.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index aa222166de58..c8e949f4a568 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -70,6 +70,7 @@ int drm_sched_entity_init(struct drm_sched_entity *entity, entity->guilty = guilty; entity->num_sched_list = num_sched_list; entity->priority = priority; + entity->last_user = current->group_leader; /* * It's perfectly valid to initialize an entity without having a valid * scheduler attached. It's just not valid to use the scheduler before it @@ -302,7 +303,7 @@ long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout) /* For a killed process disallow further enqueueing of jobs. */ last_user = cmpxchg(&entity->last_user, current->group_leader, NULL); - if ((!last_user || last_user == current->group_leader) && + if (last_user == current->group_leader && (current->flags & PF_EXITING) && (current->exit_code == SIGKILL)) drm_sched_entity_kill(entity); From 926d002e6d7e2f1fd5c1b53cf6208153ee7d380d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Oct 2025 11:39:37 +0200 Subject: [PATCH 14/44] drm/mediatek: Fix device use-after-free on unbind A recent change fixed device reference leaks when looking up drm platform device driver data during bind() but failed to remove a partial fix which had been added by commit 80805b62ea5b ("drm/mediatek: Fix kobject put for component sub-drivers"). This results in a reference imbalance on component bind() failures and on unbind() which could lead to a user-after-free. Make sure to only drop the references after retrieving the driver data by effectively reverting the previous partial fix. Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference. Fixes: 1f403699c40f ("drm/mediatek: Fix device/node reference count leaks in mtk_drm_get_all_drm_priv") Reported-by: Sjoerd Simons Closes: https://lore.kernel.org/r/20251003-mtk-drm-refcount-v1-1-3b3f2813b0db@collabora.com Cc: stable@vger.kernel.org Cc: Ma Ke Cc: AngeloGioacchino Del Regno Signed-off-by: Johan Hovold Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Sjoerd Simons Tested-by: Sjoerd Simons Tested-by: Ritesh Raj Sarraf Reviewed-by: CK Hu Link: https://patchwork.kernel.org/project/dri-devel/patch/20251006093937.27869-1-johan@kernel.org/ Signed-off-by: Chun-Kuang Hu --- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index eb5537f0ac90..31ff2922758a 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -686,10 +686,6 @@ err_free: for (i = 0; i < private->data->mmsys_dev_num; i++) private->all_drm_private[i]->drm = NULL; err_put_dev: - for (i = 0; i < private->data->mmsys_dev_num; i++) { - /* For device_find_child in mtk_drm_get_all_priv() */ - put_device(private->all_drm_private[i]->dev); - } put_device(private->mutex_dev); return ret; } @@ -697,18 +693,12 @@ err_put_dev: static void mtk_drm_unbind(struct device *dev) { struct mtk_drm_private *private = dev_get_drvdata(dev); - int i; /* for multi mmsys dev, unregister drm dev in mmsys master */ if (private->drm_master) { drm_dev_unregister(private->drm); mtk_drm_kms_deinit(private->drm); drm_dev_put(private->drm); - - for (i = 0; i < private->data->mmsys_dev_num; i++) { - /* For device_find_child in mtk_drm_get_all_priv() */ - put_device(private->all_drm_private[i]->dev); - } put_device(private->mutex_dev); } private->mtk_drm_bound = false; From ba10f8d92a2c026b1052b4c0fa2cd7538838c965 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 16 Oct 2025 13:55:27 -0500 Subject: [PATCH 15/44] drm/amd: Check that VPE has reached DPM0 in idle handler [Why] Newer VPE microcode has functionality that will decrease DPM level only when a workload has run for 2 or more seconds. If VPE is turned off before this DPM decrease and the PMFW doesn't reset it when power gating VPE, the SOC can get stuck with a higher DPM level. This can happen from amdgpu's ring buffer test because it's a short quick workload for VPE and VPE is turned off after 1s. [How] In idle handler besides checking fences are drained check PMFW version to determine if it will reset DPM when power gating VPE. If PMFW will not do this, then check VPE DPM level. If it is not DPM0 reschedule delayed work again until it is. v2: squash in return fix (Alex) Cc: Peyton.Lee@amd.com Reported-by: Sultan Alsawaf Reviewed-by: Sultan Alsawaf Tested-by: Sultan Alsawaf Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4615 Reviewed-by: Lijo Lazar Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher (cherry picked from commit 3ac635367eb589bee8edcc722f812a89970e14b7) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c | 34 ++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c index 474bfe36c0c2..aa78c2ee9e21 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c @@ -322,6 +322,26 @@ static int vpe_early_init(struct amdgpu_ip_block *ip_block) return 0; } +static bool vpe_need_dpm0_at_power_down(struct amdgpu_device *adev) +{ + switch (amdgpu_ip_version(adev, VPE_HWIP, 0)) { + case IP_VERSION(6, 1, 1): + return adev->pm.fw_version < 0x0a640500; + default: + return false; + } +} + +static int vpe_get_dpm_level(struct amdgpu_device *adev) +{ + struct amdgpu_vpe *vpe = &adev->vpe; + + if (!adev->pm.dpm_enabled) + return 0; + + return RREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_request_lv)); +} + static void vpe_idle_work_handler(struct work_struct *work) { struct amdgpu_device *adev = @@ -329,11 +349,17 @@ static void vpe_idle_work_handler(struct work_struct *work) unsigned int fences = 0; fences += amdgpu_fence_count_emitted(&adev->vpe.ring); + if (fences) + goto reschedule; - if (fences == 0) - amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VPE, AMD_PG_STATE_GATE); - else - schedule_delayed_work(&adev->vpe.idle_work, VPE_IDLE_TIMEOUT); + if (vpe_need_dpm0_at_power_down(adev) && vpe_get_dpm_level(adev) != 0) + goto reschedule; + + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VPE, AMD_PG_STATE_GATE); + return; + +reschedule: + schedule_delayed_work(&adev->vpe.idle_work, VPE_IDLE_TIMEOUT); } static int vpe_common_init(struct amdgpu_vpe *vpe) From 3328443363a0895fd9c096edfe8ecd372ca9145e Mon Sep 17 00:00:00 2001 From: Daniel Palmer Date: Sat, 18 Oct 2025 14:44:50 +0900 Subject: [PATCH 16/44] drm/radeon: Do not kfree() devres managed rdev Since the allocation of the drivers main structure was changed to devm_drm_dev_alloc() rdev is managed by devres and we shouldn't be calling kfree() on it. This fixes things exploding if the driver probe fails and devres cleans up the rdev after we already free'd it. Fixes: a9ed2f052c5c ("drm/radeon: change drm_dev_alloc to devm_drm_dev_alloc") Signed-off-by: Daniel Palmer Signed-off-by: Alex Deucher (cherry picked from commit 16c0681617b8a045773d4d87b6140002fa75b03b) --- drivers/gpu/drm/radeon/radeon_kms.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 645e33bf7947..ba1446acd703 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -84,7 +84,6 @@ void radeon_driver_unload_kms(struct drm_device *dev) rdev->agp = NULL; done_free: - kfree(rdev); dev->dev_private = NULL; } From 745bae76acdd71709773c129a69deca01036250b Mon Sep 17 00:00:00 2001 From: Daniel Palmer Date: Sat, 18 Oct 2025 14:44:51 +0900 Subject: [PATCH 17/44] drm/radeon: Remove calls to drm_put_dev() Since the allocation of the drivers main structure was changed to devm_drm_dev_alloc() drm_put_dev()'ing to trigger it to be free'd should be done by devres. However, drm_put_dev() is still in the probe error and device remove paths. When the driver fails to probe warnings like the following are shown because devres is trying to drm_put_dev() after the driver already did it. [ 5.642230] radeon 0000:01:05.0: probe with driver radeon failed with error -22 [ 5.649605] ------------[ cut here ]------------ [ 5.649607] refcount_t: underflow; use-after-free. [ 5.649620] WARNING: CPU: 0 PID: 357 at lib/refcount.c:28 refcount_warn_saturate+0xbe/0x110 Fixes: a9ed2f052c5c ("drm/radeon: change drm_dev_alloc to devm_drm_dev_alloc") Signed-off-by: Daniel Palmer Signed-off-by: Alex Deucher (cherry picked from commit 3eb8c0b4c091da0a623ade0d3ee7aa4a93df1ea4) --- drivers/gpu/drm/radeon/radeon_drv.c | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 88e821d67af7..9c8907bc61d9 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -314,17 +314,17 @@ static int radeon_pci_probe(struct pci_dev *pdev, ret = pci_enable_device(pdev); if (ret) - goto err_free; + return ret; pci_set_drvdata(pdev, ddev); ret = radeon_driver_load_kms(ddev, flags); if (ret) - goto err_agp; + goto err; ret = drm_dev_register(ddev, flags); if (ret) - goto err_agp; + goto err; if (rdev->mc.real_vram_size <= (8 * 1024 * 1024)) format = drm_format_info(DRM_FORMAT_C8); @@ -337,30 +337,14 @@ static int radeon_pci_probe(struct pci_dev *pdev, return 0; -err_agp: +err: pci_disable_device(pdev); -err_free: - drm_dev_put(ddev); return ret; } -static void -radeon_pci_remove(struct pci_dev *pdev) -{ - struct drm_device *dev = pci_get_drvdata(pdev); - - drm_put_dev(dev); -} - static void radeon_pci_shutdown(struct pci_dev *pdev) { - /* if we are running in a VM, make sure the device - * torn down properly on reboot/shutdown - */ - if (radeon_device_is_virtual()) - radeon_pci_remove(pdev); - #if defined(CONFIG_PPC64) || defined(CONFIG_MACH_LOONGSON64) /* * Some adapters need to be suspended before a @@ -613,7 +597,6 @@ static struct pci_driver radeon_kms_pci_driver = { .name = DRIVER_NAME, .id_table = pciidlist, .probe = radeon_pci_probe, - .remove = radeon_pci_remove, .shutdown = radeon_pci_shutdown, .driver.pm = &radeon_pm_ops, }; From 5d7b36d1bffce8340b37cbba95ef743ed3adaefd Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Fri, 28 Mar 2025 10:34:57 +0800 Subject: [PATCH 18/44] drm/amd/display: pause the workload setting in dm v1: Pause the workload setting in dm when doinn idle optimization v2: Rebase patch to latest kernel code base (kernel 6.16) Reviewed-by: Alex Deucher Signed-off-by: Kenneth Feng Signed-off-by: Alex Deucher Signed-off-by: Yang Wang Signed-off-by: Alex Deucher (cherry picked from commit bc6d54ac7e7436721a19443265f971f890c13cc5) --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c index 1ec9d03ad747..f08121a2b838 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -248,6 +248,8 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work) struct vblank_control_work *vblank_work = container_of(work, struct vblank_control_work, work); struct amdgpu_display_manager *dm = vblank_work->dm; + struct amdgpu_device *adev = drm_to_adev(dm->ddev); + int r; mutex_lock(&dm->dc_lock); @@ -277,7 +279,16 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work) if (dm->active_vblank_irq_count == 0) { dc_post_update_surfaces_to_stream(dm->dc); + + r = amdgpu_dpm_pause_power_profile(adev, true); + if (r) + dev_warn(adev->dev, "failed to set default power profile mode\n"); + dc_allow_idle_optimizations(dm->dc, true); + + r = amdgpu_dpm_pause_power_profile(adev, false); + if (r) + dev_warn(adev->dev, "failed to restore the power profile mode\n"); } mutex_unlock(&dm->dc_lock); From 382bd6a792836875da555fe9a2b51222b813fed1 Mon Sep 17 00:00:00 2001 From: Matthew Schwartz Date: Mon, 20 Oct 2025 16:09:34 -0700 Subject: [PATCH 19/44] drm/amd/display: Don't program BLNDGAM_MEM_PWR_FORCE when CM low-power is disabled on DCN30 Before commit 33056a97ae5e ("drm/amd/display: Remove double checks for `debug.enable_mem_low_power.bits.cm`"), dpp3_program_blnd_lut(NULL) checked the low-power debug flag before calling dpp3_power_on_blnd_lut(false). After commit 33056a97ae5e ("drm/amd/display: Remove double checks for `debug.enable_mem_low_power.bits.cm`"), dpp3_program_blnd_lut(NULL) unconditionally calls dpp3_power_on_blnd_lut(false). The BLNDGAM power helper writes BLNDGAM_MEM_PWR_FORCE when CM low-power is disabled, causing immediate SRAM power toggles instead of deferring at vupdate. This can disrupt atomic color/LUT sequencing during transitions between direct scanout and composition within gamescope's DRM backend on Steam Deck OLED. To fix this, leave the BLNDGAM power state unchanged when low-power is disabled, matching dpp3_power_on_hdr3dlut and dpp3_power_on_shaper. Fixes: 33056a97ae5e ("drm/amd/display: Remove double checks for `debug.enable_mem_low_power.bits.cm`") Signed-off-by: Matthew Schwartz Reviewed-by: Harry Wentland Reviewed-by: Mario Limonciello Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher (cherry picked from commit 13ff4f63fcddfc84ec8632f1443936b00aa26725) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c index 09be2a90cc79..4f569cd8a5d6 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c @@ -578,9 +578,6 @@ static void dpp3_power_on_blnd_lut( dpp_base->ctx->dc->optimized_required = true; dpp_base->deferred_reg_writes.bits.disable_blnd_lut = true; } - } else { - REG_SET(CM_MEM_PWR_CTRL, 0, - BLNDGAM_MEM_PWR_FORCE, power_on == true ? 0 : 1); } } From 238d468d3ed18a324bb9d8c99f18c665dbac0511 Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Wed, 22 Oct 2025 14:12:21 +0800 Subject: [PATCH 20/44] drm/amd/pm: fix smu table id bound check issue in smu_cmn_update_table() 'table_index' is a variable defined by the smu driver (kmd) 'table_id' is a variable defined by the hw smu (pmfw) This code should use table_index as a bounds check. Fixes: caad2613dc4bd ("drm/amd/powerplay: move table setting common code to smu_cmn.c") Signed-off-by: Yang Wang Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher (cherry picked from commit fca0c66b22303de0d1d6313059baf4dc960a4753) --- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index f532f7c69259..a8961a8f5c42 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -969,7 +969,7 @@ int smu_cmn_update_table(struct smu_context *smu, table_index); uint32_t table_size; int ret = 0; - if (!table_data || table_id >= SMU_TABLE_COUNT || table_id < 0) + if (!table_data || table_index >= SMU_TABLE_COUNT || table_id < 0) return -EINVAL; table_size = smu_table->tables[table_index].size; From 07a13f913c291d6ec72ee4fc848d13ecfdc0e705 Mon Sep 17 00:00:00 2001 From: John Smith Date: Tue, 21 Oct 2025 11:08:13 +0200 Subject: [PATCH 21/44] drm/amd/pm/powerplay/smumgr: Fix PCIeBootLinkLevel value on Fiji Previously this was initialized with zero which represented PCIe Gen 1.0 instead of using the maximum value from the speed table which is the behaviour of all other smumgr implementations. Fixes: 18edef19ea44 ("drm/amd/powerplay: implement fw image related smu interface for Fiji.") Signed-off-by: John Smith Signed-off-by: Alex Deucher (cherry picked from commit c52238c9fb414555c68340cd80e487d982c1921c) --- drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c index d2dbd90bb427..0a876c840c79 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c @@ -2024,7 +2024,7 @@ static int fiji_init_smc_table(struct pp_hwmgr *hwmgr) table->VoltageResponseTime = 0; table->PhaseResponseTime = 0; table->MemoryThermThrottleEnable = 1; - table->PCIeBootLinkLevel = 0; /* 0:Gen1 1:Gen2 2:Gen3*/ + table->PCIeBootLinkLevel = (uint8_t) (data->dpm_table.pcie_speed_table.count); table->PCIeGenInterval = 1; table->VRConfig = 0; From 501672e3c1576aa9a8364144213c77b98a31a42c Mon Sep 17 00:00:00 2001 From: John Smith Date: Tue, 21 Oct 2025 11:09:09 +0200 Subject: [PATCH 22/44] drm/amd/pm/powerplay/smumgr: Fix PCIeBootLinkLevel value on Iceland Previously this was initialized with zero which represented PCIe Gen 1.0 instead of using the maximum value from the speed table which is the behaviour of all other smumgr implementations. Fixes: 18aafc59b106 ("drm/amd/powerplay: implement fw related smu interface for iceland.") Signed-off-by: John Smith Signed-off-by: Alex Deucher (cherry picked from commit 92b0a6ae6672857ddeabf892223943d2f0e06c97) --- drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c index 1f50f1e74c48..aa3ae9b115c4 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c @@ -2028,7 +2028,7 @@ static int iceland_init_smc_table(struct pp_hwmgr *hwmgr) table->VoltageResponseTime = 0; table->PhaseResponseTime = 0; table->MemoryThermThrottleEnable = 1; - table->PCIeBootLinkLevel = 0; + table->PCIeBootLinkLevel = (uint8_t) (data->dpm_table.pcie_speed_table.count); table->PCIeGenInterval = 1; result = iceland_populate_smc_svi2_config(hwmgr, table); From f3b37ebf2c94e3a3d7bbf5e3788ad86cf30fc7be Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 22 Oct 2025 09:12:54 -0400 Subject: [PATCH 23/44] drm/amdgpu: fix SPDX headers on amdgpu_cper.c/h These should be MIT. The driver in general is MIT and the license text at the top of the files is MIT so fix it. Fixes: 92d5d2a09de1 ("drm/amdgpu: Introduce funcs for populating CPER") Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4654 Reviewed-by: Mario Limonciello Signed-off-by: Alex Deucher (cherry picked from commit abd3f876404cafb107cb34bacb74706bfee11cbe) --- drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_cper.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c index ef996493115f..425a3e564360 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: MIT /* * Copyright 2025 Advanced Micro Devices, Inc. * diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.h index bcb97d245673..353421807387 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: MIT */ /* * Copyright 2025 Advanced Micro Devices, Inc. * From 964f8ff276a54ad7fb09168141fb6a8d891d548a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 22 Oct 2025 09:14:55 -0400 Subject: [PATCH 24/44] drm/amdgpu: fix SPDX header on amd_cper.h This should be MIT. The driver in general is MIT and the license text at the top of the file is MIT so fix it. Fixes: 523b69c65445 ("drm/amd/include: Add amd cper header") Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4654 Reviewed-by: Mario Limonciello Signed-off-by: Alex Deucher (cherry picked from commit 72c5482cb0f3d3c772c9de50e5a4265258a53f81) --- drivers/gpu/drm/amd/include/amd_cper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/include/amd_cper.h b/drivers/gpu/drm/amd/include/amd_cper.h index 086869264425..a252ee4c7874 100644 --- a/drivers/gpu/drm/amd/include/amd_cper.h +++ b/drivers/gpu/drm/amd/include/amd_cper.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: MIT */ /* * Copyright 2025 Advanced Micro Devices, Inc. * From 8284a9e91722d3214aac5d54b4e0d2c91af0fdfc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 22 Oct 2025 09:17:37 -0400 Subject: [PATCH 25/44] drm/amdgpu: fix SPDX header on irqsrcs_vcn_5_0.h This should be MIT. The driver in general is MIT and the license text at the top of the file is MIT so fix it. Fixes: d1bb64651095 ("drm/amdgpu: add irq source ids for VCN5_0/JPEG5_0") Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4654 Reviewed-by: Mario Limonciello Signed-off-by: Alex Deucher (cherry picked from commit 68c20d7b1779f97d600e61b9e95726c0cd609e2a) --- drivers/gpu/drm/amd/include/ivsrcid/vcn/irqsrcs_vcn_5_0.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/include/ivsrcid/vcn/irqsrcs_vcn_5_0.h b/drivers/gpu/drm/amd/include/ivsrcid/vcn/irqsrcs_vcn_5_0.h index 64b553e7de1a..e7fdcee22a71 100644 --- a/drivers/gpu/drm/amd/include/ivsrcid/vcn/irqsrcs_vcn_5_0.h +++ b/drivers/gpu/drm/amd/include/ivsrcid/vcn/irqsrcs_vcn_5_0.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: MIT */ /* * Copyright 2024 Advanced Micro Devices, Inc. All rights reserved. From 4f2cd64510e7ae0b3a6ec1c10826cb6baf04edfa Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 22 Oct 2025 09:19:55 -0400 Subject: [PATCH 26/44] drm/amdgpu: fix SPDX header on cyan_skillfish_reg_init.c This should be MIT. The driver in general is MIT and the license text at the top of the file is MIT so fix it. Fixes: e8529dbc75ca ("drm/amdgpu: add ip offset support for cyan skillfish") Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4654 Reviewed-by: Mario Limonciello Signed-off-by: Alex Deucher (cherry picked from commit 102c4f7c554ac5a5ecf0023fa0612beb58e3b0bd) --- drivers/gpu/drm/amd/amdgpu/cyan_skillfish_reg_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/cyan_skillfish_reg_init.c b/drivers/gpu/drm/amd/amdgpu/cyan_skillfish_reg_init.c index 96616a865aac..ed1e25661706 100644 --- a/drivers/gpu/drm/amd/amdgpu/cyan_skillfish_reg_init.c +++ b/drivers/gpu/drm/amd/amdgpu/cyan_skillfish_reg_init.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: MIT /* * Copyright 2018 Advanced Micro Devices, Inc. * From 7d08c3b1731014dd1cfd0bf8b0cb1cef9dfd191e Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Thu, 16 Oct 2025 20:08:10 -0600 Subject: [PATCH 27/44] drm/amd/display: Add HDR workaround for a specific eDP [WHY & HOW] Some eDP panels suffer from flicking when HDR is enabled in KDE or Gnome. This add another quirk to worksaround to skip VSC that is incompatible with an eDP panel. Link: https://gitlab.freedesktop.org/drm/amd/-/issues/4452 Reviewed-by: Aurabindo Pillai Signed-off-by: Alex Hung Signed-off-by: Wayne Lin Tested-by: Dan Wheeler Signed-off-by: Alex Deucher (cherry picked from commit 99441824bec63549a076cd86631d138ec9a0c71c) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index fe100e4c9801..cc21337a182f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -83,6 +83,7 @@ static void apply_edid_quirks(struct drm_device *dev, struct edid *edid, struct edid_caps->panel_patch.remove_sink_ext_caps = true; break; case drm_edid_encode_panel_id('S', 'D', 'C', 0x4154): + case drm_edid_encode_panel_id('S', 'D', 'C', 0x4171): drm_dbg_driver(dev, "Disabling VSC on monitor with panel id %X\n", panel_id); edid_caps->panel_patch.disable_colorimetry = true; break; From b3656b355b5522cef1b52a7469010009c98156db Mon Sep 17 00:00:00 2001 From: Ivan Lipski Date: Wed, 17 Sep 2025 11:00:02 -0400 Subject: [PATCH 28/44] drm/amd/display: Fix incorrect return of vblank enable on unconfigured crtc [Why&How] Return -EINVAL when userspace asks us to enable vblank on a crtc that is not yet enabled. Suggested-by: Aurabindo Pillai Reviewed-by: Aurabindo Pillai Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/1856 Signed-off-by: Ivan Lipski Signed-off-by: Wayne Lin Tested-by: Dan Wheeler Signed-off-by: Alex Deucher (cherry picked from commit cb57b8cdb072dc37723b6906da1c37ff9cbc2da4) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c index f08121a2b838..38f9ea313dcb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -308,8 +308,12 @@ static inline int amdgpu_dm_crtc_set_vblank(struct drm_crtc *crtc, bool enable) int irq_type; int rc = 0; - if (acrtc->otg_inst == -1) - goto skip; + if (enable && !acrtc->base.enabled) { + drm_dbg_vbl(crtc->dev, + "Reject vblank enable on unconfigured CRTC %d (enabled=%d)\n", + acrtc->crtc_id, acrtc->base.enabled); + return -EINVAL; + } irq_type = amdgpu_display_crtc_idx_to_irq_type(adev, acrtc->crtc_id); @@ -394,7 +398,7 @@ static inline int amdgpu_dm_crtc_set_vblank(struct drm_crtc *crtc, bool enable) return rc; } #endif -skip: + if (amdgpu_in_reset(adev)) return 0; From dc8aa0cb87a7836b59422cc02d969c8df849ee39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 22 Oct 2025 13:07:16 +0300 Subject: [PATCH 29/44] drm/i915/dmc: Clear HRR EVT_CTL/HTP to zero on ADL-S MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On ADL-S the main DMC HRR event DMC_EVT_CTL/HTP are never restored to their previous values during DC6 exit. This angers assert_dmc_loaded(), and basically makes the HRR handler unusable because we don't rewrite EVT_HTP when enabling DMC events. Let's just clear the HRR EVT_CTL/HTP to zero from the beginnning so that the expected value matches the post-DC6 reality. I suppose if we ever had actual use for HRR we'd have to both, reject HRR+PSR, and reprogram EVT_HTP when enabling the event. But for now we don't care about HRR so keeping both registers zeroed is fine. Cc: stable@vger.kernel.org Tested-by: Petr Vorel Fixes: 43175c92d403 ("drm/i915/dmc: Assert DMC is loaded harder") Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15153 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20251022100718.24803-2-ville.syrjala@linux.intel.com Reviewed-by: Petr Vorel Reviewed-by: Imre Deak Tested-by: Imre Deak (cherry picked from commit 4df3b340ff6e9f499735d8b52b96a9257fde3918) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_dmc.c | 55 +++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 77a0199f9ea5..4a4cace1f879 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -546,6 +546,36 @@ static bool is_event_handler(struct intel_display *display, REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == event_id; } +static bool fixup_dmc_evt(struct intel_display *display, + enum intel_dmc_id dmc_id, + i915_reg_t reg_ctl, u32 *data_ctl, + i915_reg_t reg_htp, u32 *data_htp) +{ + if (!is_dmc_evt_ctl_reg(display, dmc_id, reg_ctl)) + return false; + + if (!is_dmc_evt_htp_reg(display, dmc_id, reg_htp)) + return false; + + /* make sure reg_ctl and reg_htp are for the same event */ + if (i915_mmio_reg_offset(reg_ctl) - i915_mmio_reg_offset(DMC_EVT_CTL(display, dmc_id, 0)) != + i915_mmio_reg_offset(reg_htp) - i915_mmio_reg_offset(DMC_EVT_HTP(display, dmc_id, 0))) + return false; + + /* + * On ADL-S the HRR event handler is not restored after DC6. + * Clear it to zero from the beginning to avoid mismatches later. + */ + if (display->platform.alderlake_s && dmc_id == DMC_FW_MAIN && + is_event_handler(display, dmc_id, MAINDMC_EVENT_VBLANK_A, reg_ctl, *data_ctl)) { + *data_ctl = 0; + *data_htp = 0; + return true; + } + + return false; +} + static bool disable_dmc_evt(struct intel_display *display, enum intel_dmc_id dmc_id, i915_reg_t reg, u32 data) @@ -1064,9 +1094,32 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc, for (i = 0; i < mmio_count; i++) { dmc_info->mmioaddr[i] = _MMIO(mmioaddr[i]); dmc_info->mmiodata[i] = mmiodata[i]; + } + for (i = 0; i < mmio_count - 1; i++) { + u32 orig_mmiodata[2] = { + dmc_info->mmiodata[i], + dmc_info->mmiodata[i+1], + }; + + if (!fixup_dmc_evt(display, dmc_id, + dmc_info->mmioaddr[i], &dmc_info->mmiodata[i], + dmc_info->mmioaddr[i+1], &dmc_info->mmiodata[i+1])) + continue; + + drm_dbg_kms(display->drm, + " mmio[%d]: 0x%x = 0x%x->0x%x (EVT_CTL)\n", + i, i915_mmio_reg_offset(dmc_info->mmioaddr[i]), + orig_mmiodata[0], dmc_info->mmiodata[i]); + drm_dbg_kms(display->drm, + " mmio[%d]: 0x%x = 0x%x->0x%x (EVT_HTP)\n", + i+1, i915_mmio_reg_offset(dmc_info->mmioaddr[i+1]), + orig_mmiodata[1], dmc_info->mmiodata[i+1]); + } + + for (i = 0; i < mmio_count; i++) { drm_dbg_kms(display->drm, " mmio[%d]: 0x%x = 0x%x%s%s\n", - i, mmioaddr[i], mmiodata[i], + i, i915_mmio_reg_offset(dmc_info->mmioaddr[i]), dmc_info->mmiodata[i], is_dmc_evt_ctl_reg(display, dmc_id, dmc_info->mmioaddr[i]) ? " (EVT_CTL)" : is_dmc_evt_htp_reg(display, dmc_id, dmc_info->mmioaddr[i]) ? " (EVT_HTP)" : "", disable_dmc_evt(display, dmc_id, dmc_info->mmioaddr[i], From 93c97bc8d85d5742d6f000d8bf3eeeb705bc6082 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 27 Oct 2025 14:09:48 +0100 Subject: [PATCH 30/44] drm/msm: dsi: fix PLL init in bonded mode When in bonded DSI mode, only one PLL in one DSI PHY is used for both DSI PHYs, meaning that parents of the secondary DSI PHY will use the primary DSI PHY PLL as parent. In this case the primary DSI PHY PLL will be set even if the primary DSI PHY is not yet enabled. The DSI PHY code has support for this particular use-case and will handle the fact the PLL was already set when initializing the primary DSI PHY. By introducing a protected variable pll_enable_cnt in the commit cb55f39bf7b1 ("drm/msm/dsi/phy: Fix reading zero as PLL rates when unprepared"), this variable is only initially set to 1 when the DSI PHY is initialized making it impossible to set the PLL before, breaking the bonded DSI use case by returning 0 when setting the PLL from the secondary DSI PHY driver and skipping the correct clocks initialization. But since it was already possible to set the PLL without enabling the DSI PHY, just drop the pll_enable_cnt setting from the PHY enable/disable and simply increment/decrement the pll_enable_cnt variable from the dsi_pll_enable/disable_pll_bias to make sure any PLL operation is done with the PLL BIAS enabled. Fixes: cb55f39bf7b1 ("drm/msm/dsi/phy: Fix reading zero as PLL rates when unprepared") Closes: https://lore.kernel.org/all/50a49d72-2b1e-471d-b0c4-d5a0b38b2a21@linaro.org/ Tested-by: Krzysztof Kozlowski Signed-off-by: Neil Armstrong Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/683688/ Link: https://lore.kernel.org/r/20251027-topic-sm8x50-fix-dsi-bonded-v1-1-a477cd3f907d@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 1 - drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 18 ++---------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h index e391505fdaf0..3cbf08231492 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h @@ -109,7 +109,6 @@ struct msm_dsi_phy { struct msm_dsi_dphy_timing timing; const struct msm_dsi_phy_cfg *cfg; void *tuning_cfg; - void *pll_data; enum msm_dsi_phy_usecase usecase; bool regulator_ldo_mode; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c index 32f06edd21a9..c5e1d2016bcc 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -426,11 +426,8 @@ static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll) u32 data; spin_lock_irqsave(&pll->pll_enable_lock, flags); - if (pll->pll_enable_cnt++) { - spin_unlock_irqrestore(&pll->pll_enable_lock, flags); - WARN_ON(pll->pll_enable_cnt == INT_MAX); - return; - } + pll->pll_enable_cnt++; + WARN_ON(pll->pll_enable_cnt == INT_MAX); data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0); data |= DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB; @@ -876,7 +873,6 @@ static int dsi_pll_7nm_init(struct msm_dsi_phy *phy) spin_lock_init(&pll_7nm->pll_enable_lock); pll_7nm->phy = phy; - phy->pll_data = pll_7nm; ret = pll_7nm_register(pll_7nm, phy->provided_clocks->hws); if (ret) { @@ -965,10 +961,8 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, u32 const delay_us = 5; u32 const timeout_us = 1000; struct msm_dsi_dphy_timing *timing = &phy->timing; - struct dsi_pll_7nm *pll = phy->pll_data; void __iomem *base = phy->base; bool less_than_1500_mhz; - unsigned long flags; u32 vreg_ctrl_0, vreg_ctrl_1, lane_ctrl0; u32 glbl_pemph_ctrl_0; u32 glbl_str_swi_cal_sel_ctrl, glbl_hstx_str_ctrl_0; @@ -1090,13 +1084,10 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, glbl_rescode_bot_ctrl = 0x3c; } - spin_lock_irqsave(&pll->pll_enable_lock, flags); - pll->pll_enable_cnt = 1; /* de-assert digital and pll power down */ data = DSI_7nm_PHY_CMN_CTRL_0_DIGTOP_PWRDN_B | DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB; writel(data, base + REG_DSI_7nm_PHY_CMN_CTRL_0); - spin_unlock_irqrestore(&pll->pll_enable_lock, flags); /* Assert PLL core reset */ writel(0x00, base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL); @@ -1209,9 +1200,7 @@ static bool dsi_7nm_set_continuous_clock(struct msm_dsi_phy *phy, bool enable) static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy) { - struct dsi_pll_7nm *pll = phy->pll_data; void __iomem *base = phy->base; - unsigned long flags; u32 data; DBG(""); @@ -1238,11 +1227,8 @@ static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy) writel(data, base + REG_DSI_7nm_PHY_CMN_CTRL_0); writel(0, base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0); - spin_lock_irqsave(&pll->pll_enable_lock, flags); - pll->pll_enable_cnt = 0; /* Turn off all PHY blocks */ writel(0x00, base + REG_DSI_7nm_PHY_CMN_CTRL_0); - spin_unlock_irqrestore(&pll->pll_enable_lock, flags); /* make sure phy is turned off */ wmb(); From 2319551e97f0cd9b4a7b78c1a6970aa4b785000b Mon Sep 17 00:00:00 2001 From: Vladimir Lypak Date: Fri, 17 Oct 2025 19:58:35 +0000 Subject: [PATCH 31/44] drm/msm/dpu: Fix allocation of RGB SSPPs without scaling Due to condition in dpu_rm_reserve_sspp, RGB SSPPs are only tried when scaling is requested, which prevents those SSPPs from being reserved if we don't need scaling at all. Instead we should check if YUV support is requested, since scaling on RGB SSPPs is optional and is not implemented in driver yet. Fixes: 774bcfb73176 ("drm/msm/dpu: add support for virtual planes") Signed-off-by: Vladimir Lypak Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/681914/ Link: https://lore.kernel.org/r/20251017-b4-dpu-fixes-v1-1-40ce5993eeb6@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index 2c77c74fac0f..d9c3b0a1d091 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -842,7 +842,7 @@ struct dpu_hw_sspp *dpu_rm_reserve_sspp(struct dpu_rm *rm, if (!reqs->scale && !reqs->yuv) hw_sspp = dpu_rm_try_sspp(rm, global_state, crtc, reqs, SSPP_TYPE_DMA); - if (!hw_sspp && reqs->scale) + if (!hw_sspp && !reqs->yuv) hw_sspp = dpu_rm_try_sspp(rm, global_state, crtc, reqs, SSPP_TYPE_RGB); if (!hw_sspp) hw_sspp = dpu_rm_try_sspp(rm, global_state, crtc, reqs, SSPP_TYPE_VIG); From 23ab0d6228bf9de6cf69db330f95a1938b276693 Mon Sep 17 00:00:00 2001 From: Vladimir Lypak Date: Fri, 17 Oct 2025 19:58:36 +0000 Subject: [PATCH 32/44] drm/msm/dpu: Propagate error from dpu_assign_plane_resources The dpu_plane_virtual_assign_resources function might fail if there is no suitable SSPP(s) for the plane. This leaves sspp field in plane state uninitialized and later leads to NULL dereference during commit: Call trace: _dpu_crtc_blend_setup+0x194/0x620 [msm] (P) dpu_crtc_atomic_begin+0xe4/0x240 [msm] drm_atomic_helper_commit_planes+0x88/0x358 msm_atomic_commit_tail+0x1b4/0x8b8 [msm] commit_tail+0xa8/0x1b0 drm_atomic_helper_commit+0x180/0x1a0 drm_atomic_commit+0x94/0xe0 drm_mode_atomic_ioctl+0xa88/0xd60 drm_ioctl_kernel+0xc4/0x138 drm_ioctl+0x364/0x4f0 __arm64_sys_ioctl+0xac/0x108 invoke_syscall.constprop.0+0x48/0x100 el0_svc_common.constprop.0+0x40/0xe8 do_el0_svc+0x24/0x38 el0_svc+0x30/0xe0 el0t_64_sync_handler+0xa0/0xe8 el0t_64_sync+0x198/0x1a0 Fixes: 3ed12a3664b3 ("drm/msm/dpu: allow sharing SSPP between planes") Signed-off-by: Vladimir Lypak Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/681916/ Link: https://lore.kernel.org/r/20251017-b4-dpu-fixes-v1-2-40ce5993eeb6@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index f54cf0faa1c7..d198a65a2c5f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -1278,7 +1278,7 @@ int dpu_assign_plane_resources(struct dpu_global_state *global_state, state, plane_state, prev_adjacent_plane_state); if (ret) - break; + return ret; prev_adjacent_plane_state = plane_state; } From 425da3305972a7bab9812770d44e2f7f97f8bfd6 Mon Sep 17 00:00:00 2001 From: Vladimir Lypak Date: Fri, 17 Oct 2025 19:58:37 +0000 Subject: [PATCH 33/44] drm/msm/dpu: Disable scaling for unsupported scaler types Scaling is not implemented for some type of scalers (QSEED2 and RGB) but it was unintentionally re-enabled with change below. The remaining condition in dpu_plane_atomic_check_pipe is not enough because it only checks for length of scaler block (which is present). This patch adds a additional check for setup_scaler operation. Fixes: 8f15005783b8 ("drm/msm/dpu: move scaling limitations out of the hw_catalog") Signed-off-by: Vladimir Lypak Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/681918/ Link: https://lore.kernel.org/r/20251017-b4-dpu-fixes-v1-3-40ce5993eeb6@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index d198a65a2c5f..6effe0fa4837 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -740,7 +740,7 @@ static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu, * We already have verified scaling against platform limitations. * Now check if the SSPP supports scaling at all. */ - if (!sblk->scaler_blk.len && + if (!(sblk->scaler_blk.len && pipe->sspp->ops.setup_scaler) && ((drm_rect_width(&new_plane_state->src) >> 16 != drm_rect_width(&new_plane_state->dst)) || (drm_rect_height(&new_plane_state->src) >> 16 != From 2f8bed9175429294860276b897de53d49ed647d8 Mon Sep 17 00:00:00 2001 From: Vladimir Lypak Date: Fri, 17 Oct 2025 19:58:38 +0000 Subject: [PATCH 34/44] drm/msm/dpu: Fix pixel extension sub-sampling In _dpu_plane_setup_pixel_ext function instead of dividing just chroma source resolution once (component 1 and 2), second component is divided once more because src_w and src_h variable is reused between iterations. Third component receives wrong source resolution too (from component 2). To fix this introduce temporary variables for each iteration. Fixes: dabfdd89eaa9 ("drm/msm/disp/dpu1: add inline rotation support for sc7280") Signed-off-by: Vladimir Lypak Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/681921/ Link: https://lore.kernel.org/r/20251017-b4-dpu-fixes-v1-4-40ce5993eeb6@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 6effe0fa4837..905524ceeb1f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -500,13 +500,15 @@ static void _dpu_plane_setup_pixel_ext(struct dpu_hw_scaler3_cfg *scale_cfg, int i; for (i = 0; i < DPU_MAX_PLANES; i++) { + uint32_t w = src_w, h = src_h; + if (i == DPU_SSPP_COMP_1_2 || i == DPU_SSPP_COMP_2) { - src_w /= chroma_subsmpl_h; - src_h /= chroma_subsmpl_v; + w /= chroma_subsmpl_h; + h /= chroma_subsmpl_v; } - pixel_ext->num_ext_pxls_top[i] = src_h; - pixel_ext->num_ext_pxls_left[i] = src_w; + pixel_ext->num_ext_pxls_top[i] = h; + pixel_ext->num_ext_pxls_left[i] = w; } } From 5e0656b125346d9a1ef65e72c6d3196b8ea6b1e1 Mon Sep 17 00:00:00 2001 From: Vladimir Lypak Date: Fri, 17 Oct 2025 19:58:39 +0000 Subject: [PATCH 35/44] drm/msm/dpu: Require linear modifier for writeback framebuffers UBWC-related register configuration for writeback is not implemented in the driver yet but there aren't any checks for non-linear modifiers in atomic_check. Thus when compressed framebuffer is attached to writeback connector it will be filled with linear image data. This patch forbids non-linear modifiers for writeback framebuffers until UBWC support for writeback is properly implemented. Fixes: 71174f362d67 ("drm/msm/dpu: move writeback's atomic_check to dpu_writeback.c") Signed-off-by: Vladimir Lypak Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/681922/ Link: https://lore.kernel.org/r/20251017-b4-dpu-fixes-v1-5-40ce5993eeb6@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c index cd73468e369a..7545c0293efb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c @@ -72,6 +72,9 @@ static int dpu_wb_conn_atomic_check(struct drm_connector *connector, DPU_ERROR("invalid fb w=%d, maxlinewidth=%u\n", fb->width, dpu_wb_conn->maxlinewidth); return -EINVAL; + } else if (fb->modifier != DRM_FORMAT_MOD_LINEAR) { + DPU_ERROR("unsupported fb modifier:%#llx\n", fb->modifier); + return -EINVAL; } return drm_atomic_helper_check_wb_connector_state(conn_state->connector, conn_state->state); From bbc65d1bde821750c48ac075057be548e38d77cc Mon Sep 17 00:00:00 2001 From: Vladimir Lypak Date: Sat, 18 Oct 2025 14:33:43 +0000 Subject: [PATCH 36/44] drm/msm/dpu: Disable broken YUV on QSEED2 hardware YUV formats on this hardware needs scaling for chroma planes. However it is not implemented for QSEED2 which breaks display pipeline if YUV format is used (causing partial and corrupted output with PPDONE timeouts). This patch temporarily disables YUV by switching affected sub-block to RGB only format list. Fixes: daf9a92daeb8 ("drm/msm/dpu: Add support for MSM8996") Signed-off-by: Vladimir Lypak Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/682061/ Link: https://lore.kernel.org/r/20251018-b4-dpu-fixes-v1-6-1852278064d0@gmail.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 6641455c4ec6..9f8d1bba9139 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -267,8 +267,8 @@ static const u32 wb2_formats_rgb_yuv[] = { .base = 0x200, .len = 0xa0,}, \ .csc_blk = {.name = "csc", \ .base = 0x320, .len = 0x100,}, \ - .format_list = plane_formats_yuv, \ - .num_formats = ARRAY_SIZE(plane_formats_yuv), \ + .format_list = plane_formats, \ + .num_formats = ARRAY_SIZE(plane_formats), \ .rotation_cfg = NULL, \ } From f5d079564c44baaeedf5e25f4b943aa042ea0eb1 Mon Sep 17 00:00:00 2001 From: Jessica Zhang Date: Tue, 23 Sep 2025 16:03:50 -0700 Subject: [PATCH 37/44] drm/msm/dpu: Fix adjusted mode clock check for 3d merge Since 3D merge allows for larger modes to be supported across 2 layer mixers, filter modes based on adjusted mode clock / 2 when 3d merge is supported. Reported-by: Abel Vesa Fixes: 62b7d6835288 ("drm/msm/dpu: Filter modes based on adjusted mode clock") Signed-off-by: Jessica Zhang Reviewed-by: Dmitry Baryshkov Reviewed-by: Abel Vesa Tested-by: Abel Vesa Tested-by: Krzysztof Kozlowski Patchwork: https://patchwork.freedesktop.org/patch/676353/ Link: https://lore.kernel.org/r/20250923-modeclk-fix-v2-1-01fcd0b2465a@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 4b970a59deaf..2f8156051d9b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -1545,6 +1545,9 @@ static enum drm_mode_status dpu_crtc_mode_valid(struct drm_crtc *crtc, adjusted_mode_clk = dpu_core_perf_adjusted_mode_clk(mode->clock, dpu_kms->perf.perf_cfg); + if (dpu_kms->catalog->caps->has_3d_merge) + adjusted_mode_clk /= 2; + /* * The given mode, adjusted for the perf clock factor, should not exceed * the max core clock rate From edce042da7984586ea5c7ed18ea5f58002afb969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Mon, 27 Oct 2025 14:12:28 +0100 Subject: [PATCH 38/44] drm/xe: Fix uninitialized return value from xe_validation_guard() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the DEFINE_CLASS() macro creates an inline function and the init args are passed down to it; since _ret is passed as an int, whatever value is set inside the function is not visible to the caller. Pass _ret as a pointer so its value propagates to the caller. Fixes: c460bc2311df ("drm/xe: Introduce an xe_validation wrapper around drm_exec") Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/6220 Cc: Maarten Lankhorst Cc: Matthew Brost Cc: intel-xe@lists.freedesktop.org Signed-off-by: Thomas Hellström Reviewed-by: Lucas De Marchi Reviewed-by: Maarten Lankhorst Reviewed-by: Matthew Brost Link: https://patch.msgid.link/20251027131228.12098-1-thomas.hellstrom@linux.intel.com (cherry picked from commit fcb8c304f4673747d535c74b340b5b8a4823727b) Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_validation.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_validation.h b/drivers/gpu/drm/xe/xe_validation.h index fec331d791e7..b2d09c596714 100644 --- a/drivers/gpu/drm/xe/xe_validation.h +++ b/drivers/gpu/drm/xe/xe_validation.h @@ -166,10 +166,10 @@ xe_validation_device_init(struct xe_validation_device *val) */ DEFINE_CLASS(xe_validation, struct xe_validation_ctx *, if (_T) xe_validation_ctx_fini(_T);, - ({_ret = xe_validation_ctx_init(_ctx, _val, _exec, _flags); - _ret ? NULL : _ctx; }), + ({*_ret = xe_validation_ctx_init(_ctx, _val, _exec, _flags); + *_ret ? NULL : _ctx; }), struct xe_validation_ctx *_ctx, struct xe_validation_device *_val, - struct drm_exec *_exec, const struct xe_val_flags _flags, int _ret); + struct drm_exec *_exec, const struct xe_val_flags _flags, int *_ret); static inline void *class_xe_validation_lock_ptr(class_xe_validation_t *_T) {return *_T; } #define class_xe_validation_is_conditional true @@ -186,7 +186,7 @@ static inline void *class_xe_validation_lock_ptr(class_xe_validation_t *_T) * exhaustive eviction. */ #define xe_validation_guard(_ctx, _val, _exec, _flags, _ret) \ - scoped_guard(xe_validation, _ctx, _val, _exec, _flags, _ret) \ + scoped_guard(xe_validation, _ctx, _val, _exec, _flags, &_ret) \ drm_exec_until_all_locked(_exec) #endif From b3fbda1a630a9439c885b2a5dc5230cc49a87e9e Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Tue, 21 Oct 2025 17:55:37 -0700 Subject: [PATCH 39/44] drm/xe: Do not wake device during a GT reset Waking the device during a GT reset can lead to unintended memory allocation, which is not allowed since GT resets occur in the reclaim path. Prevent this by holding a PM reference while a reset is in flight. Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs") Cc: stable@vger.kernel.org Signed-off-by: Matthew Brost Reviewed-by: Matthew Auld Link: https://lore.kernel.org/r/20251022005538.828980-3-matthew.brost@intel.com (cherry picked from commit 480b358e7d8ef69fd8f1b0cad6e07c7d70a36ee4) Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_gt.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index 3e0ad7e5b5df..6d3db5e55d98 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -813,12 +813,16 @@ static int gt_reset(struct xe_gt *gt) unsigned int fw_ref; int err; - if (xe_device_wedged(gt_to_xe(gt))) - return -ECANCELED; + if (xe_device_wedged(gt_to_xe(gt))) { + err = -ECANCELED; + goto err_pm_put; + } /* We only support GT resets with GuC submission */ - if (!xe_device_uc_enabled(gt_to_xe(gt))) - return -ENODEV; + if (!xe_device_uc_enabled(gt_to_xe(gt))) { + err = -ENODEV; + goto err_pm_put; + } xe_gt_info(gt, "reset started\n"); @@ -826,8 +830,6 @@ static int gt_reset(struct xe_gt *gt) if (!err) xe_gt_warn(gt, "reset block failed to get lifted"); - xe_pm_runtime_get(gt_to_xe(gt)); - if (xe_fault_inject_gt_reset()) { err = -ECANCELED; goto err_fail; @@ -874,6 +876,7 @@ err_fail: xe_gt_err(gt, "reset failed (%pe)\n", ERR_PTR(err)); xe_device_declare_wedged(gt_to_xe(gt)); +err_pm_put: xe_pm_runtime_put(gt_to_xe(gt)); return err; @@ -895,7 +898,9 @@ void xe_gt_reset_async(struct xe_gt *gt) return; xe_gt_info(gt, "reset queued\n"); - queue_work(gt->ordered_wq, >->reset.worker); + xe_pm_runtime_get_noresume(gt_to_xe(gt)); + if (!queue_work(gt->ordered_wq, >->reset.worker)) + xe_pm_runtime_put(gt_to_xe(gt)); } void xe_gt_suspend_prepare(struct xe_gt *gt) From 056d76f7cb9fa68c8bbf85b4055aeb84af6139d5 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Wed, 1 Oct 2025 01:59:42 +0200 Subject: [PATCH 40/44] drm/panel: sitronix-st7789v: fix sync flags for t28cp45tn89 I planned to set the polarity of horizontal and vertical sync, but accidentally described vertical sync twice with different polarity instead. Note, that there is no functional change, because the driver only makes use of DRM_MODE_FLAG_P[HV]SYNC to divert from the default active-low polarity. Reported-by: Laurent Pinchart Closes: https://lore.kernel.org/all/20250923132616.GH20765@pendragon.ideasonboard.com/ Fixes: a411558cc143 ("drm/panel: sitronix-st7789v: add Inanbo T28CP45TN89 support") Reviewed-by: Laurent Pinchart Reviewed-by: Marek Vasut Signed-off-by: Sebastian Reichel Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20251001-t28cp45tn89-fix-v2-1-67fe8e3046ca@collabora.com --- drivers/gpu/drm/panel/panel-sitronix-st7789v.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7789v.c b/drivers/gpu/drm/panel/panel-sitronix-st7789v.c index 04d91929eedd..d5f821d6b23c 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7789v.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7789v.c @@ -249,6 +249,11 @@ static const struct drm_display_mode default_mode = { .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, }; +/* + * The mode data for this panel has been reverse engineered without access + * to the panel datasheet / manual. Using DRM_MODE_FLAG_PHSYNC like all + * other panels results in garbage data on the display. + */ static const struct drm_display_mode t28cp45tn89_mode = { .clock = 6008, .hdisplay = 240, @@ -261,7 +266,7 @@ static const struct drm_display_mode t28cp45tn89_mode = { .vtotal = 320 + 8 + 4 + 4, .width_mm = 43, .height_mm = 57, - .flags = DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC, + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC, }; static const struct drm_display_mode et028013dma_mode = { From d8eb00bbc628c8916ab0da2bb80059d48aa4512e Mon Sep 17 00:00:00 2001 From: Sebastian Fleer Date: Wed, 29 Oct 2025 13:35:28 +0100 Subject: [PATCH 41/44] drm/panel: kingdisplay-kd097d04: Disable EoTp Since commit d97e71e44937 ("drm/bridge: synopsys: dw-mipi-dsi: enable EoTp by default") panel output on an Acer Chromebook Tab 10 (google-dru) is corrupted. The tablet I use is equipped with a kingdisplay-kd097d04 panel, disabling EoTp restores the correct functionality. Fixes: 2a994cbed6b2 ("drm/panel: Add Kingdisplay KD097D04 panel driver") Suggested-by: Jens Reidel Signed-off-by: Sebastian Fleer Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20251029124007.232333-1-dev@dwurp.de --- drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c b/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c index 2fc7b0779b37..893af9b16756 100644 --- a/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c +++ b/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c @@ -359,7 +359,7 @@ static int kingdisplay_panel_probe(struct mipi_dsi_device *dsi) dsi->lanes = 4; dsi->format = MIPI_DSI_FMT_RGB888; dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | - MIPI_DSI_MODE_LPM; + MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET; kingdisplay = devm_drm_panel_alloc(&dsi->dev, __typeof(*kingdisplay), base, &kingdisplay_panel_funcs, From 3257bd193fa1702791978d8418c9a96e3def082c Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 14 Oct 2025 13:30:51 +0200 Subject: [PATCH 42/44] drm/imx: parallel-display: convert to devm_drm_bridge_alloc() API This is the new API for allocating DRM bridges. This conversion was missed during the initial conversion of all bridges to the new API. Thus all kernels with commit 94d50c1a2ca3 ("drm/bridge: get/put the bridge reference in drm_bridge_attach/detach()") and using this driver now warn due to drm_bridge_attach() incrementing the refcount, which is not initialized without using devm_drm_bridge_alloc() for allocation. To make the conversion simple and straightforward without messing up with the drmm_simple_encoder_alloc(), move the struct drm_bridge from struct imx_parallel_display_encoder to struct imx_parallel_display. Also remove the 'struct imx_parallel_display *pd' from struct imx_parallel_display_encoder, not needed anymore. Fixes: 94d50c1a2ca3 ("drm/bridge: get/put the bridge reference in drm_bridge_attach/detach()") Reported-by: Ernest Van Hoecke Closes: https://lore.kernel.org/all/hlf4wdopapxnh4rekl5s3kvoi6egaga3lrjfbx6r223ar3txri@3ik53xw5idyh/ Signed-off-by: Luca Ceresoli Reviewed-by: Louis Chauvet Tested-by: Ernest Van Hoecke Link: https://patch.msgid.link/20251014-drm-bridge-alloc-imx-ipuv3-v1-1-a1bb1dcbff50@bootlin.com Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/ipuv3/parallel-display.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/imx/ipuv3/parallel-display.c b/drivers/gpu/drm/imx/ipuv3/parallel-display.c index 6d8325c76697..3d0de9c6e925 100644 --- a/drivers/gpu/drm/imx/ipuv3/parallel-display.c +++ b/drivers/gpu/drm/imx/ipuv3/parallel-display.c @@ -25,19 +25,18 @@ struct imx_parallel_display_encoder { struct drm_encoder encoder; - struct drm_bridge bridge; - struct imx_parallel_display *pd; }; struct imx_parallel_display { struct device *dev; u32 bus_format; struct drm_bridge *next_bridge; + struct drm_bridge bridge; }; static inline struct imx_parallel_display *bridge_to_imxpd(struct drm_bridge *b) { - return container_of(b, struct imx_parallel_display_encoder, bridge)->pd; + return container_of(b, struct imx_parallel_display, bridge); } static const u32 imx_pd_bus_fmts[] = { @@ -195,15 +194,13 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data) if (IS_ERR(imxpd_encoder)) return PTR_ERR(imxpd_encoder); - imxpd_encoder->pd = imxpd; encoder = &imxpd_encoder->encoder; - bridge = &imxpd_encoder->bridge; + bridge = &imxpd->bridge; ret = imx_drm_encoder_parse_of(drm, encoder, imxpd->dev->of_node); if (ret) return ret; - bridge->funcs = &imx_pd_bridge_funcs; drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); connector = drm_bridge_connector_init(drm, encoder); @@ -228,9 +225,10 @@ static int imx_pd_probe(struct platform_device *pdev) u32 bus_format = 0; const char *fmt; - imxpd = devm_kzalloc(dev, sizeof(*imxpd), GFP_KERNEL); - if (!imxpd) - return -ENOMEM; + imxpd = devm_drm_bridge_alloc(dev, struct imx_parallel_display, bridge, + &imx_pd_bridge_funcs); + if (IS_ERR(imxpd)) + return PTR_ERR(imxpd); /* port@1 is the output port */ imxpd->next_bridge = devm_drm_of_get_bridge(dev, np, 1, 0); From bf7e97910b9f4d9679e075a39be371a4ed65dbd4 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 14 Oct 2025 13:30:52 +0200 Subject: [PATCH 43/44] drm/imx: parallel-display: add the bridge before attaching it Invoking drm_bridge_add() is good practice, so add it to this driver. Link: https://lore.kernel.org/all/DDHZ5GO9MPF0.CGYTVBI74FOZ@bootlin.com Signed-off-by: Luca Ceresoli Reviewed-by: Louis Chauvet Link: https://patch.msgid.link/20251014-drm-bridge-alloc-imx-ipuv3-v1-2-a1bb1dcbff50@bootlin.com Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/ipuv3/parallel-display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/imx/ipuv3/parallel-display.c b/drivers/gpu/drm/imx/ipuv3/parallel-display.c index 3d0de9c6e925..7fc6af703307 100644 --- a/drivers/gpu/drm/imx/ipuv3/parallel-display.c +++ b/drivers/gpu/drm/imx/ipuv3/parallel-display.c @@ -256,6 +256,8 @@ static int imx_pd_probe(struct platform_device *pdev) platform_set_drvdata(pdev, imxpd); + devm_drm_bridge_add(dev, &imxpd->bridge); + return component_add(dev, &imx_pd_ops); } From a9fb41b5def8e1e0103d5fd1453787993587281e Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 24 Oct 2025 09:35:53 +0200 Subject: [PATCH 44/44] drm/ast: Clear preserved bits from register output value Preserve the I/O register bits in __ast_write8_i_masked() as specified by preserve_mask. Accidentally OR-ing the output value into these will overwrite the register's previous settings. Fixes display output on the AST2300, where the screen can go blank at boot. The driver's original commit 312fec1405dd ("drm: Initial KMS driver for AST (ASpeed Technologies) 2000 series (v2)") already added the broken code. Commit 6f719373b943 ("drm/ast: Blank with VGACR17 sync enable, always clear VGACRB6 sync off") triggered the bug. Signed-off-by: Thomas Zimmermann Reported-by: Peter Schneider Closes: https://lore.kernel.org/dri-devel/a40caf8e-58ad-4f9c-af7f-54f6f69c29bb@googlemail.com/ Tested-by: Peter Schneider Reviewed-by: Jocelyn Falempe Fixes: 6f719373b943 ("drm/ast: Blank with VGACR17 sync enable, always clear VGACRB6 sync off") Fixes: 312fec1405dd ("drm: Initial KMS driver for AST (ASpeed Technologies) 2000 series (v2)") Cc: Thomas Zimmermann Cc: Nick Bowler Cc: Douglas Anderson Cc: Dave Airlie Cc: Jocelyn Falempe Cc: dri-devel@lists.freedesktop.org Cc: # v3.5+ Link: https://patch.msgid.link/20251024073626.129032-1-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index c15aef014f69..d41bd876167c 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -282,13 +282,13 @@ static inline void __ast_write8_i(void __iomem *addr, u32 reg, u8 index, u8 val) __ast_write8(addr, reg + 1, val); } -static inline void __ast_write8_i_masked(void __iomem *addr, u32 reg, u8 index, u8 read_mask, +static inline void __ast_write8_i_masked(void __iomem *addr, u32 reg, u8 index, u8 preserve_mask, u8 val) { - u8 tmp = __ast_read8_i_masked(addr, reg, index, read_mask); + u8 tmp = __ast_read8_i_masked(addr, reg, index, preserve_mask); - tmp |= val; - __ast_write8_i(addr, reg, index, tmp); + val &= ~preserve_mask; + __ast_write8_i(addr, reg, index, tmp | val); } static inline u32 ast_read32(struct ast_device *ast, u32 reg)