summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_display_engine.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/kernel/gsp_display_engine.c b/kernel/gsp_display_engine.c
index 98f85fe..c522a93 100644
--- a/kernel/gsp_display_engine.c
+++ b/kernel/gsp_display_engine.c
@@ -1419,6 +1419,30 @@ void gsp_disp_engine_pump(struct nv_vgpu_device *vgpu)
0xffc;
/*
+ * Ring wrap / reset resync (eng4, 2026-11-12). nvEvoMakeRoom
+ * resets the driver's push pointer to the ring base when it
+ * wraps (writes a JUMP at the head, sets putOffset = 0), so the
+ * channel's PUT steps BACKWARD below our consumed. gsp_disp_run
+ * deliberately only publishes a GET that reached PUT exactly
+ * (see its r1630 comment), so a stale consumed left AHEAD of PUT
+ * can never resync: the parse from the old consumed hits the
+ * wrapped tail and never lands on the new PUT, GET stays past
+ * PUT forever, and nvidia-modeset's nvEvoMakeRoom /
+ * nvEvoPollForEmptyChannel spin (they break only on GET ==
+ * put_offset). Seen live as core c57d PUT=0xcc8 GET=0xcd8 held
+ * for minutes with Xorg 100% in-kernel (nvkms_yield) and xdpyinfo
+ * unanswered. Re-seed consumed to the ring base and republish
+ * GET so the wrapped pushes are parsed from 0 (the driver's
+ * authoritative write pointer is PUT).
+ */
+ if (put < s->consumed) {
+ s->consumed = 0;
+ s->last_put = 0;
+ gsp_disp_bar0_write(vgpu,
+ s->ctl_off + GSP_DISP_REG_GET, 0);
+ }
+
+ /*
* Raster line for the window channels: NVC57E_GET_LINE at
* 0x208. Bit 15 set = blanking, 14:0 = line. A free-running
* 1080p60 counter is enough for the driver's scanline/vblank