From: Alex Deucher <[email protected]>

We need to increment the reset counter, force fence completion,
and set the wedged event when a user queue is reset, but only
for the guilty queue.  We don't want additional events for
collateral damage.

Only increment the reset counter and set the wedged event
in the top level userq reset callers (both KGD and KFD).
This aligns with how this is managed for kernel queue resets.

v2: fix task info refcount handling, align with
    kfd error reporting.

Signed-off-by: Alex Deucher <[email protected]>
Cc: Srinivasan Shanmugam <[email protected]>
Cc: Prike Liang <[email protected]>
Cc: Sunil Khatri <[email protected]>
Cc: Lazar Lijo <[email protected]>
Reviewed-by: Srinivasan Shanmugam <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c      | 18 +++++++++++++++++-
 drivers/gpu/drm/amd/amdgpu/mes_userqueue.c     |  2 --
 .../drm/amd/amdkfd/kfd_device_queue_manager.c  | 17 ++++++++++++++++-
 3 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
index ab3ef3a9f655..20bc15ad55f4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -144,6 +144,8 @@ static void amdgpu_userq_hang_detect_work(struct 
work_struct *work)
        struct amdgpu_device *adev = uq_mgr->adev;
        const struct amdgpu_userq_funcs *userq_funcs =
                adev->userq_funcs[queue->queue_type];
+       struct drm_wedge_task_info *info = NULL;
+       struct amdgpu_task_info *ti = NULL;
        bool gpu_reset = false;
 
        if (unlikely(adev->debug_disable_gpu_ring_reset)) {
@@ -158,6 +160,14 @@ static void amdgpu_userq_hang_detect_work(struct 
work_struct *work)
        if (!amdgpu_gpu_recovery)
                return;
 
+       if (queue->vm && queue->vm->pasid) {
+               ti = amdgpu_vm_get_task_info_pasid(adev, queue->vm->pasid);
+               if (ti) {
+                       amdgpu_vm_print_task_info(adev, ti);
+                       info = &ti->task;
+               }
+       }
+
        if (amdgpu_userq_is_reset_type_supported(adev, queue->queue_type,
                                                 AMDGPU_RESET_TYPE_PER_QUEUE)) {
                int r;
@@ -167,11 +177,17 @@ static void amdgpu_userq_hang_detect_work(struct 
work_struct *work)
                                                         queue, NULL, NULL);
                else
                        r = userq_funcs->reset(queue);
-               if (r)
+               if (r) {
                        gpu_reset = true;
+               } else {
+                       atomic_inc(&adev->gpu_reset_counter);
+                       amdgpu_userq_fence_driver_force_completion(queue);
+                       drm_dev_wedged_event(adev_to_drm(adev), 
DRM_WEDGE_RECOVERY_NONE, info);
+               }
        } else {
                gpu_reset = true;
        }
+       amdgpu_vm_put_task_info(ti);
 
        /*
         * Don't schedule the work here! Scheduling or queue work from one reset
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c 
b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
index 3fad95199e0c..3d27d2aa2cd0 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
@@ -258,9 +258,7 @@ int mes_userq_reset_queue(struct amdgpu_device *adev,
                                r = mes_userq_unmap(uq);
                                if (r)
                                        return r;
-                               atomic_inc(&adev->gpu_reset_counter);
                                amdgpu_userq_fence_driver_force_completion(uq);
-                               drm_dev_wedged_event(adev_to_drm(adev), 
DRM_WEDGE_RECOVERY_NONE, NULL);
                                break;
                        }
                }
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index f6a749fbdd8e..ebab66e1a6c1 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -448,6 +448,9 @@ int kfd_reset_queue_mes(struct device_queue_manager *dqm, 
int queue_type,
 static int reset_queues_mes(struct device_queue_manager *dqm, struct queue *q)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)dqm->dev->adev;
+       struct drm_wedge_task_info *info = NULL;
+       struct amdgpu_task_info *ti = NULL;
+       struct kfd_process_device *pdd;
        unsigned int num_hung = 0;
        int r = 0;
        struct mes_remove_queue_input queue_input;
@@ -476,13 +479,25 @@ static int reset_queues_mes(struct device_queue_manager 
*dqm, struct queue *q)
        r = amdgpu_gfx_reset_mes_compute(adev, NULL, NULL, NULL, &num_hung, 
&queue_input);
        if (r)
                goto fail;
+       pdd = kfd_get_process_device_data(q->device, q->process);
+       if (pdd) {
+               ti = amdgpu_vm_get_task_info_pasid(adev, pdd->pasid);
+               if (ti) {
+                       amdgpu_vm_print_task_info(adev, ti);
+                       info = &ti->task;
+               }
+       }
 
        dqm->detect_hang_count = num_hung;
        /* When MES doesn't detect any queue hang, no reset happens. Don't 
signal reset
         * event.
         */
-       if (dqm->detect_hang_count)
+       if (dqm->detect_hang_count) {
                kfd_signal_reset_event(dqm->dev);
+               atomic_inc(&adev->gpu_reset_counter);
+               drm_dev_wedged_event(adev_to_drm(adev), 
DRM_WEDGE_RECOVERY_NONE, info);
+       }
+       amdgpu_vm_put_task_info(ti);
 
 fail:
        dqm->detect_hang_count = 0;
-- 
2.34.1

Reply via email to