diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_display_engine.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/kernel/gsp_display_engine.c b/kernel/gsp_display_engine.c index 0e66a84..ca470f2 100644 --- a/kernel/gsp_display_engine.c +++ b/kernel/gsp_display_engine.c @@ -157,6 +157,7 @@ static struct { u8 *pbuf; /* 4 KB push-buffer bounce (service thread only) */ unsigned long boot_jiffies; u32 log_budget; + u32 push_dumps; /* bounded raw push dumps (disp_dbg) */ /* Cached display-instance-memory base per guest (<= 2 guests). */ struct { struct nv_vgpu_device *vgpu; @@ -676,6 +677,31 @@ static void gsp_disp_run(struct nv_vgpu_device *vgpu, struct gsp_disp_chan *ch, if (gsp_disp_read(vgpu, ch->pb_pa, disp.pbuf, 4096)) return; + /* + * Bounded raw dump of the pushed segment (disp_dbg only): the head + * shows the first methods, the tail shows what completes the update + * (UPDATE 0x200 / SET_NOTIFIER 0x208/0x20c). Bounded to 4 pushes so + * a boot cannot flood the log. + */ + if (gsp_disp_dbg && disp.push_dumps < 4 && put > start) { + u32 dwords = put - start; + u32 d, shown = min_t(u32, dwords, 16); + + disp.push_dumps++; + pr_info("h=0x%x push@0x%x len=%u dwords head:", + ch->hclass, start, dwords); + for (d = 0; d < shown; d++) + pr_cont(" %08x", + *(u32 *)(disp.pbuf + start + 4 * d)); + if (dwords > 48) { + pr_cont(" ... tail:"); + for (d = dwords - 32; d < dwords; d++) + pr_cont(" %08x", + *(u32 *)(disp.pbuf + start + 4 * d)); + } + pr_cont("\n"); + } + while (off != put && steps++ < 8192) { u32 hdr, op, count, addr; @@ -684,7 +710,8 @@ static void gsp_disp_run(struct nv_vgpu_device *vgpu, struct gsp_disp_chan *ch, hdr = *(u32 *)(disp.pbuf + off); op = hdr >> 29; count = (hdr >> 18) & 0x3ff; - addr = (hdr >> 2) & 0xfff; + /* NV_UDISP_DMA_METHOD_OFFSET is 15:2 (14 bits). */ + addr = (hdr >> 2) & 0x3fff; switch (op) { case 0: /* METHOD (incrementing) */ |
