On 7/14/26 10:02, Srinivasan Shanmugam wrote:
> Signal QUEUE_RESET EVENTFD subscriptions when hung user queues are
> detected.
> 
> MES reports the doorbell indices of hung queues. Use the existing
> doorbell-to-queue mapping to resolve the affected queue without scanning
> all user queues.
> 
> Consolidate the queue state update, reset accounting, EVENTFD signaling,
> fence completion, and wedged event notification in a common helper. Use
> the helper for both the original guilty queue and additional affected
> queues.
> 
> EVENTFD remains notification-only.
> 
> v2: (per Christian)
>  - Use the doorbell xarray to look up affected queues instead of scanning
>    all queues.
>  - Move queue reset handling into amdgpu_userq.c.
>  - Consolidate queue state updates, EVENTFD signaling, and fence
>    completion in a single helper.
> 
> v3: Rebase only.
> 
> v4: (per Alex)
>  - Rebase on Alex's "drm/amdgpu/userq: properly account for resets".
>  - Preserve the reset counter update in the common hung queue helper.
>  - Use amdgpu_userq_handle_hung_queue() for both successful queue reset
>    paths.
> 
> Suggested-by: Christian König <[email protected]>
> Suggested-by: Alex Deucher <[email protected]>
> Signed-off-by: Srinivasan Shanmugam <[email protected]>

Acked-by: Christian König <[email protected]>

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c  | 39 +++++++++---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h  |  2 +
>  drivers/gpu/drm/amd/amdgpu/mes_userqueue.c | 72 ++++++++++++++--------
>  3 files changed, 80 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> index fb0d335875af..65b20d7a4b18 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> @@ -135,6 +135,34 @@ static void amdgpu_userq_mgr_reset_work(struct 
> work_struct *work)
>       amdgpu_device_gpu_recover(adev, NULL, &reset_context);
>  }
>  
> +/**
> + * amdgpu_userq_handle_hung_queue - handle a successfully reset hung queue
> + * @adev: AMDGPU device
> + * @queue: affected user queue
> + *
> + * Mark the queue as hung, account for the reset, force-complete its
> + * fences, notify matching QUEUE_RESET EVENTFD subscribers, and send
> + * the DRM wedged event.
> + */
> +void amdgpu_userq_handle_hung_queue(struct amdgpu_device *adev,
> +                                 struct amdgpu_usermode_queue *queue)
> +{
> +     struct amdgpu_eventfd_mgr *eventfd_mgr;
> +
> +     queue->state = AMDGPU_USERQ_STATE_HUNG;
> +     atomic_inc(&adev->gpu_reset_counter);
> +
> +     amdgpu_userq_fence_driver_force_completion(queue);
> +
> +     eventfd_mgr = amdgpu_userq_eventfd_mgr(queue->userq_mgr);
> +     amdgpu_eventfd_signal(eventfd_mgr,
> +                           DRM_AMDGPU_EVENT_TYPE_QUEUE_RESET,
> +                           queue);
> +
> +     drm_dev_wedged_event(adev_to_drm(adev),
> +                          DRM_WEDGE_RECOVERY_NONE, NULL);
> +}
> +
>  static void amdgpu_userq_hang_detect_work(struct work_struct *work)
>  {
>       struct amdgpu_usermode_queue *queue =
> @@ -167,13 +195,10 @@ 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, NULL);
> -             }
> +             else
> +                     amdgpu_userq_handle_hung_queue(adev, queue);
>       } else {
>               gpu_reset = true;
>       }
> @@ -247,8 +272,6 @@ void amdgpu_userq_process_fence_irq(struct amdgpu_device 
> *adev, u32 doorbell)
>       xa_unlock_irqrestore(xa, flags);
>  }
>  
> -
> -
>  int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
>                                  struct amdgpu_usermode_queue *queue,
>                                  u64 addr, u64 expected_size,
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> index b69621311b80..526e007e300e 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> @@ -180,6 +180,8 @@ void amdgpu_userq_pre_reset(struct amdgpu_device *adev);
>  int amdgpu_userq_post_reset(struct amdgpu_device *adev, bool vram_lost);
>  void amdgpu_userq_start_hang_detect_work(struct amdgpu_usermode_queue 
> *queue);
>  void amdgpu_userq_process_fence_irq(struct amdgpu_device *adev, u32 
> doorbell);
> +void amdgpu_userq_handle_hung_queue(struct amdgpu_device *adev,
> +                                 struct amdgpu_usermode_queue *queue);
>  
>  /*
>   * CP packs the per-process doorbell_id of the queue in
> diff --git a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c 
> b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
> index 3fad95199e0c..27adcea7b9a0 100644
> --- a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
> +++ b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
> @@ -26,6 +26,7 @@
>  #include "amdgpu_gfx.h"
>  #include "mes_userqueue.h"
>  #include "amdgpu_userq_fence.h"
> +#include "amdgpu_userq_internal.h"
>  #include "amdgpu_cwsr.h"
>  
>  #define AMDGPU_USERQ_PROC_CTX_SZ PAGE_SIZE
> @@ -238,34 +239,55 @@ int mes_userq_reset_queue(struct amdgpu_device *adev,
>                         unsigned int queue,
>                         unsigned int db)
>  {
> +     struct xarray *xa = &adev->userq_doorbell_xa;
>       struct amdgpu_usermode_queue *uq;
>       bool use_mmio = adev->gfx.mec.use_mmio_for_reset;
> -     unsigned long uq_id;
> -     int r;
> +     unsigned long flags;
> +     int r = 0;
>  
> -     xa_for_each(&adev->userq_doorbell_xa, uq_id, uq) {
> -             if (uq->queue_type == queue_type) {
> -                     if (uq == guilty_uq)
> -                             continue;
> -                     if (uq->doorbell_index == db) {
> -                             uq->state = AMDGPU_USERQ_STATE_HUNG;
> -                             if (use_mmio)
> -                                     r = amdgpu_mes_reset_queue_mmio(adev, 
> queue_type, 0, 1, pipe, queue, 0);
> -                             else
> -                                     r = amdgpu_mes_reset_user_queue(adev, 
> queue_type, db, 0);
> -                             if (r)
> -                                     return r;
> -                             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;
> -                     }
> -             }
> -     }
> -     return 0;
> +     /*
> +      * Resolve the doorbell directly to the affected queue instead of
> +      * scanning all user queues.
> +      */
> +     xa_lock_irqsave(xa, flags);
> +
> +     uq = xa_load(xa, db);
> +     if (uq)
> +             kref_get(&uq->refcount);
> +
> +     xa_unlock_irqrestore(xa, flags);
> +
> +     if (!uq)
> +             return 0;
> +
> +     /*
> +      * The guilty queue is handled separately by the caller.
> +      */
> +     if (uq == guilty_uq)
> +             goto out_put_queue;
> +
> +     if (uq->queue_type != queue_type)
> +             goto out_put_queue;
> +
> +     if (use_mmio)
> +             r = amdgpu_mes_reset_queue_mmio(adev, queue_type,
> +                                             0, 1, pipe, queue, 0);
> +     else
> +             r = amdgpu_mes_reset_user_queue(adev, queue_type, db, 0);
> +
> +     if (r)
> +             goto out_put_queue;
> +
> +     r = mes_userq_unmap(uq);
> +     if (r)
> +             goto out_put_queue;
> +
> +     amdgpu_userq_handle_hung_queue(adev, uq);
> +
> +out_put_queue:
> +     amdgpu_userq_put(uq);
> +
> +     return r;
>  }
>  
>  static int mes_userq_create_ctx_space(struct amdgpu_userq_mgr *uq_mgr,

Reply via email to