summaryrefslogtreecommitdiffstats
path: root/src/gallium/winsys/radeon/drm
diff options
context:
space:
mode:
authorJerome Glisse <[email protected]>2013-04-23 19:22:33 -0400
committerJerome Glisse <[email protected]>2013-04-25 18:36:31 -0400
commitabb96fdea70546f974ba59cbd00bc54afee9cfdb (patch)
tree26cd3596731ed64e3a242ded8779bb1930472a70 /src/gallium/winsys/radeon/drm
parent53fbae7eace466d8fe22173c01518fbde7102d6c (diff)
winsys/radeon: consolidate tracing into winsys v2
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 <[email protected]> Reviewed-by: Marek Olšák <[email protected]>
Diffstat (limited to 'src/gallium/winsys/radeon/drm')
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_cs.c19
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_cs.h11
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c30
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_winsys.c2
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_winsys.h13
5 files changed, 46 insertions, 29 deletions
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
index 720e0864d19..ea0c99df3fa 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 66aee55dae0..7683e96f525 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 a3634bf2566..e738a988679 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 f6877d5e95d..368902039c4 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 a37bd120cb8..1c2fb698981 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