AMD General

The corresponding Libdrm patch updated as: 
https://gitlab.freedesktop.org/mesa/libdrm/-/merge_requests/487, please help 
review the series patch together, thanks!

Regards,
      Prike

> -----Original Message-----
> From: Liang, Prike <[email protected]>
> Sent: Tuesday, September 22, 2026 3:59 PM
> To: [email protected]
> Cc: Deucher, Alexander <[email protected]>; Koenig, Christian
> <[email protected]>; Pelloux-Prayer, Pierre-Eric <Pierre-eric.Pelloux-
> [email protected]>; Liang, Prike <[email protected]>
> Subject: [PATCH v3 5/5] drm/amdgpu: track user queue guilt and report reset 
> status
>
> A hung user queue must not be replayed after reset because its context may be
> corrupted. Keep the guilty state on the queue and report it through the 
> sticky HUNG
> status. Skip guilty queues and queues whose VM generation has changed when
> mapping or restoring them.
>
> Signed-off-by: Prike Liang <[email protected]>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 30 ++++++++++++++++++++---
> drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h |  3 +++
>  include/uapi/drm/amdgpu_drm.h             | 11 ++++++---
>  3 files changed, 37 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> index 4ddd22af63c5..8ac63beca995 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> @@ -148,6 +148,8 @@ static void amdgpu_userq_hang_detect_work(struct
> work_struct *work)
>               }
>       }
>
> +     WRITE_ONCE(queue->guilty, true);
> +
>       if (amdgpu_userq_is_reset_type_supported(adev, queue->queue_type,
>
> AMDGPU_RESET_TYPE_PER_QUEUE)) {
>               int r;
> @@ -174,7 +176,7 @@ static void amdgpu_userq_hang_detect_work(struct
> work_struct *work)
>        * handler to another is illegal if you don't take extra precautions!
>        */
>       if (gpu_reset)
> -             amdgpu_userq_mgr_reset_work(&queue->userq_mgr->reset_work);
> +             amdgpu_userq_mgr_reset_work(&uq_mgr->reset_work);
>  }
>
>  /*
> @@ -338,6 +340,10 @@ static int amdgpu_userq_restore_helper(struct
> amdgpu_usermode_queue *queue)
>               adev->userq_funcs[queue->queue_type];
>       int r = 0;
>
> +     if (READ_ONCE(queue->guilty) ||
> +         queue->generation != amdgpu_vm_generation(adev, queue->vm))
> +             return 0;
> +
>       if (queue->state == AMDGPU_USERQ_STATE_PREEMPTED) {
>               trace_amdgpu_userq_state_start(queue);
>
> @@ -388,6 +394,10 @@ static int amdgpu_userq_map_helper(struct
> amdgpu_usermode_queue *queue)
>               adev->userq_funcs[queue->queue_type];
>       int r;
>
> +     if (READ_ONCE(queue->guilty) ||
> +         queue->generation != amdgpu_vm_generation(adev, queue->vm))
> +             return 0;
> +
>       if (queue->state == AMDGPU_USERQ_STATE_UNMAPPED) {
>               trace_amdgpu_userq_state_start(queue);
>
> @@ -692,6 +702,7 @@ amdgpu_userq_create(struct drm_file *filp, union
> drm_amdgpu_userq *args)
>       queue->queue_type = args->in.ip_type;
>       queue->vm = &fpriv->vm;
>       queue->priority = priority;
> +     queue->reset_counter = atomic_read(&adev->gpu_reset_counter);
>       queue->generation = amdgpu_vm_generation(adev, &fpriv->vm);
>       queue->xcp_id = (fpriv->xcp_id != AMDGPU_XCP_NO_PARTITION) ?
>                               fpriv->xcp_id : 0;
> @@ -831,14 +842,20 @@ amdgpu_userq_query_status(struct drm_file *filp, union
> drm_amdgpu_userq *args)
>       }
>
>       args->out_qs.flags = 0;
> -     if (queue->state == AMDGPU_USERQ_STATE_HUNG)
> +     if (queue->reset_counter != atomic_read(&adev->gpu_reset_counter))
> +             args->out_qs.flags |=
> AMDGPU_USERQ_QUERY_STATUS_FLAGS_RESET;
> +     if (queue->state == AMDGPU_USERQ_STATE_HUNG ||
> +         READ_ONCE(queue->guilty))
>               args->out_qs.flags |=
> AMDGPU_USERQ_QUERY_STATUS_FLAGS_HUNG;
>       if (queue->generation != amdgpu_vm_generation(adev, &fpriv->vm))
>               args->out_qs.flags |=
> AMDGPU_USERQ_QUERY_STATUS_FLAGS_VRAMLOST;
>       if (queue->state == AMDGPU_USERQ_STATE_INVALID_VA)
>               args->out_qs.flags |=
> AMDGPU_USERQ_QUERY_STATUS_FLAGS_INVALID_VA;
> -     amdgpu_userq_put(queue);
> +     if (amdgpu_in_reset(adev))
> +             args->out_qs.flags |=
> +AMDGPU_USERQ_QUERY_STATUS_FLAGS_RESET_IN_PROGRESS;
>       mutex_unlock(&uq_mgr->userq_mutex);
> +     /* The final put may destroy the queue and take userq_mutex. */
> +     amdgpu_userq_put(queue);
>
>       return 0;
>  }
> @@ -900,6 +917,7 @@ static int amdgpu_userq_input_args_validate(struct
> drm_device *dev,
>               }
>               break;
>       case AMDGPU_USERQ_OP_FREE:
> +     case AMDGPU_USERQ_OP_QUERY_STATUS:
>               if (args->in.ip_type ||
>                   args->in.doorbell_handle ||
>                   args->in.doorbell_offset ||
> @@ -1596,7 +1614,11 @@ int amdgpu_userq_post_reset(struct amdgpu_device
> *adev, bool vram_lost)
>       int ret = 0, r;
>
>       xa_for_each(&adev->userq_doorbell_xa, queue_id, queue) {
> -             if (queue->state == AMDGPU_USERQ_STATE_HUNG
> && !vram_lost) {
> +             if (vram_lost || READ_ONCE(queue->guilty) ||
> +                 queue->generation != amdgpu_vm_generation(adev, queue->vm))
> +                     continue;
> +
> +             if (queue->state == AMDGPU_USERQ_STATE_HUNG) {
>                       trace_amdgpu_userq_state_start(queue);
>
>                       userq_funcs = adev->userq_funcs[queue->queue_type];
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> index d1a2e2a45861..c2349115f404 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> @@ -51,6 +51,8 @@ struct amdgpu_userq_obj {  struct amdgpu_usermode_queue
> {
>       int                     queue_type;
>       enum amdgpu_userq_state state;
> +     /* Reset due to a hang; must not be re-mapped, userspace recreates. */
> +     bool                    guilty;
>       uint64_t                doorbell_handle;
>       uint64_t                doorbell_index;
>       u32                     doorbell_offset;
> @@ -79,6 +81,7 @@ struct amdgpu_usermode_queue {
>       struct dma_fence        *last_fence;
>       u32                     xcp_id;
>       int                     priority;
> +     unsigned int            reset_counter;
>       uint64_t                generation;
>       struct dentry           *debugfs_queue;
>
> diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h 
> index
> 2f81ec3265cd..7e928c4e8868 100644
> --- a/include/uapi/drm/amdgpu_drm.h
> +++ b/include/uapi/drm/amdgpu_drm.h
> @@ -360,18 +360,23 @@ union drm_amdgpu_ctx {  #define
> AMDGPU_USERQ_QUERY_STATUS_FLAGS_VRAMLOST (1 << 1)
>  /* the invalid userq VA unmapped */
>  #define AMDGPU_USERQ_QUERY_STATUS_FLAGS_INVALID_VA (1 << 2)
> +/* indicate a GPU reset occurred since the queue was created */ #define
> +AMDGPU_USERQ_QUERY_STATUS_FLAGS_RESET (1 << 3)
> +/* indicate that a GPU reset has not completed yet */ #define
> +AMDGPU_USERQ_QUERY_STATUS_FLAGS_RESET_IN_PROGRESS (1 << 4)
> +
>  /*
>   * This structure is a container to pass input configuration
>   * info for all supported userqueue related operations.
>   * For operation AMDGPU_USERQ_OP_CREATE: user is expected
>   *  to set all fields, excep the parameter 'queue_id'.
> - * For operation AMDGPU_USERQ_OP_FREE: the only input parameter expected
> - *  to be set is 'queue_id', eveything else is ignored.
> + * For operations AMDGPU_USERQ_OP_FREE and
> AMDGPU_USERQ_OP_QUERY_STATUS:
> + *  only 'op' and 'queue_id' should be set; all other fields must be zero.
>   */
>  struct drm_amdgpu_userq_in {
>       /** AMDGPU_USERQ_OP_* */
>       __u32   op;
> -     /** Queue id passed for operation USERQ_OP_FREE */
> +     /** Queue id passed for operations USERQ_OP_FREE and
> +USERQ_OP_QUERY_STATUS */
>       __u32   queue_id;
>       /** the target GPU engine to execute workload (AMDGPU_HW_IP_*) */
>       __u32   ip_type;
> --
> 2.34.1

Reply via email to