FAILED: patch "[PATCH] drm/amdgpu: Fix last_update fence leak in amdgpu_vm_init()" failed to apply to 5.10-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x b4f7b4459b1b155e4c4977a6482b5df2cf08758c
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026092916-hurry-appendix-2bde@gregkh' --subject-prefix 'PATCH 5.10.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From b4f7b4459b1b155e4c4977a6482b5df2cf08758c Mon Sep 17 00:00:00 2001
From: Wentao Liang <[email protected]>
Date: Wed, 16 Sep 2026 09:55:36 +0000
Subject: [PATCH] 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.
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +1 -0
@@ -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);
Sasha Levin
maintainerPATCH 1/2 drm/amdgpu: simplify VM update tracking a bit
From: Christian König <[email protected]>
[ Upstream commit e997b82745a5b2419bc5b72735811d7162ac994a ]
Store the 64bit sequence directly. Makes it simpler to use and saves a bit of fence reference counting overhead.
Stable-dep-of: b4f7b4459b1b ("drm/amdgpu: Fix last_update fence leak in amdgpu_vm_init()")
--- drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 40 +++++++----------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | 9 ++---- drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h | 2 +- 4 files changed, 16 insertions(+), 37 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c +11 -29
@@ -276,19 +276,15 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm,struct amdgpu_device *adev = ring->adev;unsigned vmhub = ring->funcs->vmhub;uint64_t fence_context = adev->fence_context + ring->idx; -struct dma_fence *updates = sync->last_vm_update;bool needs_flush = vm->use_cpu_for_update; -int r =0 ; +uint64_t updates = sync->last_vm_update; +int r; *id = vm->reserved_vmid[vmhub]; -if (updates && (*id)->flushed_updates && - updates->context == (*id)->flushed_updates->context && - !dma_fence_is_later (updates, (*id)->flushed_updates)) - updates =NULL ; -if ((*id)->owner != vm->immediate.fence_context || - job->vm_pd_addr != (*id)->pd_gpu_addr || - updates || !(*id)->last_flush || + (*id)->pd_gpu_addr != job->vm_pd_addr || + (*id)->flushed_updates < updates || + !(*id)->last_flush || ((*id)->last_flush->context != fence_context && !dma_fence_is_signaled ((*id)->last_flush))) {struct dma_fence *tmp;
@@ -302,8 +298,7 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm, tmp =amdgpu_sync_peek_fence (&(*id)->active, ring);if (tmp) { *id =NULL ; - r =amdgpu_sync_fence (sync, tmp); -return r; +return amdgpu_sync_fence (sync, tmp); } needs_flush = true; }
@@ -315,10 +310,7 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm,if (r)return r; -if (updates) { -dma_fence_put ((*id)->flushed_updates); - (*id)->flushed_updates =dma_fence_get (updates); - } + (*id)->flushed_updates = updates; job->vm_needs_flush = needs_flush;return 0 ; }
@@ -346,7 +338,7 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm,unsigned vmhub = ring->funcs->vmhub;struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub];uint64_t fence_context = adev->fence_context + ring->idx; -struct dma_fence *updates = sync->last_vm_update; +uint64_t updates = sync->last_vm_update;int r; job->vm_needs_flush = vm->use_cpu_for_update;
@@ -354,7 +346,6 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm,/* Check if we can use a VMID already assigned to this VM */ list_for_each_entry_reverse ((*id), &id_mgr->ids_lru, list) {bool needs_flush = vm->use_cpu_for_update; -struct dma_fence *flushed;/* Check all the prerequisites to using this VMID */ if ((*id)->owner != vm->immediate.fence_context)
@@ -368,8 +359,7 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm, !dma_fence_is_signaled((*id)->last_flush))) needs_flush = true; - flushed = (*id)->flushed_updates; -if (updates && (!flushed ||dma_fence_is_later (updates, flushed))) +if ((*id)->flushed_updates < updates) needs_flush = true;if (needs_flush && !adev->vm_manager.concurrent_flush)
@@ -382,11 +372,7 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm,if (r)return r; -if (updates && (!flushed ||dma_fence_is_later (updates, flushed))) { -dma_fence_put ((*id)->flushed_updates); - (*id)->flushed_updates =dma_fence_get (updates); - } - + (*id)->flushed_updates = updates; job->vm_needs_flush |= needs_flush;return 0 ; }
@@ -432,8 +418,6 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring, goto error;if (!id) { -struct dma_fence *updates = sync->last_vm_update; -/* Still no ID to use? Then use the idle one found earlier */ id = idle;
@@ -442,8 +426,7 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring,if (r) goto error; -dma_fence_put (id->flushed_updates); - id->flushed_updates =dma_fence_get (updates); + id->flushed_updates = sync->last_vm_update; job->vm_needs_flush = true; }
@@ -609,7 +592,6 @@ void amdgpu_vmid_mgr_fini(struct amdgpu_device *adev)struct amdgpu_vmid *id = &id_mgr->ids[j];amdgpu_sync_free (&id->active); -dma_fence_put (id->flushed_updates);dma_fence_put (id->last_flush);dma_fence_put (id->pasid_mapping); }
drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h +1 -1
@@ -47,7 +47,7 @@ struct amdgpu_vmid {uint64_t pd_gpu_addr;/* last flushed PD/PT update */ -struct dma_fence *flushed_updates; +uint64_t flushed_updates;uint32_t current_gpu_reset_count;
drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c +3 -6
@@ -49,7 +49,7 @@ static struct kmem_cache *amdgpu_sync_slab;void amdgpu_sync_create (struct amdgpu_sync *sync) {hash_init (sync->fences); - sync->last_vm_update =NULL ; + sync->last_vm_update =0 ; }/**
@@ -183,7 +183,7 @@ int amdgpu_sync_vm_fence(struct amdgpu_sync *sync, struct dma_fence *fence)if (!fence)return 0 ; -amdgpu_sync_keep_later (&sync->last_vm_update, fence); + sync->last_vm_update =max (sync->last_vm_update, fence->seqno);return amdgpu_sync_fence (sync, fence); }
@@ -376,8 +376,7 @@ int amdgpu_sync_clone(struct amdgpu_sync *source, struct amdgpu_sync *clone) } } -dma_fence_put (clone->last_vm_update); - clone->last_vm_update =dma_fence_get (source->last_vm_update); + clone->last_vm_update = source->last_vm_update;return 0 ; }
@@ -419,8 +418,6 @@ void amdgpu_sync_free(struct amdgpu_sync *sync)dma_fence_put (e->fence);kmem_cache_free (amdgpu_sync_slab, e); } - -dma_fence_put (sync->last_vm_update); }/**
drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h +1 -1
@@ -43,7 +43,7 @@ enum amdgpu_sync_mode {*/ struct amdgpu_sync { DECLARE_HASHTABLE(fences, 4); -struct dma_fence *last_vm_update; +uint64_t last_vm_update; };void amdgpu_sync_create (struct amdgpu_sync *sync);
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 drm/amdgpu: Fix last_update fence leak in amdgpu_vm_init()
From: Wentao Liang <[email protected]>
[ Upstream commit b4f7b4459b1b155e4c4977a6482b5df2cf08758c ]
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.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +1 -0
@@ -2942,6 +2942,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, vm->root.base.bo =NULL ; error_free_delayed: +dma_fence_put (vm->last_update);dma_fence_put (vm->last_unlocked);drm_sched_entity_destroy (&vm->delayed);
Signature · 1 line
2.53.0