From c34e08ba6c0037a72a7433741225b020c989e4ae Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 23 Sep 2025 07:04:40 -0700 Subject: [PATCH 01/15] 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/15] 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/15] 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/15] 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/15] 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 73b7e48a87c79fd6df40aeafcd3994287e31e25f Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 22 Oct 2025 15:20:51 -0700 Subject: [PATCH 06/15] 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 07/15] 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 93c97bc8d85d5742d6f000d8bf3eeeb705bc6082 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 27 Oct 2025 14:09:48 +0100 Subject: [PATCH 08/15] 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 09/15] 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 10/15] 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 11/15] 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 12/15] 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 13/15] 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 14/15] 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 15/15] 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