From c5fd4eaad50d620c7e09ac2082b2fb55ee54170e Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Wed, 16 Sep 2026 09:49:56 +0000 Subject: [PATCH 01/13] drm/amd/display: Fix dc stream excess put in dm_update_crtc_state() In dm_update_crtc_state(), when a modeset is required the newly created stream is stored in dm_new_crtc_state->stream and an extra reference is taken with dc_stream_retain(). The reference returned by create_validate_stream_for_sink() is released as an extra reference at the skip_modeset label, leaving the stream owned by the new CRTC state. If amdgpu_dm_check_crtc_color_mgmt() fails afterwards, the code jumps to the fail label which releases new_stream again. Since the extra reference was already released at skip_modeset, this drops the reference owned by dm_new_crtc_state->stream and the stream is released while the atomic state still points to it, leading to a premature free of the dc stream. Set new_stream to NULL after releasing the extra reference at the skip_modeset label so that a later goto fail cannot release the reference owned by the new CRTC state. Fixes: 7cd4b70091a5 ("drm/amd/display: Rework CRTC color management") Signed-off-by: Wentao Liang Signed-off-by: Alex Deucher (cherry picked from commit 102a47065a62dc8f6bbbb47cf082a2934282eb08) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 36d2f86f000a..91fdf3de7202 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5583,8 +5583,10 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, skip_modeset: /* Release extra reference */ - if (new_stream) + if (new_stream) { dc_stream_release(new_stream); + new_stream = NULL; + } new_stream = NULL; /* From 3022bdfe3e6d776e9273d6892f7c193138ca0666 Mon Sep 17 00:00:00 2001 From: Prike Liang Date: Fri, 31 Jul 2026 11:44:37 +0800 Subject: [PATCH 02/13] drm/amdgpu: move userq fence wait out of signalling section The eviction fence suspend worker waits for every pending userq fence from inside a dma_fence_begin_signalling() critical section. Waiting on another DMA fence while responsible for signalling one violates the cross-driver fence contract and is reported by lockdep as a dma_fence_map dependency. Move the wait before dma_fence_begin_signalling(). Keep userq_mutex held so queue lifetime remains stable while inspecting last_fence. Fixes: fc61df151617 ("drm/amdgpu: annotate eviction fence signaling path") Signed-off-by: Prike Liang Reviewed-by: Vitaly Prosyak Signed-off-by: Alex Deucher (cherry picked from commit 3bd4fbc5ed89621340b5cd249869092691a9c81f) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c | 3 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 4 +--- drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c index f6b7522c3c82..f8652fd0525d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c @@ -68,6 +68,9 @@ amdgpu_eviction_fence_suspend_worker(struct work_struct *work) mutex_lock(&uq_mgr->userq_mutex); + /* Fence waits are not allowed in a fence signalling critical section. */ + amdgpu_userq_wait_for_signal(uq_mgr); + /* * This is intentionally after taking the userq_mutex since we do * allocate memory while holding this lock, but only after ensuring that diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c index e43bda0cab3f..280bdeb38970 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c @@ -1272,7 +1272,7 @@ amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr) return ret; } -static void +void amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr *uq_mgr) { struct amdgpu_usermode_queue *queue; @@ -1291,8 +1291,6 @@ amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr *uq_mgr) void amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr) { - /* Wait for any pending userqueue fence work to finish */ - amdgpu_userq_wait_for_signal(uq_mgr); amdgpu_userq_evict_all(uq_mgr); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h index 6412a7f7b6ef..488dc21d7c81 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h @@ -162,6 +162,7 @@ void amdgpu_userq_mgr_cancel_reset_work(struct amdgpu_device *adev); void amdgpu_userq_mgr_cancel_resume(struct amdgpu_userq_mgr *userq_mgr); void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr); +void amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr *uq_mgr); void amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr); void amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *userq_mgr, From cd195f1616b2bb5fb7765465326c4d5d64a620a0 Mon Sep 17 00:00:00 2001 From: Sunil Khatri Date: Thu, 17 Sep 2026 18:56:45 +0530 Subject: [PATCH 03/13] drm/amdgpu/userq: fix double jiffies conversion in hang detect timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Function amdgpu_userq_start_hang_detect_work() calls msecs_to_jiffies() on adev->gfx_timeout/compute_timeout/sdma_timeout before arming hang_detect_work. These timeout values already hold jiffies values from amdgpu_device_get_job_timeout_settings() at device init. This silently shrinks the real hang-detect deadline to (2 * HZ) ms instead of the intended timeout. e.g. 500ms instead of the 2000ms default on a CONFIG_HZ=250 kernel, only coincidentally correct at HZ=1000. The shortened window is easily exceeded by ordinary fence-completion latency, causing hang_detect_work to fire and trigger a per-queue or full GPU reset for queues that are not actually hung. Pass the jiffies value directly to queue_delayed_work() instead of converting it a second time. Fixes: fc3336be9c62 ("drm/amd/amdgpu: Add independent hang detect work for user queue fence") Signed-off-by: Sunil Khatri Reviewed-by: Christian König Signed-off-by: Alex Deucher (cherry picked from commit 13d44ca033cb74756c2aef0ade54a75cdf2f6271) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c index 280bdeb38970..cc8e7af18834 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c @@ -184,27 +184,27 @@ static void amdgpu_userq_hang_detect_work(struct work_struct *work) void amdgpu_userq_start_hang_detect_work(struct amdgpu_usermode_queue *queue) { struct amdgpu_device *adev; - unsigned long timeout_ms; + unsigned long timeout_jiffies; adev = queue->userq_mgr->adev; /* Determine timeout based on queue type */ switch (queue->queue_type) { case AMDGPU_RING_TYPE_GFX: - timeout_ms = adev->gfx_timeout; + timeout_jiffies = adev->gfx_timeout; break; case AMDGPU_RING_TYPE_COMPUTE: - timeout_ms = adev->compute_timeout; + timeout_jiffies = adev->compute_timeout; break; case AMDGPU_RING_TYPE_SDMA: - timeout_ms = adev->sdma_timeout; + timeout_jiffies = adev->sdma_timeout; break; default: - timeout_ms = adev->gfx_timeout; + timeout_jiffies = adev->gfx_timeout; break; } queue_delayed_work(adev->reset_domain->wq, &queue->hang_detect_work, - msecs_to_jiffies(timeout_ms)); + timeout_jiffies); } void amdgpu_userq_process_fence_irq(struct amdgpu_device *adev, u32 doorbell) From f952ed353a27b46c86c9525a39b7a642850b8139 Mon Sep 17 00:00:00 2001 From: Sunil Khatri Date: Thu, 17 Sep 2026 18:56:45 +0530 Subject: [PATCH 04/13] drm/amdgpu/vcn5.0.1: fix video_timeout unit mismatch in jpeg reset wait MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vcn_v5_0_1_reset_jpeg_pre_helper() passes adev->video_timeout directly to amdgpu_fence_wait_polling(), whose timeout parameter is documented and implemented in usecs (busy-wait loop decrementing by udelay(2)). adev->video_timeout is set in jiffies by amdgpu_device_get_job_timeout_settings(), via msecs_to_jiffies(). Passing it unconverted means the intended ~2s wait for outstanding JPEG fences to complete before the JPEG queue is torn down actually lasts only a couple of microseconds (HZ jiffies interpreted as usecs), so pending jobs are almost never given a real chance to finish before the reset path forces completion in the following helper. Convert the jiffies value to usecs with jiffies_to_usecs() before passing it to amdgpu_fence_wait_polling(). Fixes: fab47d2db5ca ("drm/amdgpu/vcn5.0.1: rework reset handling") Cc: Jesse.Zhang Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Sunil Khatri Reviewed-by: Christian König Signed-off-by: Alex Deucher (cherry picked from commit b8334fec8b90ebffcaa01001a23edca9f29a05e9) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index 1a07c3bf4425..011afc0fdc87 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -1335,7 +1335,8 @@ static int vcn_v5_0_1_reset_jpeg_pre_helper(struct amdgpu_device *adev, int inst /* if Jobs are still pending after timeout, * We'll handle them in the bottom helper */ - amdgpu_fence_wait_polling(ring, wait_seq, adev->video_timeout); + amdgpu_fence_wait_polling(ring, wait_seq, + jiffies_to_usecs(adev->video_timeout)); } return 0; From 6b13ddbf5bb8deec337f9b4887f579097a953f6a Mon Sep 17 00:00:00 2001 From: Sunil Khatri Date: Thu, 17 Sep 2026 18:56:45 +0530 Subject: [PATCH 05/13] drm/amdgpu/vcn4.0.3: fix video_timeout unit mismatch in jpeg reset wait MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vcn_v4_0_3_reset_jpeg_pre_helper() passes adev->video_timeout directly to amdgpu_fence_wait_polling(), whose timeout parameter is documented and implemented in usecs (busy-wait loop decrementing by udelay(2)). adev->video_timeout is set in jiffies by amdgpu_device_get_job_timeout_settings(), via msecs_to_jiffies(). Passing it unconverted means the intended ~2s wait for outstanding JPEG fences to complete before the JPEG queue is torn down actually lasts only a couple of microseconds (HZ jiffies interpreted as usecs), so pending jobs are almost never given a real chance to finish before the reset path forces completion in the following helper. Convert the jiffies value to usecs with jiffies_to_usecs() before passing it to amdgpu_fence_wait_polling(). Fixes: d25c67fd9d6f ("drm/amdgpu/vcn4.0.3: rework reset handling") Cc: Jesse.Zhang Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Sunil Khatri Reviewed-by: Christian König Signed-off-by: Alex Deucher (cherry picked from commit 5feabbd673c10ebee22b880e4d812f08974d2ef7) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index 179b892fb410..62e2e04314dc 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -1689,7 +1689,8 @@ static int vcn_v4_0_3_reset_jpeg_pre_helper(struct amdgpu_device *adev, int inst /* if Jobs are still pending after timeout, * We'll handle them in the bottom helper */ - amdgpu_fence_wait_polling(ring, wait_seq, adev->video_timeout); + amdgpu_fence_wait_polling(ring, wait_seq, + jiffies_to_usecs(adev->video_timeout)); } return 0; From c3a31087b1c8df679b653c1a09d9abe5ff7ec8ef Mon Sep 17 00:00:00 2001 From: Asad Kamal Date: Fri, 28 Aug 2026 15:59:21 +0800 Subject: [PATCH 06/13] drm/amdkfd: fix use-after-free and multi-container gap in kfd_dev_mapping kfd_dev_mapping caches the address_space of the first /dev/kfd opener so that the GPU reset path can call unmap_mapping_range() to zap all userspace mappings of doorbell and MMIO ranges. This design has two bugs that both manifest under SRIOV with multiple containers: 1. Use-after-free / rwsem deadlock. The cached pointer refers to an inode owned by the first opener's container. When that container exits and its inode is released, kfd_dev_mapping becomes a dangling pointer. A subsequent GPU reset dereferences it inside unmap_mapping_range(), which takes i_mmap_rwsem on the freed inode, causing a hard hang observable as an uninterruptible rwsem wait. 2. Multi-container gap. Only the first opener's address_space is cached; VMAs created by later openers live in a different address_space and are never reached by unmap_mapping_range(). After a GPU reset those stale mappings keep doorbell and MMIO pages accessible to guest userspace with no GPU behind them, risking PCIe transaction timeouts and NMI panics. Fix both bugs with the same approach used by DRM core (drm_drv.c): create a private pseudo-filesystem at module init time and allocate one anonymous inode from it. In kfd_open() redirect every opener's file->f_mapping to that inode's address_space. The inode is module-owned, lives exactly as long as the amdgpu module, and collects VMAs from all openers in one address_space. A single unmap_mapping_range() call in the reset path then correctly reaches every container's mappings with no dangling pointer risk. The hang manifests as an NMI backtrace on the GPU reset workqueue stuck spinning in rwsem_down_read_slowpath() with a corrupted i_mmap_rwsem: Workqueue: amdgpu-reset-dev xgpu_ai_mailbox_flr_work [amdgpu] Call Trace: kvm_wait+0x1f/0x40 __pv_queued_spin_lock_slowpath+0x31d/0x3a0 _raw_spin_lock_irq+0x51/0x80 rwsem_down_read_slowpath+0xb3/0x550 down_read+0x48/0xd0 unmap_mapping_range+0x71/0x140 kfd_dev_unmap_mapping_range+0x5b/0x140 [amdgpu] amdgpu_amdkfd_clear_kfd_mapping+0xd8/0x190 [amdgpu] amdgpu_device_gpu_recover+0x232/0x450 [amdgpu] xgpu_ai_mailbox_flr_work+0xb5/0xc0 [amdgpu] process_one_work+0x18e/0x3e0 worker_thread+0x2e3/0x420 kthread+0x10a/0x230 Fixes: 70cadefcc616 ("drm/amdgpu: unmap all user mappings of framebuffer and doorbell before mode1 reset") Signed-off-by: Asad Kamal Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher (cherry picked from commit 1128b4a52de1572e87431de837fd9850cb99542c) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 71 +++++++++++++++++++----- 1 file changed, 57 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 504a286368eb..344da6c0e96a 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -70,18 +71,54 @@ static const struct class kfd_class = { }; /* - * Cache the address space of the chardev on first open so that the reset - * path can drop all userspace mappings of doorbell and MMIO ranges via - * unmap_mapping_range(). + * Private pseudo-filesystem for KFD, Provides a stable, module-owned + * inode whose address_space is the unmap target for all /dev/kfd + * openers during GPU reset. */ -static struct address_space *kfd_dev_mapping; +static struct vfsmount *kfd_fs_mnt; +static int kfd_fs_cnt; + +static int kfd_fs_init_fs_context(struct fs_context *fc) +{ + return init_pseudo(fc, 0x4b464400 /* "KFD" */) ? 0 : -ENOMEM; +} + +static struct file_system_type kfd_fs_type = { + .name = "kfd", + .init_fs_context = kfd_fs_init_fs_context, + .kill_sb = kill_anon_super, +}; + +static struct inode *kfd_fs_inode_new(void) +{ + struct inode *inode; + int r; + + r = simple_pin_fs(&kfd_fs_type, &kfd_fs_mnt, &kfd_fs_cnt); + if (r < 0) + return ERR_PTR(r); + + inode = alloc_anon_inode(kfd_fs_mnt->mnt_sb); + if (IS_ERR(inode)) + simple_release_fs(&kfd_fs_mnt, &kfd_fs_cnt); + + return inode; +} + +static void kfd_fs_inode_free(struct inode *inode) +{ + if (inode) { + iput(inode); + simple_release_fs(&kfd_fs_mnt, &kfd_fs_cnt); + } +} + +static struct inode *kfd_anon_inode; void kfd_dev_unmap_mapping_range(loff_t const holebegin, loff_t const holelen) { - struct address_space *mapping = READ_ONCE(kfd_dev_mapping); - - if (mapping) - unmap_mapping_range(mapping, holebegin, holelen, 1); + if (kfd_anon_inode) + unmap_mapping_range(kfd_anon_inode->i_mapping, holebegin, holelen, 1); } static inline struct kfd_process_device *kfd_lock_pdd_by_id(struct kfd_process *p, __u32 gpu_id) @@ -107,6 +144,13 @@ int kfd_chardev_init(void) { int err = 0; + kfd_anon_inode = kfd_fs_inode_new(); + if (IS_ERR(kfd_anon_inode)) { + err = PTR_ERR(kfd_anon_inode); + kfd_anon_inode = NULL; + return err; + } + kfd_char_dev_major = register_chrdev(0, kfd_dev_name, &kfd_fops); err = kfd_char_dev_major; if (err < 0) @@ -130,6 +174,8 @@ int kfd_chardev_init(void) err_class_create: unregister_chrdev(kfd_char_dev_major, kfd_dev_name); err_register_chrdev: + kfd_fs_inode_free(kfd_anon_inode); + kfd_anon_inode = NULL; return err; } @@ -138,6 +184,8 @@ void kfd_chardev_exit(void) device_destroy(&kfd_class, MKDEV(kfd_char_dev_major, 0)); class_unregister(&kfd_class); unregister_chrdev(kfd_char_dev_major, kfd_dev_name); + kfd_fs_inode_free(kfd_anon_inode); + kfd_anon_inode = NULL; kfd_device = NULL; } @@ -150,12 +198,7 @@ static int kfd_open(struct inode *inode, struct file *filep) if (iminor(inode) != 0) return -ENODEV; - /* - * /dev/kfd is a single chardev so all opens share one inode. Cache - * its address_space on the first open for use by the reset path. - */ - if (!READ_ONCE(kfd_dev_mapping)) - cmpxchg(&kfd_dev_mapping, NULL, inode->i_mapping); + filep->f_mapping = kfd_anon_inode->i_mapping; is_32bit_user_mode = in_compat_syscall(); From aea841bc62a76242396610d22d8ff40c13065f64 Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Wed, 16 Sep 2026 10:01:39 +0000 Subject: [PATCH 07/13] drm/amdgpu: Fix vmid_wait fence leak in amdgpu_ring_init() amdgpu_ring_init() initializes ring->vmid_wait with a reference to the stub fence taken via dma_fence_get_stub(). When a later step of the initialization fails, e.g. amdgpu_fence_driver_init_ring(), a writeback slot allocation or the ring buffer allocation, the function returns an error without releasing the stub fence reference and the reference is leaked if the ring is torn down without amdgpu_ring_fini(). Move the stub fence assignment to the end of the initialization, right before the ring is registered with the GPU scheduler, where no further failure is possible. The stub fence is only consumed by command submission handling in amdgpu_ids.c once the ring is up and running, so nothing reads it during the error-prone part of the initialization. Fixes: 48e9fbd1a284 ("drm/amdgpu: initialize the vmid_wait with the stub fence") Signed-off-by: Wentao Liang Signed-off-by: Alex Deucher (cherry picked from commit f2b96986851203e9c50ca0d13aaa3581ca3e8ebd) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 686c92e96025..5922406d0a03 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -254,7 +254,6 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, ring->adev = adev; ring->num_hw_submission = sched_hw_submission; ring->sched_score = sched_score; - ring->vmid_wait = dma_fence_get_stub(); ring->idx = adev->num_rings++; adev->rings[ring->idx] = ring; @@ -374,6 +373,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, ring->max_dw = max_dw; ring->hw_prio = hw_prio; + ring->vmid_wait = dma_fence_get_stub(); if (!ring->no_scheduler && ring->funcs->type < AMDGPU_HW_IP_NUM) { hw_ip = ring->funcs->type; From a997baa61179b450bd55c4810c7ccfed3b753a54 Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Wed, 16 Sep 2026 09:54:32 +0000 Subject: [PATCH 08/13] drm/amdgpu: Fix acpi device leak in amdgpu_acpi_enumerate_xcc() amdgpu_acpi_enumerate_xcc() looks up each XCC ACPI device with acpi_dev_get_first_match_dev(), which takes a reference to the device. The reference is dropped with acpi_dev_put() after the XCC info is initialized, but if the kzalloc_obj() allocation of the XCC info fails the function returns -ENOMEM without releasing the reference, leaking the last reference to the ACPI device. Drop the ACPI device reference on the allocation failure path before returning. Fixes: 4d5275ab0b18 ("drm/amdgpu: Add parsing of acpi xcc objects") Reviewed-by: Lijo Lazar Signed-off-by: Wentao Liang Signed-off-by: Alex Deucher (cherry picked from commit 9211ef48b31ec66999cf55e04d0cbc60cd855fd5) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index 7f5abb03be1b..8b8acf98fdfe 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -1167,8 +1167,10 @@ int amdgpu_acpi_enumerate_xcc(void) } xcc_info = kzalloc_obj(struct amdgpu_acpi_xcc_info); - if (!xcc_info) + if (!xcc_info) { + acpi_dev_put(acpi_dev); return -ENOMEM; + } INIT_LIST_HEAD(&xcc_info->list); xcc_info->handle = acpi_device_handle(acpi_dev); From b4f7b4459b1b155e4c4977a6482b5df2cf08758c Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Wed, 16 Sep 2026 09:55:36 +0000 Subject: [PATCH 09/13] drm/amdgpu: Fix last_update fence leak in amdgpu_vm_init() amdgpu_vm_init() initializes vm->last_update, vm->last_unlocked and vm->last_tlb_flush with references to the stub fence taken via dma_fence_get_stub(). The error label at the end of the function releases the last_unlocked and last_tlb_flush references with dma_fence_put(), but the reference stored in vm->last_update is never dropped, so whenever the page table root creation, the reservation of the root BO or the PASID registration fails, the stub fence reference leaks. Drop the vm->last_update reference together with the other stub fence references on the error path. Fixes: 187916e6ed9d ("drm/amdgpu: install stub fence into potential unused fence pointers") Signed-off-by: Wentao Liang Signed-off-by: Alex Deucher (cherry picked from commit e7979c84fc05a176bdf855ee664871b1648404c9) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index bb04101b0fb5..4a63b472f68e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2678,6 +2678,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, amdgpu_bo_unref(&root_bo); error_free_delayed: + dma_fence_put(vm->last_update); dma_fence_put(vm->last_tlb_flush); dma_fence_put(vm->last_unlocked); ttm_lru_bulk_move_fini(&adev->mman.bdev, &vm->lru_bulk_move); From 2b86ab1bd6673c525adda88819d7658ba9e784ec Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Wed, 16 Sep 2026 09:58:05 +0000 Subject: [PATCH 10/13] drm/amdgpu: Fix runtime PM leak in amdgpu_debugfs_test_ib_show() amdgpu_debugfs_test_ib_show() resumes the device with pm_runtime_get_sync() before taking the reset domain semaphore with down_write_killable(). If the write lock acquisition is interrupted, the function returns without calling pm_runtime_put_autosuspend(), leaking the runtime PM reference acquired for the device and keeping the GPU awake. Drop the runtime PM reference on the interrupted down_write_killable() error path before returning. Fixes: 6049db43d6dd ("drm/amdgpu: change reset lock from mutex to rw_semaphore") Signed-off-by: Wentao Liang Signed-off-by: Alex Deucher (cherry picked from commit ec30a576c2d4c0364549e6c04218f50704ef56c8) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 132d054900b5..aca1a8045afa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -1780,8 +1780,10 @@ static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused) /* Avoid accidently unparking the sched thread during GPU reset */ r = down_write_killable(&adev->reset_domain->sem); - if (r) + if (r) { + pm_runtime_put_autosuspend(dev->dev); return r; + } /* hold on the scheduler */ for (i = 0; i < AMDGPU_MAX_RINGS; i++) { From 0fd5e9ddf362b1253b3c94b858371f90400e5c4a Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Wed, 23 Sep 2026 11:31:18 -0600 Subject: [PATCH 11/13] drm/amd/display: Relax DML frame limit with UBSAN [WHY] UBSAN instrumentation adds checks and handler calls and increases stack usage in the large DML calculation functions, similar to KASAN and KCSAN. With UBSAN enabled these files exceed the default -Wframe-larger-than limit and fail to build when -Werror is in effect. Reproduced with LLVM (make LLVM=1, clang 19.1.1), CONFIG_UBSAN=y, CONFIG_GCOV_PROFILE_ALL=y and CONFIG_DRM_AMDGPU_WERROR=y on x86_64. [HOW] Include CONFIG_UBSAN in the sanitizer check that selects the higher per-file frame warning limit in the dml and dml2_0 Makefiles. Suggested-by: Leo Li Assisted-by: Copilot:Claude-Opus-5.5 Signed-off-by: Alex Hung Signed-off-by: Alex Deucher (cherry picked from commit ebf8b0fd8508b744f85a8eee82b745b1d3502dd0) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dml2_0/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 10d4ace04d4f..096520bd27c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -29,7 +29,7 @@ dml_ccflags := $(CC_FLAGS_FPU) dml_rcflags := $(CC_FLAGS_NO_FPU) ifneq ($(CONFIG_FRAME_WARN),0) - ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y) + ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)$(CONFIG_UBSAN)),y) ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_COMPILE_TEST),yy) frame_warn_limit := 4096 else diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile b/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile index 5388bf094fbc..4d682e92df1d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile @@ -28,7 +28,7 @@ dml2_ccflags := $(CC_FLAGS_FPU) dml2_rcflags := $(CC_FLAGS_NO_FPU) ifneq ($(CONFIG_FRAME_WARN),0) - ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y) + ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)$(CONFIG_UBSAN)),y) ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_COMPILE_TEST),yy) frame_warn_limit := 4096 else From 18779dd84515db093fedb4ebaf0998c9b165a5fb Mon Sep 17 00:00:00 2001 From: Ivan Lipski Date: Fri, 21 Aug 2026 00:04:53 -0400 Subject: [PATCH 12/13] drm/amd/display: Bump frame warning limit for clang builds of dml [Why&How] When building the DML files with clang without any sanitizer or LTO, the following -Wframe-larger-than errors break the build under CONFIG_WERROR: display_mode_vba_30.c: error: stack frame size (2512) exceeds limit (2048) in 'dml30_ModeSupportAndSystemConfigurationFull' display_mode_vba_31.c: error: stack frame size (2416) exceeds limit (2048) in 'dml31_ModeSupportAndSystemConfigurationFull' display_mode_vba_314.c: error: stack frame size (2392) exceeds limit (2048) in 'dml314_ModeSupportAndSystemConfigurationFull' Clang consistently spills more than gcc, pushing the frame past the 2048 byte limit. Apply an existing approach of increasing the warn stack size to the non-sanitizer path so plain clang builds use a 3072 byte limit. Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/5642 Signed-off-by: Ivan Lipski Signed-off-by: Alex Deucher (cherry picked from commit 21711b6e66bb7b41b1aec67b2d99aafe768c8fcb) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 096520bd27c6..79eeb3721b99 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -36,7 +36,11 @@ ifneq ($(CONFIG_FRAME_WARN),0) frame_warn_limit := 3072 endif else - frame_warn_limit := 2048 + ifeq ($(CONFIG_CC_IS_CLANG),y) + frame_warn_limit := 3072 + else + frame_warn_limit := 2048 + endif endif ifeq ($(call test-lt, $(CONFIG_FRAME_WARN), $(frame_warn_limit)),y) From 15814c01ac57643edf1662a076d2961332f277a5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 23 Sep 2026 21:44:30 -0400 Subject: [PATCH 13/13] drm/amd/display: Bump frame warning limit for all builds of dml Some configs with gcc are also now affected. Signed-off-by: Alex Deucher (cherry picked from commit 76b9706e7fa1a6e374703170128b1be2f590cda7) --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 6 +----- drivers/gpu/drm/amd/display/dc/dml2_0/Makefile | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 79eeb3721b99..91465ac05c97 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -36,11 +36,7 @@ ifneq ($(CONFIG_FRAME_WARN),0) frame_warn_limit := 3072 endif else - ifeq ($(CONFIG_CC_IS_CLANG),y) - frame_warn_limit := 3072 - else - frame_warn_limit := 2048 - endif + frame_warn_limit := 3072 endif ifeq ($(call test-lt, $(CONFIG_FRAME_WARN), $(frame_warn_limit)),y) diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile b/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile index 4d682e92df1d..39ee2d1999dd 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile @@ -35,7 +35,7 @@ ifneq ($(CONFIG_FRAME_WARN),0) frame_warn_limit := 3072 endif else - frame_warn_limit := 2056 + frame_warn_limit := 3072 endif ifeq ($(call test-lt, $(CONFIG_FRAME_WARN), $(frame_warn_limit)),y)