diff options
| -rw-r--r-- | kernel/gsp_display_engine.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/kernel/gsp_display_engine.c b/kernel/gsp_display_engine.c index c2fab96..5109245 100644 --- a/kernel/gsp_display_engine.c +++ b/kernel/gsp_display_engine.c @@ -972,6 +972,32 @@ static void gsp_disp_run(struct nv_vgpu_device *vgpu, struct gsp_disp_chan *ch, } } + /* + * Only publish a read pointer when the segment parsed through to the + * driver's PUT. A segment that runs off the 4 KB ring (unwritten or + * not-yet-visible content) or hits misaligned data must NOT consume + * anything: publishing GET past PUT wedged nvidia-modeset on the + * window channel (r1630: GET=0x1000, "Error while waiting for GPU + * progress"). Leaving consumed unchanged also retries next pass, + * which covers a ring the guest has kicked but not yet flushed. + */ + if (off != put) { + if (gsp_disp_dbg && disp.push_dumps < 8) { + u32 d, shown = 16; + + disp.push_dumps++; + pr_info("h=0x%x push-noparse 0x%x..0x%x (consumed stays 0x%x) head:", + ch->hclass, start, put, ch->consumed); + if (put > start && put - start < shown) + shown = put - start; + for (d = 0; d < shown; d++) + pr_cont(" %08x", + *(u32 *)(disp.pbuf + start + 4 * d)); + pr_cont("\n"); + } + return; + } + ch->consumed = off; ch->last_put = put; if (gsp_disp_dbg && off != start) @@ -1111,6 +1137,10 @@ void gsp_disp_engine_vgpu_cleanup(struct nv_vgpu_device *vgpu) unsigned long flags; int i; + /* Fresh diagnostic budgets for the next mdev/boot. */ + disp.push_dumps = 0; + disp.im_logs = 0; + spin_lock_irqsave(&disp.lock, flags); for (i = 0; i < GSP_DISP_MAX_CHANNELS; i++) { if (disp.ch[i].valid && disp.ch[i].vgpu == vgpu) { |
