Reviewed-by: Marek Olšák <mar...@gmail.com>

Marek

On Thu, Apr 25, 2013 at 1:18 AM,  <j.gli...@gmail.com> wrote:
> From: Jerome Glisse <jgli...@redhat.com>
>
> This move the tracing timeout and printing into winsys and add
> an debug environement variable for it (R600_DEBUG=trace_cs).
>
> Lot of file touched because of winsys API changes.
>
> v2: Do not write lockup file if ib uniq id does not match last one
>
> Signed-off-by: Jerome Glisse <jgli...@redhat.com>
> ---
>  src/gallium/drivers/r300/r300_context.c            |  2 +-
>  src/gallium/drivers/r300/r300_flush.c              |  6 ++--
>  src/gallium/drivers/r600/evergreen_compute.c       |  2 +-
>  src/gallium/drivers/r600/r600_hw_context.c         | 36 
> +---------------------
>  src/gallium/drivers/r600/r600_pipe.c               | 17 +++++-----
>  src/gallium/drivers/r600/r600_pipe.h               | 11 ++-----
>  src/gallium/drivers/r600/r600_state_common.c       |  4 ---
>  src/gallium/drivers/radeon/radeon_uvd.c            |  4 +--
>  src/gallium/drivers/radeonsi/r600_hw_context.c     |  2 +-
>  src/gallium/drivers/radeonsi/radeonsi_compute.c    |  2 +-
>  src/gallium/drivers/radeonsi/radeonsi_pipe.c       |  2 +-
>  src/gallium/winsys/radeon/drm/radeon_drm_cs.c      | 19 +++++++-----
>  src/gallium/winsys/radeon/drm/radeon_drm_cs.h      | 11 +++----
>  src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c | 30 +++++++++++-------
>  src/gallium/winsys/radeon/drm/radeon_drm_winsys.c  |  2 +-
>  src/gallium/winsys/radeon/drm/radeon_winsys.h      | 13 +++++---
>  16 files changed, 68 insertions(+), 95 deletions(-)
>
> diff --git a/src/gallium/drivers/r300/r300_context.c 
> b/src/gallium/drivers/r300/r300_context.c
> index 340a7f0..ba1859b 100644
> --- a/src/gallium/drivers/r300/r300_context.c
> +++ b/src/gallium/drivers/r300/r300_context.c
> @@ -379,7 +379,7 @@ struct pipe_context* r300_create_context(struct 
> pipe_screen* screen,
>                       sizeof(struct pipe_transfer), 64,
>                       UTIL_SLAB_SINGLETHREADED);
>
> -    r300->cs = rws->cs_create(rws, RING_GFX);
> +    r300->cs = rws->cs_create(rws, RING_GFX, NULL);
>      if (r300->cs == NULL)
>          goto fail;
>
> diff --git a/src/gallium/drivers/r300/r300_flush.c 
> b/src/gallium/drivers/r300/r300_flush.c
> index 10c4a30..709fe52 100644
> --- a/src/gallium/drivers/r300/r300_flush.c
> +++ b/src/gallium/drivers/r300/r300_flush.c
> @@ -52,7 +52,7 @@ static void r300_flush_and_cleanup(struct r300_context 
> *r300, unsigned flags)
>      }
>
>      r300->flush_counter++;
> -    r300->rws->cs_flush(r300->cs, flags);
> +    r300->rws->cs_flush(r300->cs, flags, 0);
>      r300->dirty_hw = 0;
>
>      /* New kitchen sink, baby. */
> @@ -100,11 +100,11 @@ void r300_flush(struct pipe_context *pipe,
>               * and we cannot emit an empty CS. Let's write to some reg. */
>              CS_LOCALS(r300);
>              OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0);
> -            r300->rws->cs_flush(r300->cs, flags);
> +            r300->rws->cs_flush(r300->cs, flags, 0);
>          } else {
>              /* Even if hw is not dirty, we should at least reset the CS in 
> case
>               * the space checking failed for the first draw operation. */
> -            r300->rws->cs_flush(r300->cs, flags);
> +            r300->rws->cs_flush(r300->cs, flags, 0);
>          }
>      }
>
> diff --git a/src/gallium/drivers/r600/evergreen_compute.c 
> b/src/gallium/drivers/r600/evergreen_compute.c
> index 189ffac..9393bbe 100644
> --- a/src/gallium/drivers/r600/evergreen_compute.c
> +++ b/src/gallium/drivers/r600/evergreen_compute.c
> @@ -426,7 +426,7 @@ static void compute_emit_cs(struct r600_context *ctx, 
> const uint *block_layout,
>                 flush_flags |= RADEON_FLUSH_KEEP_TILING_FLAGS;
>         }
>
> -       ctx->ws->cs_flush(ctx->rings.gfx.cs, flush_flags);
> +       ctx->ws->cs_flush(ctx->rings.gfx.cs, flush_flags, 
> ctx->screen->cs_count++);
>
>         ctx->flags = 0;
>
> diff --git a/src/gallium/drivers/r600/r600_hw_context.c 
> b/src/gallium/drivers/r600/r600_hw_context.c
> index b4fb3bf..3abce1e 100644
> --- a/src/gallium/drivers/r600/r600_hw_context.c
> +++ b/src/gallium/drivers/r600/r600_hw_context.c
> @@ -137,21 +137,17 @@ void r600_need_cs_space(struct r600_context *ctx, 
> unsigned num_dw,
>                 for (i = 0; i < R600_NUM_ATOMS; i++) {
>                         if (ctx->atoms[i] && ctx->atoms[i]->dirty) {
>                                 num_dw += ctx->atoms[i]->num_dw;
> -#if R600_TRACE_CS
>                                 if (ctx->screen->trace_bo) {
>                                         num_dw += R600_TRACE_CS_DWORDS;
>                                 }
> -#endif
>                         }
>                 }
>
>                 /* The upper-bound of how much space a draw command would 
> take. */
>                 num_dw += R600_MAX_FLUSH_CS_DWORDS + R600_MAX_DRAW_CS_DWORDS;
> -#if R600_TRACE_CS
>                 if (ctx->screen->trace_bo) {
>                         num_dw += R600_TRACE_CS_DWORDS;
>                 }
> -#endif
>         }
>
>         /* Count in queries_suspend. */
> @@ -339,37 +335,7 @@ void r600_context_flush(struct r600_context *ctx, 
> unsigned flags)
>         }
>
>         /* Flush the CS. */
> -#if R600_TRACE_CS
> -       if (ctx->screen->trace_bo) {
> -               struct r600_screen *rscreen = ctx->screen;
> -               unsigned i;
> -
> -               for (i = 0; i < cs->cdw; i++) {
> -                       fprintf(stderr, "[%4d] [%5d] 0x%08x\n", 
> rscreen->cs_count, i, cs->buf[i]);
> -               }
> -               rscreen->cs_count++;
> -       }
> -#endif
> -       ctx->ws->cs_flush(ctx->rings.gfx.cs, flags);
> -#if R600_TRACE_CS
> -       if (ctx->screen->trace_bo) {
> -               struct r600_screen *rscreen = ctx->screen;
> -               unsigned i;
> -
> -               for (i = 0; i < 10; i++) {
> -                       usleep(5);
> -                       if (!ctx->ws->buffer_is_busy(rscreen->trace_bo->buf, 
> RADEON_USAGE_READWRITE)) {
> -                               break;
> -                       }
> -               }
> -               if (i == 10) {
> -                       fprintf(stderr, "timeout on cs lockup likely happen 
> at cs %d dw %d\n",
> -                               rscreen->trace_ptr[1], rscreen->trace_ptr[0]);
> -               } else {
> -                       fprintf(stderr, "cs %d executed in %dms\n", 
> rscreen->trace_ptr[1], i * 5);
> -               }
> -       }
> -#endif
> +       ctx->ws->cs_flush(ctx->rings.gfx.cs, flags, ctx->screen->cs_count++);
>  }
>
>  void r600_begin_new_cs(struct r600_context *ctx)
> diff --git a/src/gallium/drivers/r600/r600_pipe.c 
> b/src/gallium/drivers/r600/r600_pipe.c
> index 4948ddd..541265d 100644
> --- a/src/gallium/drivers/r600/r600_pipe.c
> +++ b/src/gallium/drivers/r600/r600_pipe.c
> @@ -45,6 +45,7 @@ static const struct debug_named_value debug_options[] = {
>         { "texdepth", DBG_TEX_DEPTH, "Print texture depth info" },
>         { "compute", DBG_COMPUTE, "Print compute info" },
>         { "vm", DBG_VM, "Print virtual addresses when creating resources" },
> +       { "trace_cs", DBG_TRACE_CS, "Trace cs and write rlockup_<csid>.c file 
> with faulty cs" },
>
>         /* shaders */
>         { "fs", DBG_FS, "Print fetch shaders" },
> @@ -212,7 +213,7 @@ static void r600_flush_dma_ring(void *ctx, unsigned flags)
>         }
>
>         rctx->rings.dma.flushing = true;
> -       rctx->ws->cs_flush(cs, flags);
> +       rctx->ws->cs_flush(cs, flags, 0);
>         rctx->rings.dma.flushing = false;
>  }
>
> @@ -430,14 +431,18 @@ static struct pipe_context *r600_create_context(struct 
> pipe_screen *screen, void
>                 goto fail;
>         }
>
> -       rctx->rings.gfx.cs = rctx->ws->cs_create(rctx->ws, RING_GFX);
> +       if (rscreen->trace_bo) {
> +               rctx->rings.gfx.cs = rctx->ws->cs_create(rctx->ws, RING_GFX, 
> rscreen->trace_bo->cs_buf);
> +       } else {
> +               rctx->rings.gfx.cs = rctx->ws->cs_create(rctx->ws, RING_GFX, 
> NULL);
> +       }
>         rctx->rings.gfx.flush = r600_flush_gfx_ring;
>         rctx->ws->cs_set_flush_callback(rctx->rings.gfx.cs, 
> r600_flush_from_winsys, rctx);
>         rctx->rings.gfx.flushing = false;
>
>         rctx->rings.dma.cs = NULL;
>         if (rscreen->info.r600_has_dma && !(rscreen->debug_flags & 
> DBG_NO_ASYNC_DMA)) {
> -               rctx->rings.dma.cs = rctx->ws->cs_create(rctx->ws, RING_DMA);
> +               rctx->rings.dma.cs = rctx->ws->cs_create(rctx->ws, RING_DMA, 
> NULL);
>                 rctx->rings.dma.flush = r600_flush_dma_ring;
>                 rctx->ws->cs_set_flush_callback(rctx->rings.dma.cs, 
> r600_flush_dma_from_winsys, rctx);
>                 rctx->rings.dma.flushing = false;
> @@ -955,12 +960,10 @@ static void r600_destroy_screen(struct pipe_screen* 
> pscreen)
>                 rscreen->ws->buffer_unmap(rscreen->fences.bo->cs_buf);
>                 pipe_resource_reference((struct 
> pipe_resource**)&rscreen->fences.bo, NULL);
>         }
> -#if R600_TRACE_CS
>         if (rscreen->trace_bo) {
>                 rscreen->ws->buffer_unmap(rscreen->trace_bo->cs_buf);
>                 pipe_resource_reference((struct 
> pipe_resource**)&rscreen->trace_bo, NULL);
>         }
> -#endif
>         pipe_mutex_destroy(rscreen->fences.mutex);
>
>         rscreen->ws->destroy(rscreen->ws);
> @@ -1305,9 +1308,8 @@ struct pipe_screen *r600_screen_create(struct 
> radeon_winsys *ws)
>
>         rscreen->global_pool = compute_memory_pool_new(rscreen);
>
> -#if R600_TRACE_CS
>         rscreen->cs_count = 0;
> -       if (rscreen->info.drm_minor >= 28) {
> +       if (rscreen->info.drm_minor >= 28 && (rscreen->debug_flags & 
> DBG_TRACE_CS)) {
>                 rscreen->trace_bo = (struct 
> r600_resource*)pipe_buffer_create(&rscreen->screen,
>                                                                               
>   PIPE_BIND_CUSTOM,
>                                                                               
>   PIPE_USAGE_STAGING,
> @@ -1317,7 +1319,6 @@ struct pipe_screen *r600_screen_create(struct 
> radeon_winsys *ws)
>                                                                         
> PIPE_TRANSFER_UNSYNCHRONIZED);
>                 }
>         }
> -#endif
>
>         return &rscreen->screen;
>  }
> diff --git a/src/gallium/drivers/r600/r600_pipe.h 
> b/src/gallium/drivers/r600/r600_pipe.h
> index 4a692e7..5fa3f56 100644
> --- a/src/gallium/drivers/r600/r600_pipe.h
> +++ b/src/gallium/drivers/r600/r600_pipe.h
> @@ -37,8 +37,6 @@
>
>  #define R600_NUM_ATOMS 40
>
> -#define R600_TRACE_CS 0
> -
>  /* the number of CS dwords for flushing and drawing */
>  #define R600_MAX_FLUSH_CS_DWORDS       16
>  #define R600_MAX_DRAW_CS_DWORDS                34
> @@ -245,7 +243,8 @@ typedef boolean (*r600g_dma_blit_t)(struct pipe_context 
> *ctx,
>  /* logging */
>  #define DBG_TEX_DEPTH          (1 << 0)
>  #define DBG_COMPUTE            (1 << 1)
> -#define DBG_VM                  (1 << 2)
> +#define DBG_VM                 (1 << 2)
> +#define DBG_TRACE_CS           (1 << 3)
>  /* shaders */
>  #define DBG_FS                 (1 << 8)
>  #define DBG_VS                 (1 << 9)
> @@ -284,11 +283,9 @@ struct r600_screen {
>          * XXX: Not sure if this is the best place for global_pool.  Also,
>          * it's not thread safe, so it won't work with multiple contexts. */
>         struct compute_memory_pool *global_pool;
> -#if R600_TRACE_CS
>         struct r600_resource            *trace_bo;
>         uint32_t                        *trace_ptr;
>         unsigned                        cs_count;
> -#endif
>         r600g_dma_blit_t                dma_blit;
>  };
>
> @@ -649,19 +646,15 @@ static INLINE void r600_emit_command_buffer(struct 
> radeon_winsys_cs *cs,
>         cs->cdw += cb->num_dw;
>  }
>
> -#if R600_TRACE_CS
>  void r600_trace_emit(struct r600_context *rctx);
> -#endif
>
>  static INLINE void r600_emit_atom(struct r600_context *rctx, struct 
> r600_atom *atom)
>  {
>         atom->emit(rctx, atom);
>         atom->dirty = false;
> -#if R600_TRACE_CS
>         if (rctx->screen->trace_bo) {
>                 r600_trace_emit(rctx);
>         }
> -#endif
>  }
>
>  static INLINE void r600_set_cso_state(struct r600_cso_state *state, void 
> *cso)
> diff --git a/src/gallium/drivers/r600/r600_state_common.c 
> b/src/gallium/drivers/r600/r600_state_common.c
> index 8190873..87a2e2e 100644
> --- a/src/gallium/drivers/r600/r600_state_common.c
> +++ b/src/gallium/drivers/r600/r600_state_common.c
> @@ -1488,11 +1488,9 @@ static void r600_draw_vbo(struct pipe_context *ctx, 
> const struct pipe_draw_info
>                                         (info.count_from_stream_output ? 
> S_0287F0_USE_OPAQUE(1) : 0);
>         }
>
> -#if R600_TRACE_CS
>         if (rctx->screen->trace_bo) {
>                 r600_trace_emit(rctx);
>         }
> -#endif
>
>         /* Set the depth buffer as dirty. */
>         if (rctx->framebuffer.state.zsbuf) {
> @@ -1764,7 +1762,6 @@ void r600_init_common_state_functions(struct 
> r600_context *rctx)
>         rctx->context.draw_vbo = r600_draw_vbo;
>  }
>
> -#if R600_TRACE_CS
>  void r600_trace_emit(struct r600_context *rctx)
>  {
>         struct r600_screen *rscreen = rctx->screen;
> @@ -1782,4 +1779,3 @@ void r600_trace_emit(struct r600_context *rctx)
>         r600_write_value(cs, PKT3(PKT3_NOP, 0, 0));
>         r600_write_value(cs, reloc);
>  }
> -#endif
> diff --git a/src/gallium/drivers/radeon/radeon_uvd.c 
> b/src/gallium/drivers/radeon/radeon_uvd.c
> index dae7880..dfd1d9f 100644
> --- a/src/gallium/drivers/radeon/radeon_uvd.c
> +++ b/src/gallium/drivers/radeon/radeon_uvd.c
> @@ -109,7 +109,7 @@ static void flush(struct ruvd_decoder *dec)
>         while(dec->cs->cdw % 16)
>                 pm4[dec->cs->cdw++] = RUVD_PKT2();
>
> -       dec->ws->cs_flush(dec->cs, 0);
> +       dec->ws->cs_flush(dec->cs, 0, 0);
>  }
>
>  /* add a new set register command to the IB */
> @@ -859,7 +859,7 @@ struct pipe_video_decoder *ruvd_create_decoder(struct 
> pipe_context *context,
>         dec->set_dtb = set_dtb;
>         dec->stream_handle = alloc_stream_handle();
>         dec->ws = ws;
> -       dec->cs = ws->cs_create(ws, RING_UVD);
> +       dec->cs = ws->cs_create(ws, RING_UVD, NULL);
>         if (!dec->cs) {
>                 RUVD_ERR("Can't get command submission context.\n");
>                 goto error;
> diff --git a/src/gallium/drivers/radeonsi/r600_hw_context.c 
> b/src/gallium/drivers/radeonsi/r600_hw_context.c
> index 0975a1f..f3f07a3 100644
> --- a/src/gallium/drivers/radeonsi/r600_hw_context.c
> +++ b/src/gallium/drivers/radeonsi/r600_hw_context.c
> @@ -225,7 +225,7 @@ void si_context_flush(struct r600_context *ctx, unsigned 
> flags)
>  #endif
>
>         /* Flush the CS. */
> -       ctx->ws->cs_flush(ctx->cs, flags);
> +       ctx->ws->cs_flush(ctx->cs, flags, 0);
>
>  #if R600_TRACE_CS
>         if (ctx->screen->trace_bo) {
> diff --git a/src/gallium/drivers/radeonsi/radeonsi_compute.c 
> b/src/gallium/drivers/radeonsi/radeonsi_compute.c
> index 67bc14e..e67d127 100644
> --- a/src/gallium/drivers/radeonsi/radeonsi_compute.c
> +++ b/src/gallium/drivers/radeonsi/radeonsi_compute.c
> @@ -200,7 +200,7 @@ static void radeonsi_launch_grid(
>         }
>  #endif
>
> -       rctx->ws->cs_flush(rctx->cs, RADEON_FLUSH_COMPUTE);
> +       rctx->ws->cs_flush(rctx->cs, RADEON_FLUSH_COMPUTE, 0);
>         rctx->ws->buffer_wait(program->shader.bo->buf, 0);
>
>         FREE(pm4);
> diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.c 
> b/src/gallium/drivers/radeonsi/radeonsi_pipe.c
> index 4e97f51..8a072fd 100644
> --- a/src/gallium/drivers/radeonsi/radeonsi_pipe.c
> +++ b/src/gallium/drivers/radeonsi/radeonsi_pipe.c
> @@ -233,7 +233,7 @@ static struct pipe_context *r600_create_context(struct 
> pipe_screen *screen, void
>         case TAHITI:
>                 si_init_state_functions(rctx);
>                 LIST_INITHEAD(&rctx->active_query_list);
> -               rctx->cs = rctx->ws->cs_create(rctx->ws, RING_GFX);
> +               rctx->cs = rctx->ws->cs_create(rctx->ws, RING_GFX, NULL);
>                 rctx->max_db = 8;
>                 si_init_config(rctx);
>                 break;
> diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c 
> b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
> index 720e086..ea0c99d 100644
> --- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
> +++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
> @@ -167,7 +167,9 @@ static void radeon_destroy_cs_context(struct 
> radeon_cs_context *csc)
>  }
>
>
> -static struct radeon_winsys_cs *radeon_drm_cs_create(struct radeon_winsys 
> *rws, enum ring_type ring_type)
> +static struct radeon_winsys_cs *radeon_drm_cs_create(struct radeon_winsys 
> *rws,
> +                                                     enum ring_type 
> ring_type,
> +                                                     struct 
> radeon_winsys_cs_handle *trace_buf)
>  {
>      struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
>      struct radeon_drm_cs *cs;
> @@ -179,6 +181,7 @@ static struct radeon_winsys_cs 
> *radeon_drm_cs_create(struct radeon_winsys *rws,
>      pipe_semaphore_init(&cs->flush_completed, 0);
>
>      cs->ws = ws;
> +    cs->trace_buf = (struct radeon_bo*)trace_buf;
>
>      if (!radeon_init_cs_context(&cs->csc1, cs->ws)) {
>          FREE(cs);
> @@ -413,7 +416,7 @@ static void radeon_drm_cs_write_reloc(struct 
> radeon_winsys_cs *rcs,
>      OUT_CS(&cs->base, index * RELOC_DWORDS);
>  }
>
> -void radeon_drm_cs_emit_ioctl_oneshot(struct radeon_cs_context *csc)
> +void radeon_drm_cs_emit_ioctl_oneshot(struct radeon_drm_cs *cs, struct 
> radeon_cs_context *csc)
>  {
>      unsigned i;
>
> @@ -432,9 +435,9 @@ void radeon_drm_cs_emit_ioctl_oneshot(struct 
> radeon_cs_context *csc)
>          }
>      }
>
> -#if RADEON_CS_DUMP_ON_LOCKUP
> -    radeon_dump_cs_on_lockup(csc);
> -#endif
> +    if (cs->trace_buf) {
> +        radeon_dump_cs_on_lockup(cs, csc);
> +    }
>
>      for (i = 0; i < csc->crelocs; i++)
>          p_atomic_dec(&csc->relocs_bo[i]->num_active_ioctls);
> @@ -458,7 +461,7 @@ void radeon_drm_cs_sync_flush(struct radeon_winsys_cs 
> *rcs)
>
>  DEBUG_GET_ONCE_BOOL_OPTION(noop, "RADEON_NOOP", FALSE)
>
> -static void radeon_drm_cs_flush(struct radeon_winsys_cs *rcs, unsigned flags)
> +static void radeon_drm_cs_flush(struct radeon_winsys_cs *rcs, unsigned 
> flags, uint32_t cs_trace_id)
>  {
>      struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
>      struct radeon_cs_context *tmp;
> @@ -474,6 +477,8 @@ static void radeon_drm_cs_flush(struct radeon_winsys_cs 
> *rcs, unsigned flags)
>      cs->csc = cs->cst;
>      cs->cst = tmp;
>
> +    cs->cst->cs_trace_id = cs_trace_id;
> +
>      /* If the CS is not empty or overflowed, emit it in a separate thread. */
>      if (cs->base.cdw && cs->base.cdw <= RADEON_MAX_CMDBUF_DWORDS && 
> !debug_get_option_noop()) {
>          unsigned i, crelocs = cs->cst->crelocs;
> @@ -536,7 +541,7 @@ static void radeon_drm_cs_flush(struct radeon_winsys_cs 
> *rcs, unsigned flags)
>                  }
>              }
>              pipe_mutex_unlock(cs->ws->cs_stack_lock);
> -            radeon_drm_cs_emit_ioctl_oneshot(cs->cst);
> +            radeon_drm_cs_emit_ioctl_oneshot(cs, cs->cst);
>          }
>      } else {
>          radeon_cs_context_cleanup(cs->cst);
> diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.h 
> b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h
> index 66aee55..7683e96 100644
> --- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.h
> +++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h
> @@ -30,8 +30,6 @@
>  #include "radeon_drm_bo.h"
>  #include <radeon_drm.h>
>
> -#define RADEON_CS_DUMP_ON_LOCKUP    0
> -
>  struct radeon_cs_context {
>      uint32_t                    buf[RADEON_MAX_CMDBUF_DWORDS];
>
> @@ -41,6 +39,8 @@ struct radeon_cs_context {
>      uint64_t                    chunk_array[3];
>      uint32_t                    flags[2];
>
> +    uint32_t                    cs_trace_id;
> +
>      /* Relocs. */
>      unsigned                    nrelocs;
>      unsigned                    crelocs;
> @@ -78,6 +78,7 @@ struct radeon_drm_cs {
>
>      int flush_started;
>      pipe_semaphore flush_completed;
> +    struct radeon_bo                    *trace_buf;
>  };
>
>  int radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo);
> @@ -121,10 +122,8 @@ radeon_bo_is_referenced_by_any_cs(struct radeon_bo *bo)
>
>  void radeon_drm_cs_sync_flush(struct radeon_winsys_cs *rcs);
>  void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws);
> -void radeon_drm_cs_emit_ioctl_oneshot(struct radeon_cs_context *csc);
> +void radeon_drm_cs_emit_ioctl_oneshot(struct radeon_drm_cs *cs, struct 
> radeon_cs_context *csc);
>
> -#if RADEON_CS_DUMP_ON_LOCKUP
> -void radeon_dump_cs_on_lockup(struct radeon_cs_context *csc);
> -#endif
> +void radeon_dump_cs_on_lockup(struct radeon_drm_cs *cs, struct 
> radeon_cs_context *csc);
>
>  #endif
> diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c 
> b/src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c
> index a3634bf..e738a98 100644
> --- a/src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c
> +++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c
> @@ -34,18 +34,18 @@
>  #include "radeon_drm_cs.h"
>  #include "radeon_drm_bo.h"
>
> -#if RADEON_CS_DUMP_ON_LOCKUP
> -static bool dumped = false;
> +#define RADEON_CS_DUMP_AFTER_MS_TIMEOUT         500
>
> -void radeon_dump_cs_on_lockup(struct radeon_cs_context *csc)
> +void radeon_dump_cs_on_lockup(struct radeon_drm_cs *cs, struct 
> radeon_cs_context *csc)
>  {
>      struct drm_radeon_gem_busy args;
>      FILE *dump;
>      unsigned i, lockup;
>      uint32_t *ptr;
> +    char fname[32];
>
>      /* only dump the first cs to cause a lockup */
> -    if (!csc->crelocs || dumped) {
> +    if (!csc->crelocs) {
>          /* can not determine if there was a lockup if no bo were use by
>           * the cs and most likely in such case no lockup occurs
>           */
> @@ -54,19 +54,27 @@ void radeon_dump_cs_on_lockup(struct radeon_cs_context 
> *csc)
>
>      memset(&args, 0, sizeof(args));
>      args.handle = csc->relocs_bo[0]->handle;
> -    for (i = 0; i < 10; i++) {
> -        usleep(5);
> +    for (i = 0; i < RADEON_CS_DUMP_AFTER_MS_TIMEOUT; i++) {
> +        usleep(1);
>          lockup = drmCommandWriteRead(csc->fd, DRM_RADEON_GEM_BUSY, &args, 
> sizeof(args));
>          if (!lockup) {
>              break;
>          }
>      }
> -    if (!lockup || i < 10) {
> +    if (!lockup || i < RADEON_CS_DUMP_AFTER_MS_TIMEOUT) {
> +        return;
> +    }
> +
> +    ptr = radeon_bo_do_map(cs->trace_buf);
> +    fprintf(stderr, "timeout on cs lockup likely happen at cs 0x%08x dw 
> 0x%08x\n", ptr[1], ptr[0]);
> +
> +    if (csc->cs_trace_id != ptr[1]) {
>          return;
>      }
>
>      /* ok we are most likely facing a lockup write the standalone replay 
> file */
> -    dump = fopen("radeon_lockup.c", "w");
> +    snprintf(fname, sizeof(fname), "rlockup_0x%08x.c", csc->cs_trace_id);
> +    dump = fopen(fname, "w");
>      if (dump == NULL) {
>          return;
>      }
> @@ -74,8 +82,9 @@ void radeon_dump_cs_on_lockup(struct radeon_cs_context *csc)
>      fprintf(dump, " * in same directory. You can find radeon_ctx.h in mesa 
> tree :\n");
>      fprintf(dump, " * mesa/src/gallium/winsys/radeon/tools/radeon_ctx.h\n");
>      fprintf(dump, " * Build with :\n");
> -    fprintf(dump, " * gcc -O0 -g radeon_lockup.c -ldrm -o radeon_lockup 
> -I/usr/include/libdrm\n");
> +    fprintf(dump, " * gcc -O0 -g %s -ldrm -o rlockup_0x%08x 
> -I/usr/include/libdrm\n", fname, csc->cs_trace_id);
>      fprintf(dump, " */\n");
> +    fprintf(dump, " /* timeout on cs lockup likely happen at cs 0x%08x dw 
> 0x%08x*/\n", ptr[1], ptr[0]);
>      fprintf(dump, "#include <stdio.h>\n");
>      fprintf(dump, "#include <stdint.h>\n");
>      fprintf(dump, "#include \"radeon_ctx.h\"\n");
> @@ -107,6 +116,7 @@ void radeon_dump_cs_on_lockup(struct radeon_cs_context 
> *csc)
>      }
>      fprintf(dump, "};\n\n");
>
> +    fprintf(dump, "/* cs %d dw */\n", csc->chunks[0].length_dw);
>      fprintf(dump, "static uint32_t cs[] = {\n");
>      ptr = csc->buf;
>      for (i = 0; i < csc->chunks[0].length_dw; i++) {
> @@ -147,6 +157,4 @@ void radeon_dump_cs_on_lockup(struct radeon_cs_context 
> *csc)
>      fprintf(dump, "    bo_wait(&ctx, bo[0]);\n");
>      fprintf(dump, "}\n");
>      fclose(dump);
> -    dumped = true;
>  }
> -#endif
> diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c 
> b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
> index f6877d5..3689020 100644
> --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
> +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
> @@ -551,7 +551,7 @@ next:
>          pipe_mutex_unlock(ws->cs_stack_lock);
>
>          if (cs) {
> -            radeon_drm_cs_emit_ioctl_oneshot(cs->cst);
> +            radeon_drm_cs_emit_ioctl_oneshot(cs, cs->cst);
>
>              pipe_mutex_lock(ws->cs_stack_lock);
>              for (i = 1; i < p_atomic_read(&ws->ncs); i++) {
> diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h 
> b/src/gallium/winsys/radeon/drm/radeon_winsys.h
> index a37bd12..1c2fb69 100644
> --- a/src/gallium/winsys/radeon/drm/radeon_winsys.h
> +++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h
> @@ -368,8 +368,12 @@ struct radeon_winsys {
>       * Create a command stream.
>       *
>       * \param ws        The winsys this function is called from.
> +     * \param ring_type The ring type (GFX, DMA, UVD)
> +     * \param trace_buf Trace buffer when tracing is enabled
>       */
> -    struct radeon_winsys_cs *(*cs_create)(struct radeon_winsys *ws, enum 
> ring_type ring_type);
> +    struct radeon_winsys_cs *(*cs_create)(struct radeon_winsys *ws,
> +                                          enum ring_type ring_type,
> +                                          struct radeon_winsys_cs_handle 
> *trace_buf);
>
>      /**
>       * Destroy a command stream.
> @@ -425,10 +429,11 @@ struct radeon_winsys {
>      /**
>       * Flush a command stream.
>       *
> -     * \param cs        A command stream to flush.
> -     * \param flags,    RADEON_FLUSH_ASYNC or 0.
> +     * \param cs          A command stream to flush.
> +     * \param flags,      RADEON_FLUSH_ASYNC or 0.
> +     * \param cs_trace_id A unique identifiant for the cs
>       */
> -    void (*cs_flush)(struct radeon_winsys_cs *cs, unsigned flags);
> +    void (*cs_flush)(struct radeon_winsys_cs *cs, unsigned flags, uint32_t 
> cs_trace_id);
>
>      /**
>       * Set a flush callback which is called from winsys when flush is
> --
> 1.8.2
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to