On Mon, Jul 13, 2026 at 12:34 PM Srinivasan Shanmugam
<[email protected]> 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 find the affected queue and notify matching
> EVENTFD subscribers.
>
> Move the queue reset handling into amdgpu_userq.c so the queue lookup
> and queue handling are performed in one place. This avoids scanning all
> queues to find a matching doorbell.
>
> 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.
>
> Cc: Alex Deucher <[email protected]>
> Suggested-by: Christian König <[email protected]>
> Signed-off-by: Srinivasan Shanmugam <[email protected]>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c  | 33 ++++++++++
>  drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h  |  3 +-
>  drivers/gpu/drm/amd/amdgpu/mes_userqueue.c | 73 ++++++++++++++--------
>  3 files changed, 83 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> index ab3ef3a9f655..5bf231d7a630 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> @@ -242,7 +242,40 @@ void amdgpu_userq_process_fence_irq(struct amdgpu_device 
> *adev, u32 doorbell)
>         xa_unlock_irqrestore(xa, flags);
>  }
>
> +/**
> + * amdgpu_userq_handle_hung_queue - handle a successfully reset hung queue
> + * @adev: AMDGPU device
> + * @queue: affected user queue
> + *
> + * Mark the queue as hung, notify matching QUEUE_RESET EVENTFD
> + * subscribers, force-complete its fences, and send the DRM wedged event.
> + *
> + * Return:
> + * true when the queue was handled, false for an invalid queue.
> + */
> +bool
> +amdgpu_userq_handle_hung_queue(struct amdgpu_device *adev,
> +                              struct amdgpu_usermode_queue *queue)
> +{
> +       struct amdgpu_eventfd_mgr *eventfd_mgr;
>
> +       if (!queue)
> +               return false;
> +
> +       queue->state = AMDGPU_USERQ_STATE_HUNG;
> +
> +       eventfd_mgr = amdgpu_userq_eventfd_mgr(queue->userq_mgr);
> +       amdgpu_eventfd_signal(eventfd_mgr,
> +                             DRM_AMDGPU_EVENT_TYPE_QUEUE_RESET,
> +                             queue);
> +
> +       amdgpu_userq_fence_driver_force_completion(queue);
> +
> +       drm_dev_wedged_event(adev_to_drm(adev),
> +                            DRM_WEDGE_RECOVERY_NONE, NULL);
> +
> +       return true;
> +}
>
>  int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
>                                    struct amdgpu_usermode_queue *queue,
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> index b69621311b80..187bfd66eb13 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> @@ -180,7 +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);
> -
> +bool 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
>   * CTXID0[9:0] on priv-fault (same encoding KFD uses via
> diff --git a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c 
> b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
> index 3fad95199e0c..4b546613c024 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,56 @@ int mes_userq_reset_queue(struct amdgpu_device *adev,

mes_userq_reset_queue() is only called for collateral damage on
compute queues.  You also need to handle this in
amdgpu_userq_hang_detect_work() for the original guilty queue.  I
think we also need this patch:
https://patchwork.freedesktop.org/patch/739898/?series=170347&rev=1

Alex

>                           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;
> +
> +       if (amdgpu_userq_handle_hung_queue(adev, uq))
> +               atomic_inc(&adev->gpu_reset_counter);
> +
> +out_put_queue:
> +       amdgpu_userq_put(uq);
> +
> +       return r;
>  }
>
>  static int mes_userq_create_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
> --
> 2.34.1
>

Reply via email to