From bf1c9c060ee12c84c3c4ae12ce9209bf61290134 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 13 Jul 2026 16:32:49 -0400 Subject: [PATCH] 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. v3: check for has_reset_queue in KFD path (Prike) Cc: Srinivasan Shanmugam Cc: Prike Liang Cc: Sunil Khatri Cc: Lazar, Lijo Reviewed-by: Srinivasan Shanmugam Reviewed-by: Lijo Lazar Reviewed-by: Prike Liang Signed-off-by: Alex Deucher --- 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 | 19 ++++++++++++++++++- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c index babaabe2d891..969f49592450 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 e099304b4ac4..df4efdea1136 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c @@ -239,9 +239,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 5446d89a84b3..51ee9c39104b 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,27 @@ 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); + if (pdd && pdd->has_reset_queue) { + 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;