On 2026-10-05 14:52, Philip Yang wrote:
prange->svm_bo stays set after the range drops its reference in
svm_range_vram_node_free(), it is only cleared later by
svm_range_bo_release(). Taking a new reference based on old->svm_bo can
therefore hit a svm_bo with refcount 0 and svm_range_bo_release_async()
pending, leaving the clone with a freed svm_bo.
Check old->ttm_res under old->lock instead, it is cleared together with
the reference drop, same as svm_range_validate_svm_bo() does.
Signed-off-by: Philip Yang <[email protected]>
Signed-off-by: Mukul Joshi <[email protected]>
---
drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index cfb428c72686..536e804bc2c5 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -2158,7 +2158,14 @@ static struct svm_range *svm_range_clone(struct
svm_range *old)
svm_range_free(new, false);
return NULL;
}
- if (old->svm_bo) {
+
+ /*
+ * Only share svm_bo if old still holds a reference to it (ttm_res
+ * set). Otherwise old->svm_bo may already be at refcount 0 with
+ * svm_range_bo_release_async pending.
+ */
+ mutex_lock(&old->lock);
+ if (old->ttm_res) {
This seems to prevent some legitimate svm_bo sharing opportunities. Can
we use svm_bo_ref_unless_zero to safely get a reference to the BO instead?
Regards,
Felix
new->ttm_res = old->ttm_res;
new->offset = old->offset;
new->svm_bo = svm_range_bo_ref(old->svm_bo);
@@ -2166,6 +2173,8 @@ static struct svm_range *svm_range_clone(struct svm_range
*old)
list_add(&new->svm_bo_list, &new->svm_bo->range_list);
spin_unlock(&new->svm_bo->list_lock);
}
+ mutex_unlock(&old->lock);
+
new->flags = old->flags;
new->preferred_loc = old->preferred_loc;
new->prefetch_loc = old->prefetch_loc;