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