amdgpu_device_gpu_recover() removes the user doorbell and MMIO mappings
and calls amdgpu_amdkfd_pre_reset() before it checks whether the guilty
job has signaled. If the job has already signaled by then, the ASIC
reset is skipped, but KFD has been suspended for a reset that will not
happen: user doorbell and MMIO mappings are gone, and with the reset
domain held the HIQ and user queues stay mapped. On SR-IOV nothing
resumes KFD, because the only amdgpu_amdkfd_post_reset() for a VF is in
amdgpu_device_reset_sriov(). kfd_locked is leaked and later
open("/dev/kfd") fails with -EINVAL.

Move the unmapping and amdgpu_amdkfd_pre_reset() after the signal check,
so that they only run when the ASIC is reset, and skip
amdgpu_amdkfd_post_reset() on bare metal when the job has signaled.
Emergency restart does not check the fence and still runs them.
amdgpu_pci_error_detected() now calls amdgpu_amdkfd_pre_reset() itself,
since amdgpu_device_halt_activities() no longer does.

The check can also see a job that was never submitted to the ring: when
its finished fence already carries an error, for example one copied from
its entity by amdgpu_job_prepare_job(), amdgpu_job_run() skips it, and
the job stays on the pending list until it is freed. Its HW fence was
never initialized, and dma_fence_get_status() would take its NULL lock.
Such a job cannot have hung the ring, so skip the ASIC reset for it as
for a signaled job.

Fixes: 9f4f2c1a3524 ("drm/amd/amdgpu: fix the kfd pre_reset sequence in sriov")
Signed-off-by: Filip Adzic <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 47 ++++++++++++++--------
 1 file changed, 30 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 44091ac12fa9..01648b0f28fd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -5541,8 +5541,6 @@ static void amdgpu_device_halt_activities(struct 
amdgpu_device *adev,
 
                cancel_delayed_work_sync(&tmp_adev->delayed_init_work);
 
-               amdgpu_amdkfd_pre_reset(tmp_adev, reset_context);
-
                /*
                 * Mark these ASICs to be reset as untracked first
                 * And add them back after reset completed
@@ -5687,13 +5685,15 @@ static int amdgpu_device_sched_resume(struct list_head 
*device_list,
 
 static void amdgpu_device_gpu_resume(struct amdgpu_device *adev,
                              struct list_head *device_list,
-                             bool   need_emergency_restart)
+                             bool   need_emergency_restart,
+                             bool   job_signaled)
 {
        struct amdgpu_device *tmp_adev = NULL;
 
        list_for_each_entry(tmp_adev, device_list, reset_list) {
                /* unlock kfd: SRIOV would do it separately */
-               if (!need_emergency_restart && !amdgpu_sriov_vf(tmp_adev))
+               if (!need_emergency_restart && !job_signaled &&
+                   !amdgpu_sriov_vf(tmp_adev))
                        amdgpu_amdkfd_post_reset(tmp_adev);
 
                /* kfd_post_reset will do nothing if kfd device is not 
initialized,
@@ -5730,6 +5730,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
                              struct amdgpu_reset_context *reset_context)
 {
        struct list_head device_list;
+       struct amdgpu_device *tmp_adev = NULL;
        bool job_signaled = false;
        struct amdgpu_hive_info *hive = NULL;
        int r = 0;
@@ -5794,28 +5795,36 @@ int amdgpu_device_gpu_recover(struct amdgpu_device 
*adev,
        /* We need to lock reset domain only once both for XGMI and single 
device */
        amdgpu_device_recovery_get_reset_lock(adev, &device_list);
 
-       /* unmap all the mappings of doorbell and framebuffer to prevent user 
space from
-        * accessing them
-        */
-       unmap_mapping_range(adev->ddev.anon_inode->i_mapping, 0, 0, 1);
-       amdgpu_amdkfd_clear_kfd_mapping(adev);
-
        amdgpu_device_halt_activities(adev, job, reset_context, &device_list,
                                      hive, need_emergency_restart);
-       if (need_emergency_restart)
-               goto skip_sched_resume;
        /*
         * Must check guilty signal here since after this point all old
-        * HW fences are force signaled.
+        * HW fences are force signaled. A job whose HW fence was never
+        * initialized was not submitted to the ring, so it cannot have hung it.
         *
         * job->base holds a reference to parent fence
         */
-       if (job && (dma_fence_get_status(&job->hw_fence->base) > 0)) {
+       if (job && !need_emergency_restart &&
+           (!dma_fence_was_initialized(&job->hw_fence->base) ||
+            dma_fence_get_status(&job->hw_fence->base) > 0)) {
                job_signaled = true;
-               dev_info(adev->dev, "Guilty job already signaled, skipping HW 
reset");
+               dev_info(adev->dev, "Guilty job %s, skipping HW reset",
+                        dma_fence_was_initialized(&job->hw_fence->base) ?
+                        "already signaled" : "was not submitted");
                goto skip_hw_reset;
        }
 
+       /* unmap all the mappings of doorbell and framebuffer to prevent user 
space from
+        * accessing them
+        */
+       unmap_mapping_range(adev->ddev.anon_inode->i_mapping, 0, 0, 1);
+       amdgpu_amdkfd_clear_kfd_mapping(adev);
+       list_for_each_entry(tmp_adev, &device_list, reset_list)
+               amdgpu_amdkfd_pre_reset(tmp_adev, reset_context);
+
+       if (need_emergency_restart)
+               goto skip_sched_resume;
+
        r = amdgpu_device_asic_reset(adev, &device_list, reset_context);
        if (r)
                goto reset_unlock;
@@ -5824,7 +5833,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
        if (r)
                goto reset_unlock;
 skip_sched_resume:
-       amdgpu_device_gpu_resume(adev, &device_list, need_emergency_restart);
+       amdgpu_device_gpu_resume(adev, &device_list, need_emergency_restart,
+                                job_signaled);
 reset_unlock:
        amdgpu_device_recovery_put_reset_lock(adev, &device_list);
        amdgpu_ras_post_reset(adev, &device_list);
@@ -6214,6 +6224,7 @@ pci_ers_result_t amdgpu_pci_error_detected(struct pci_dev 
*pdev, pci_channel_sta
        struct amdgpu_hive_info *hive __free(xgmi_put_hive) =
                amdgpu_get_xgmi_hive(adev);
        struct amdgpu_reset_context reset_context;
+       struct amdgpu_device *tmp_adev;
        struct list_head device_list;
 
        dev_info(adev->dev, "PCI error: detected callback!!\n");
@@ -6254,6 +6265,8 @@ pci_ers_result_t amdgpu_pci_error_detected(struct pci_dev 
*pdev, pci_channel_sta
                amdgpu_device_recovery_get_reset_lock(adev, &device_list);
                amdgpu_device_halt_activities(adev, NULL, &reset_context, 
&device_list,
                                              hive, false);
+               list_for_each_entry(tmp_adev, &device_list, reset_list)
+                       amdgpu_amdkfd_pre_reset(tmp_adev, &reset_context);
                if (hive)
                        mutex_unlock(&hive->hive_lock);
                return PCI_ERS_RESULT_NEED_RESET;
@@ -6428,7 +6441,7 @@ void amdgpu_pci_resume(struct pci_dev *pdev)
                list_add_tail(&adev->reset_list, &device_list);
        }
        amdgpu_device_sched_resume(&device_list, NULL, NULL);
-       amdgpu_device_gpu_resume(adev, &device_list, false);
+       amdgpu_device_gpu_resume(adev, &device_list, false, false);
        amdgpu_device_recovery_put_reset_lock(adev, &device_list);
 
        if (hive) {
-- 
2.43.0

Reply via email to