radeonsi: stop reporting reset to app once gpu recovery is done
authorPierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Fri, 7 Apr 2023 07:48:02 +0000 (09:48 +0200)
committerMarge Bot <emma+marge@anholt.net>
Thu, 27 Apr 2023 12:06:08 +0000 (12:06 +0000)
This way apps know they can recreate their contexts when
the status go back to NO_ERROR.

This depends on new UAPI in the kernel; for older kernel, radeonsi
will stop reporting a reset after 3 seconds. Apps will be able to
create new contexts but they'll have to handle not being able to
submit tasks.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/7460
Reviewed-by: André Almeida <andrealmeid@igalia.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22290>

src/gallium/drivers/r600/r600_pipe_common.c
src/gallium/drivers/radeonsi/si_gfx_cs.c
src/gallium/drivers/radeonsi/si_pipe.c
src/gallium/drivers/radeonsi/si_pipe.h
src/gallium/include/winsys/radeon_winsys.h
src/gallium/winsys/amdgpu/drm/amdgpu_cs.c
src/gallium/winsys/radeon/drm/radeon_drm_cs.c

index 17a5f15..ffd2efd 100644 (file)
@@ -489,7 +489,7 @@ static enum pipe_reset_status r600_get_reset_status(struct pipe_context *ctx)
 {
        struct r600_common_context *rctx = (struct r600_common_context *)ctx;
 
-       return rctx->ws->ctx_query_reset_status(rctx->ctx, false, NULL);
+       return rctx->ws->ctx_query_reset_status(rctx->ctx, false, NULL, NULL);
 }
 
 static void r600_set_debug_callback(struct pipe_context *ctx,
index be2d353..698d984 100644 (file)
@@ -80,7 +80,7 @@ void si_flush_gfx_cs(struct si_context *ctx, unsigned flags, struct pipe_fence_h
     * while si_get_reset_status can't. */
    if (!(ctx->context_flags & SI_CONTEXT_FLAG_AUX) &&
        ctx->device_reset_callback.reset) {
-      enum pipe_reset_status status = ctx->ws->ctx_query_reset_status(ctx->ctx, true, NULL);
+      enum pipe_reset_status status = ctx->ws->ctx_query_reset_status(ctx->ctx, true, NULL, NULL);
       if (status != PIPE_NO_RESET)
          ctx->device_reset_callback.reset(ctx->device_reset_callback.data, status);
    }
index ab42506..afd13ff 100644 (file)
@@ -385,13 +385,20 @@ static enum pipe_reset_status si_get_reset_status(struct pipe_context *ctx)
    if (sctx->context_flags & SI_CONTEXT_FLAG_AUX)
       return PIPE_NO_RESET;
 
-   bool needs_reset;
-   enum pipe_reset_status status = sctx->ws->ctx_query_reset_status(sctx->ctx, false, &needs_reset);
+   bool needs_reset, reset_completed;
+   enum pipe_reset_status status = sctx->ws->ctx_query_reset_status(sctx->ctx, false,
+                                                                    &needs_reset, &reset_completed);
 
-   if (status != PIPE_NO_RESET && needs_reset && !(sctx->context_flags & SI_CONTEXT_FLAG_AUX)) {
-      /* Call the gallium frontend to set a no-op API dispatch. */
-      if (sctx->device_reset_callback.reset) {
-         sctx->device_reset_callback.reset(sctx->device_reset_callback.data, status);
+   if (status != PIPE_NO_RESET) {
+      if (sctx->has_reset_been_notified && reset_completed)
+         return PIPE_NO_RESET;
+
+      sctx->has_reset_been_notified = true;
+
+      if (!(sctx->context_flags & SI_CONTEXT_FLAG_AUX)) {
+         /* Call the gallium frontend to set a no-op API dispatch. */
+         if (needs_reset && sctx->device_reset_callback.reset)
+            sctx->device_reset_callback.reset(sctx->device_reset_callback.data, status);
       }
    }
    return status;
@@ -818,7 +825,7 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen, unsign
       struct si_context *saux = si_get_aux_context(sscreen);
 
       enum pipe_reset_status status = sctx->ws->ctx_query_reset_status(
-         saux->ctx, true, NULL);
+         saux->ctx, true, NULL, NULL);
       if (status != PIPE_NO_RESET) {
          /* We lost the aux_context, create a new one */
          struct u_log_context *aux_log = (saux)->log;
index c9ff072..29bc59f 100644 (file)
@@ -1218,6 +1218,7 @@ struct si_context {
    bool dpbb_force_off_profile_ps;
    bool vs_writes_viewport_index;
    bool vs_disables_clipping_viewport;
+   bool has_reset_been_notified;
 
    /* Precomputed IA_MULTI_VGT_PARAM */
    union si_vgt_param_key ia_multi_vgt_param_key;
index 46b9c96..6e9b01f 100644 (file)
@@ -527,7 +527,7 @@ struct radeon_winsys {
     */
    enum pipe_reset_status (*ctx_query_reset_status)(struct radeon_winsys_ctx *ctx,
                                                     bool full_reset_only,
-                                                    bool *needs_reset);
+                                                    bool *needs_reset, bool *reset_completed);
 
    /**
     * Create a command stream.
index b7e1b9c..24a2bb0 100644 (file)
@@ -349,13 +349,15 @@ static void amdgpu_ctx_destroy(struct radeon_winsys_ctx *rwctx)
 
 static enum pipe_reset_status
 amdgpu_ctx_query_reset_status(struct radeon_winsys_ctx *rwctx, bool full_reset_only,
-                              bool *needs_reset)
+                              bool *needs_reset, bool *reset_completed)
 {
    struct amdgpu_ctx *ctx = (struct amdgpu_ctx*)rwctx;
    int r;
 
    if (needs_reset)
       *needs_reset = false;
+   if (reset_completed)
+      *reset_completed = false;
 
    /* Return a failure due to a GPU hang. */
    if (ctx->ws->info.drm_minor >= 24) {
@@ -376,6 +378,18 @@ amdgpu_ctx_query_reset_status(struct radeon_winsys_ctx *rwctx, bool full_reset_o
       }
 
       if (flags & AMDGPU_CTX_QUERY2_FLAGS_RESET) {
+         if (reset_completed) {
+            /* The ARB_robustness spec says:
+             *
+             *    If a reset status other than NO_ERROR is returned and subsequent
+             *    calls return NO_ERROR, the context reset was encountered and
+             *    completed. If a reset status is repeatedly returned, the context may
+             *    be in the process of resetting.
+             *
+             */
+            if (!(flags & AMDGPU_CTX_QUERY2_FLAGS_RESET_IN_PROGRESS))
+               *reset_completed = true;
+         }
          if (needs_reset)
                *needs_reset = flags & AMDGPU_CTX_QUERY2_FLAGS_VRAMLOST;
          if (flags & AMDGPU_CTX_QUERY2_FLAGS_GUILTY)
index 45342a6..69ce977 100644 (file)
@@ -89,7 +89,7 @@ static void radeon_drm_ctx_destroy(struct radeon_winsys_ctx *ctx)
 
 static enum pipe_reset_status
 radeon_drm_ctx_query_reset_status(struct radeon_winsys_ctx *rctx, bool full_reset_only,
-                                  bool *needs_reset)
+                                  bool *needs_reset, bool *reset_completed)
 {
    struct radeon_ctx *ctx = (struct radeon_ctx*)rctx;
 
@@ -98,11 +98,15 @@ radeon_drm_ctx_query_reset_status(struct radeon_winsys_ctx *rctx, bool full_rese
    if (ctx->gpu_reset_counter == latest) {
       if (needs_reset)
          *needs_reset = false;
+      if (reset_completed)
+         *reset_completed = false;
       return PIPE_NO_RESET;
    }
 
    if (needs_reset)
       *needs_reset = true;
+   if (reset_completed)
+      *reset_completed = true;
 
    ctx->gpu_reset_counter = latest;
    return PIPE_UNKNOWN_CONTEXT_RESET;