From: Honglei Huang <[email protected]>

Add helpers to quiesce and resume KFD compute queues for xnack-off SVM
restore. Use mmget_not_zero() to safely acquire a reference to
svm->gpusvm.mm before calling into KFD, protecting against races with
concurrent mm teardown.

Signed-off-by: Honglei Huang <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_userptr.c | 60 +++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userptr.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userptr.c
index 0b02008be..34b3b4149 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userptr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userptr.c
@@ -566,6 +566,66 @@ void amdgpu_svm_restore_gc_work_func(struct work_struct *w)
                                   
msecs_to_jiffies(AMDGPU_SVM_RANGE_RESTORE_DELAY_MS));
 }
 
+void amdgpu_svm_quiesce_compute(struct amdgpu_svm *svm)
+{
+       struct mm_struct *mm = svm->gpusvm.mm;
+       int ret;
+
+       if (!mm)
+               return;
+
+       if (atomic_cmpxchg(&svm->restore.quiesced, 0, 1) != 0)
+               return;
+
+       if (!mmget_not_zero(mm)) {
+               atomic_set(&svm->restore.quiesced, 0);
+               return;
+       }
+
+       ret = kgd2kfd_quiesce_mm(mm, KFD_QUEUE_EVICTION_TRIGGER_SVM);
+       mmput(mm);
+       if (ret == -ESRCH) {
+               AMDGPU_SVM_TRACE("kfd quiesce skipped no KFD process\n");
+               atomic_set(&svm->restore.quiesced, 0);
+               return;
+       }
+
+       if (ret) {
+               AMDGPU_SVM_TRACE("kfd quiesce failed ret=%d\n", ret);
+               atomic_set(&svm->restore.quiesced, 0);
+               return;
+       }
+
+       AMDGPU_SVM_TRACE("kfd quiesce ret=%d\n", ret);
+}
+
+void amdgpu_svm_resume_compute(struct amdgpu_svm *svm)
+{
+       struct mm_struct *mm = svm->gpusvm.mm;
+       int ret;
+
+       if (atomic_cmpxchg(&svm->restore.quiesced, 1, 0) != 1)
+               return;
+
+       if (!mm)
+               return;
+
+       if (!mmget_not_zero(mm))
+               return;
+
+       ret = kgd2kfd_resume_mm(mm);
+       mmput(mm);
+       if (ret == -ESRCH) {
+               AMDGPU_SVM_TRACE("kfd resume skipped no KFD process\n");
+               return;
+       }
+
+       if (ret)
+               AMDGPU_SVM_TRACE("kfd resume failed ret=%d\n", ret);
+       else
+               AMDGPU_SVM_TRACE("kfd resume ret=%d\n", ret);
+}
+
 int amdgpu_svm_restore_init(struct amdgpu_svm *svm,
                            void (*begin)(struct amdgpu_svm *),
                            void (*end)(struct amdgpu_svm *))
-- 
2.34.1

Reply via email to