winsys/amdgpu: rework how SW reset status is generated and reported
authorMarek Olšák <marek.olsak@amd.com>
Mon, 7 Aug 2023 01:37:32 +0000 (21:37 -0400)
committerMarge Bot <emma+marge@anholt.net>
Thu, 17 Aug 2023 15:34:06 +0000 (15:34 +0000)
This adds a new helper amdgpu_ctx_set_sw_reset_status that sets the SW
status. The logic of which CS is reported as rejected is also changed
slightly, i.e. other contexts no longer affect the current context.

The helper will be exposed to radeonsi to allow reporting non-recoverable
allocation failures and skipped draws.

Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24732>

src/gallium/winsys/amdgpu/drm/amdgpu_cs.c
src/gallium/winsys/amdgpu/drm/amdgpu_cs.h
src/gallium/winsys/amdgpu/drm/amdgpu_winsys.h

index 082d8d2..77f9ee9 100644 (file)
@@ -285,7 +285,6 @@ static struct radeon_winsys_ctx *amdgpu_ctx_create(struct radeon_winsys *ws,
 
    ctx->ws = amdgpu_winsys(ws);
    ctx->refcount = 1;
-   ctx->initial_num_total_rejected_cs = ctx->ws->num_total_rejected_cs;
    ctx->allow_context_lost = allow_context_lost;
 
    r = amdgpu_cs_ctx_create2(ctx->ws->dev, amdgpu_priority, &ctx->ctx);
@@ -412,6 +411,33 @@ destroy_ctx:
    return r;
 }
 
+static void
+amdgpu_ctx_set_sw_reset_status(struct radeon_winsys_ctx *rwctx, enum pipe_reset_status status,
+                               const char *format, ...)
+{
+   struct amdgpu_ctx *ctx = (struct amdgpu_ctx*)rwctx;
+
+   /* Don't overwrite the last reset status. */
+   if (ctx->sw_status != PIPE_NO_RESET)
+      return;
+
+   ctx->sw_status = status;
+
+   if (!ctx->allow_context_lost) {
+      va_list args;
+
+      va_start(args, format);
+      vfprintf(stderr, format, args);
+      va_end(args);
+
+      /* Non-robust contexts are allowed to terminate the process. The only alternative is
+       * to skip command submission, which would look like a freeze because nothing is drawn,
+       * which looks like a hang without any reset.
+       */
+      abort();
+   }
+}
+
 static enum pipe_reset_status
 amdgpu_ctx_query_reset_status(struct radeon_winsys_ctx *rwctx, bool full_reset_only,
                               bool *needs_reset, bool *reset_completed)
@@ -428,8 +454,7 @@ amdgpu_ctx_query_reset_status(struct radeon_winsys_ctx *rwctx, bool full_reset_o
    if (ctx->ws->info.drm_minor >= 24) {
       uint64_t flags;
 
-      if (full_reset_only &&
-          ctx->initial_num_total_rejected_cs == ctx->ws->num_total_rejected_cs) {
+      if (full_reset_only && ctx->sw_status == PIPE_NO_RESET) {
          /* If the caller is only interested in full reset (= wants to ignore soft
           * recoveries), we can use the rejected cs count as a quick first check.
           */
@@ -490,12 +515,11 @@ amdgpu_ctx_query_reset_status(struct radeon_winsys_ctx *rwctx, bool full_reset_o
       }
    }
 
-   /* Return a failure due to a rejected command submission. */
-   if (ctx->ws->num_total_rejected_cs > ctx->initial_num_total_rejected_cs) {
+   /* Return a failure due to SW issues. */
+   if (ctx->sw_status != PIPE_NO_RESET) {
       if (needs_reset)
          *needs_reset = true;
-      return ctx->rejected_any_cs ? PIPE_GUILTY_CONTEXT_RESET :
-                                    PIPE_INNOCENT_CONTEXT_RESET;
+      return ctx->sw_status;
    }
    if (needs_reset)
       *needs_reset = false;
@@ -1693,7 +1717,7 @@ static void amdgpu_cs_submit_ib(void *job, void *gdata, int thread_index)
 
    assert(num_chunks <= ARRAY_SIZE(chunks));
 
-   if (unlikely(acs->ctx->rejected_any_cs)) {
+   if (unlikely(acs->ctx->sw_status != PIPE_NO_RESET)) {
       r = -ECANCELED;
    } else if (unlikely(noop)) {
       r = 0;
@@ -1737,20 +1761,9 @@ static void amdgpu_cs_submit_ib(void *job, void *gdata, int thread_index)
 
 cleanup:
    if (unlikely(r)) {
-      if (!acs->ctx->allow_context_lost) {
-         /* Non-robust contexts are allowed to terminate the process. The only alternative is
-          * to skip command submission, which would look like a freeze because nothing is drawn,
-          * which is not a useful state to be in under any circumstances.
-          */
-         fprintf(stderr, "amdgpu: The CS has been rejected (%i), but the context isn't robust.\n", r);
-         fprintf(stderr, "amdgpu: The process will be terminated.\n");
-         exit(1);
-      }
-
-      fprintf(stderr, "amdgpu: The CS has been rejected (%i). Recreate the context.\n", r);
-      if (!acs->ctx->rejected_any_cs)
-         ws->num_total_rejected_cs++;
-      acs->ctx->rejected_any_cs = true;
+      amdgpu_ctx_set_sw_reset_status((struct radeon_winsys_ctx*)acs->ctx,
+                                     PIPE_GUILTY_CONTEXT_RESET,
+                                     "amdgpu: The CS has been rejected (%i).\n", r);
    }
 
    /* If there was an error, signal the fence, because it won't be signalled
index 8babf49..6599cc4 100644 (file)
@@ -30,8 +30,8 @@ struct amdgpu_ctx {
     */
    bool allow_context_lost;
 
-   unsigned initial_num_total_rejected_cs;
-   bool rejected_any_cs;
+   /* Lost context status due to ioctl and allocation failures. */
+   enum pipe_reset_status sw_status;
 };
 
 struct amdgpu_cs_buffer {
index 35f5434..62b583a 100644 (file)
@@ -81,7 +81,6 @@ struct amdgpu_winsys {
    simple_mtx_t bo_fence_lock;
 
    int num_cs; /* The number of command streams created. */
-   unsigned num_total_rejected_cs;
    uint32_t surf_index_color;
    uint32_t surf_index_fmask;
    uint32_t next_bo_unique_id;