summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_display_engine.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_display_engine.c')
-rw-r--r--kernel/gsp_display_engine.c29
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) */