AMD General
Regards,
Prike
> -----Original Message-----
> From: Alex Deucher <[email protected]>
> Sent: Tuesday, July 14, 2026 11:55 PM
> To: [email protected]
> Cc: Deucher, Alexander <[email protected]>; SHANMUGAM,
> SRINIVASAN <[email protected]>; Liang, Prike
> <[email protected]>; Khatri, Sunil <[email protected]>; Lazar, Lijo
> <[email protected]>
> Subject: [PATCH V2] drm/amdgpu: properly account for resets with user queues
>
> 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]>
> ---
> 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 6aa75da27f912..58754fc41bb6c 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> @@ -123,6 +123,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)) { @@ -137,6 +139,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;
> @@ -146,11 +156,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 d3d79bbaf9eb7..a1371a9f961d1 100644
> --- a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
> +++ b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
> @@ -234,9 +234,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 0419fe869d4b0..58ccbf955f287 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) {
We may also need to check the has_reset_queue flag before notifying the wedged
event,
since the KFD reset event is only raised when has_reset_queue is set. With it
or not, the patch is
Reviewed-by: Prike Liang <[email protected]>
> 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.55.0