On 2026-10-05 17:05, Chen, Xiaogang wrote:

On 10/5/2026 3:32 PM, 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.

Use svm_bo_ref_unless_zero() under old->lock to only share the svm_bo if
it is still alive, same as svm_range_validate_svm_bo() does.

v2: use svm_bo_ref_unless_zero instead of checking old->ttm_res, to keep
     sharing the svm_bo when the range dropped its own reference (Felix).

Signed-off-by: Philip Yang <[email protected]>
Signed-off-by: Mukul Joshi <[email protected]>
---
  drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 9 +++++++--
  1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index cfb428c72686..7ffc31df3b87 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -2158,14 +2158,19 @@ static struct svm_range *svm_range_clone(struct svm_range *old)
          svm_range_free(new, false);
          return NULL;
      }
-    if (old->svm_bo) {
+
+    /* old->lock keeps old->svm_bo alive while taking the reference */

How old->lock can keep old->svm_bo alive? This lock protects old prange's data from accessing.
prange->svm_bo and prange->ttm_res set to NULL under prange lock when svm_bo is released.

So holding old->lock while taking the reference guarantees we read either a valid svm_bo pointer or NULL; the structure cannot be freed between reading the pointer and kref_get_unless_zero().
The lock protects the svm_bo pointer, not the svm_bo lifetime itself.

Regards,
Philip

Regards

Xiaogang

+    mutex_lock(&old->lock);
+    if (svm_bo_ref_unless_zero(old->svm_bo)) {
          new->ttm_res = old->ttm_res;
          new->offset = old->offset;
-        new->svm_bo = svm_range_bo_ref(old->svm_bo);
+        new->svm_bo = old->svm_bo;
          spin_lock(&new->svm_bo->list_lock);
          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;

Reply via email to