On 9/11/26 10:22, Prike Liang wrote:
> When a queue encounters a reset error and fallback to device reset,
> mark both the queue and its owning process as guilty so that userspace
> is notified that the offending queue is no longer usable and should
> recreate the context before resubmitting work.
> 
> Signed-off-by: Prike Liang <[email protected]>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c   |  4 +++-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 24 ++++++++++++++++++++---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h |  5 ++++-
>  3 files changed, 28 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
> index b15ed4a534f1..038d18faf344 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
> @@ -589,7 +589,9 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev,
>       if (ctx->generation != amdgpu_vm_generation(adev, &fpriv->vm))
>               out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_VRAMLOST;
>  
> -     if (amdgpu_ctx_guilty(ctx))
> +     if (amdgpu_ctx_guilty(ctx) ||
> +        ((out->state.flags & AMDGPU_CTX_QUERY2_FLAGS_RESET) &&
> +        fpriv->userq_mgr.guilty))
>               out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_GUILTY;
>  
>       if (amdgpu_in_reset(adev))
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> index 6c92575213c1..7098d550c0ee 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> @@ -173,8 +173,12 @@ static void amdgpu_userq_hang_detect_work(struct 
> work_struct *work)
>        * Don't schedule the work here! Scheduling or queue work from one reset
>        * handler to another is illegal if you don't take extra precautions!
>        */
> -     if (gpu_reset)
> +     if (gpu_reset) {
> +             /* Block re-map until userspace recreates the queue. */
> +             queue->guilty = true;
> +             queue->userq_mgr->guilty = true;

Clear NAK to having a global guilty flag in the userq_mgr. Each queue should be 
handled completely separated.

The only case where that makes sense would be gang submitted queues, but we 
haven't implemented those.

Regards,
Christian.

>               amdgpu_userq_mgr_reset_work(&queue->userq_mgr->reset_work);
> +     }
>  }
>  
>  /*
> @@ -389,8 +393,17 @@ static int amdgpu_userq_map_helper(struct 
> amdgpu_usermode_queue *queue)
>       int r;
>  
>       if (queue->state == AMDGPU_USERQ_STATE_UNMAPPED) {
> -             trace_amdgpu_userq_state_start(queue);
>  
> +             if (queue->guilty) {
> +                     /*
> +                      * A queue that was reset for hanging must not be
> +                      * re-mapped: replaying its command stream faults
> +                      * again. Leave it unmapped for userspace to recreate.
> +                      */
> +                     return 0;
> +             }
> +
> +             trace_amdgpu_userq_state_start(queue);
>               r = userq_funcs->map(queue);
>               if (r) {
>                       trace_amdgpu_userq_state_changed(queue, 
> AMDGPU_USERQ_STATE_HUNG);
> @@ -833,7 +846,8 @@ 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)
>               args->out_qs.flags |= AMDGPU_USERQ_QUERY_STATUS_FLAGS_HUNG;
> -     if (queue->generation != amdgpu_vm_generation(adev, &fpriv->vm))
> +     if (queue->generation != amdgpu_vm_generation(adev, &fpriv->vm) ||
> +        fpriv->userq_mgr.guilty)
>               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;
> @@ -1594,6 +1608,10 @@ 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) {
> +              /* Guilty queues are not restored; userspace recreates them. */
> +             if (queue->guilty)
> +                     continue;
> +
>               if (queue->state == AMDGPU_USERQ_STATE_HUNG && !vram_lost) {
>                       trace_amdgpu_userq_state_start(queue);
>  
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> index 40228c60a1ea..f2eca744a3c5 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;
> @@ -132,7 +134,8 @@ struct amdgpu_userq_mgr {
>       struct drm_file                 *file;
>       struct mutex                    proc_ctx_lock;
>       struct amdgpu_userq_obj         proc_ctx_obj;
> -
> +     /* Set when any queue owned by this process is reset guilty */
> +     bool                            guilty;
>       bool                            proc_ctx_allocated;
>       uint32_t                        proc_ctx_array_index;
>       /**

Reply via email to