diff --git a/src/asahi/lib/cmdbuf.xml b/src/asahi/lib/cmdbuf.xml
index 99f7abec04d..045d2877089 100644
--- a/src/asahi/lib/cmdbuf.xml
+++ b/src/asahi/lib/cmdbuf.xml
@@ -559,6 +559,7 @@
+
@@ -657,6 +658,15 @@
+
+
+
+
+
+
+
diff --git a/src/asahi/lib/decode.c b/src/asahi/lib/decode.c
index 4bb88f83850..ce84ea0d6e3 100644
--- a/src/asahi/lib/decode.c
+++ b/src/asahi/lib/decode.c
@@ -262,9 +262,10 @@ agxdecode_dump_bo(struct agx_bo *bo, const char *name)
}
/* Abstraction for command stream parsing */
-typedef unsigned (*decode_cmd)(const uint8_t *map, bool verbose);
+typedef unsigned (*decode_cmd)(const uint8_t *map, uint64_t *link, bool verbose);
#define STATE_DONE (0xFFFFFFFFu)
+#define STATE_LINK (0xFFFFFFFEu)
static void
agxdecode_stateful(uint64_t va, const char *label, decode_cmd decoder, bool verbose)
@@ -276,13 +277,14 @@ agxdecode_stateful(uint64_t va, const char *label, decode_cmd decoder, bool verb
uint8_t *map = agxdecode_fetch_gpu_mem(va, 64);
uint8_t *end = (uint8_t *) alloc->ptr.cpu + alloc->size;
+ uint64_t link = 0;
if (verbose)
agxdecode_dump_bo(alloc, label);
fflush(agxdecode_dump_stream);
while (map < end) {
- unsigned count = decoder(map, verbose);
+ unsigned count = decoder(map, &link, verbose);
/* If we fail to decode, default to a hexdump (don't hang) */
if (count == 0) {
@@ -293,14 +295,19 @@ agxdecode_stateful(uint64_t va, const char *label, decode_cmd decoder, bool verb
map += count;
fflush(agxdecode_dump_stream);
- if (count == STATE_DONE)
+ if (count == STATE_DONE) {
break;
+ } else if (count == STATE_LINK) {
+ alloc = agxdecode_find_mapped_gpu_mem_containing(link);
+ map = agxdecode_fetch_gpu_mem(link, 64);
+ end = (uint8_t *) alloc->ptr.cpu + alloc->size;
+ }
}
}
unsigned COUNTER = 0;
static unsigned
-agxdecode_pipeline(const uint8_t *map, UNUSED bool verbose)
+agxdecode_pipeline(const uint8_t *map, uint64_t *link, UNUSED bool verbose)
{
uint8_t zeroes[16] = { 0 };
@@ -461,7 +468,7 @@ agxdecode_record(uint64_t va, size_t size, bool verbose)
}
static unsigned
-agxdecode_cmd(const uint8_t *map, bool verbose)
+agxdecode_cmd(const uint8_t *map, uint64_t *link, bool verbose)
{
if (map[0] == 0x02 && map[1] == 0x10 && map[2] == 0x00 && map[3] == 0x00) {
/* XXX: This is a CDM command not a VDM one */
@@ -542,6 +549,13 @@ agxdecode_cmd(const uint8_t *map, bool verbose)
return ALIGN_POT(length, 8);
}
+ case AGX_VDM_BLOCK_TYPE_STREAM_LINK: {
+ agx_unpack(agxdecode_dump_stream, map, STREAM_LINK, hdr);
+ DUMP_UNPACKED(STREAM_LINK, hdr, "Stream Link\n");
+ *link = hdr.target_lo | (((uint64_t) hdr.target_hi) << 32);
+ return STATE_LINK;
+ }
+
case AGX_VDM_BLOCK_TYPE_STREAM_TERMINATE: {
DUMP_CL(STREAM_TERMINATE, map, "Stream Terminate");
return STATE_DONE;