AMD General > -----Original Message----- > From: amd-gfx <[email protected]> On Behalf Of Alex > Deucher > Sent: Tuesday, July 14, 2026 9:25 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) { > 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; > --
Thanks for addressing the review comments. Looks good to me. The reset accounting is now performed only for the guilty queue in the top-level KGD/KFD reset paths. During a queue recovery, additional collateral queues may also need to be reset as part of the same recovery operation. Those collateral queues still have their fences force-completed, but they no longer increment the device reset counter or generate additional DRM wedged events. As a result, a single recovery operation generates one device-level reset notification, which aligns with the kernel queue reset handling. The task-info reference handling is also now consistent with the existing amdgpu_job_timedout() path. The reference obtained through amdgpu_vm_get_task_info_pasid() is released with amdgpu_vm_put_task_info() after its final use. Reviewed-by: Srinivasan Shanmugam <[email protected]> > 2.55.0
