amdgpu_amdkfd_restore_userptr_worker() and svm_range_restore_work()
reschedule themselves when validation fails with evicted objects
pending. After a surprise removal the restore paths fail with -ENODEV
permanently, so rescheduling just spins the worker uselessly until
cancel_delayed_work_sync() in fini finally stops it - which can take
a while, since process teardown itself is delayed by the dead device.

Treat -ENODEV as terminal in both workers and also stop setting
evicted_bos after it.

Cc: Xiaogang Chen <[email protected]>
Signed-off-by: Olivier Kaloudoff <[email protected]>
---
Changes in v5:
- none

Changes in v4:
- moved the svm_range_restore_work() change here from the SVM
  migration patch (Felix Kuehling)
- assign ret on the evicted_bos-mismatch and confirm_valid-WARN paths,
  fixing a latent uninitialized read introduced in v2

Changes in v3:
- retitled; now covers both restore workers

Changes in v2:
- new
---
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index d668816..2ad6777 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -2827,6 +2827,7 @@ static void amdgpu_amdkfd_restore_userptr_worker(struct 
work_struct *work)
        struct task_struct *usertask;
        struct mm_struct *mm;
        uint32_t evicted_bos;
+       int ret;
 
        mutex_lock(&process_info->notifier_lock);
        evicted_bos = process_info->evicted_bos;
@@ -2846,14 +2847,16 @@ static void amdgpu_amdkfd_restore_userptr_worker(struct 
work_struct *work)
 
        mutex_lock(&process_info->lock);
 
-       if (update_invalid_user_pages(process_info, mm))
+       ret = update_invalid_user_pages(process_info, mm);
+       if (ret)
                goto unlock_out;
        /* userptr_inval_list can be empty if all evicted userptr BOs
         * have been freed. In that case there is nothing to validate
         * and we can just restart the queues.
         */
        if (!list_empty(&process_info->userptr_inval_list)) {
-               if (validate_invalid_user_pages(process_info))
+               ret = validate_invalid_user_pages(process_info);
+               if (ret)
                        goto unlock_out;
        }
        /* Final check for concurrent evicton and atomic update. If
@@ -2862,11 +2865,14 @@ static void amdgpu_amdkfd_restore_userptr_worker(struct 
work_struct *work)
         * reference counting inside KFD will handle this case.
         */
        mutex_lock(&process_info->notifier_lock);
-       if (process_info->evicted_bos != evicted_bos)
+       if (process_info->evicted_bos != evicted_bos) {
+               ret = -EAGAIN;
                goto unlock_notifier_out;
+       }
 
        if (confirm_valid_user_pages_locked(process_info)) {
                WARN(1, "User pages unexpectedly invalid");
+               ret = -EINVAL;
                goto unlock_notifier_out;
        }
 
@@ -2884,8 +2890,10 @@ unlock_notifier_out:
 unlock_out:
        mutex_unlock(&process_info->lock);
 
-       /* If validation failed, reschedule another attempt */
-       if (evicted_bos) {
+       /* If validation failed, reschedule another attempt, unless the
+        * device is gone for good
+        */
+       if (evicted_bos && ret != -ENODEV) {
                queue_delayed_work(system_freezable_wq,
                        &process_info->restore_userptr_work,
                        msecs_to_jiffies(AMDGPU_USERPTR_RESTORE_DELAY_MS));
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index fa4054d..3dab456 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -2013,8 +2013,10 @@ out_reschedule:
        mmap_write_unlock(mm);
        mutex_unlock(&process_info->lock);
 
-       /* If validation failed, reschedule another attempt */
-       if (evicted_ranges) {
+       /* If validation failed, reschedule another attempt, unless the
+        * device is gone for good
+        */
+       if (evicted_ranges && r != -ENODEV) {
                pr_debug("reschedule to restore svm range\n");
                queue_delayed_work(system_freezable_wq, &svms->restore_work,
                        msecs_to_jiffies(AMDGPU_SVM_RANGE_RESTORE_DELAY_MS));
-- 
2.47.3

Reply via email to