From acb51d5389219dfe5d6415b753d849753ace98ea Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Thu, 12 Nov 2026 22:30:28 -0500 Subject: vgsp: DDX re-probe stops once the latch has served (stops lookalike switch thrash) In svc_userd_ddx_reprobe, refuse to switch while the current latch has just delivered decoded entries (ch->submissions != gr_ram_userd_latch_sub), the same 'served' criterion the pump's DEFERRED clause uses. The switch path resets defers=0, so a defers-based guard would have stopped only the first of c141's six switches; forward-only nput>oput is semantically wrong for DDX generations (a fresh block starts with a tiny put) and would lock onto the junk maximum. Validated c150-c153 (rich args + tick): latch SWITCHED 0/run (was 6-8 at ~2 s), sema-xchan uok=1 continuous, and c152/c153 Xorg logs show ZERO 'Failed to (idle|initialize) DMA'/push-buffer/AddScreen lines - the ScreenInit DMA instance is now stable on the deferral alone. Residual (next): Xorg then spins in-kernel (95% CPU, SIGKILL-immune, xdpyinfo unanswered; userd put=0 get=0 vs last=7098 in sema-xchan is the lead) - gl_frames still hangs at BAR map. --- kernel/gsp_sema_service.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'kernel/gsp_sema_service.c') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index f8604b6..ced815d 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -43976,6 +43976,25 @@ static bool svc_userd_ddx_reprobe(struct nv_vgpu_device *vgpu, if (!svc_userd_ddx_family(ch) || !ch->userd_ok || ch->gr_ram_userd_confirmed || !ch->gr_ram_userd_latch_at) return false; + /* + * CONT.462 follow-up (X-DMA latch lifetime, c141 residual): a latch + * that has SERVED is never swapped speculatively. c141 showed six + * SWITCHED events in ~70 s, every one of them driven by a re-probe of + * a static lookalike: the switch itself re-seeds last_get behind the + * new block's put (the span seed below), priming a consume burst that + * makes the NEXT block "served" within a pass or two - so the + * defer/switch ladder self-sustained and starved the client (Xorg spun + * with uok=1 held; gl_frames never reached px0). Do NOT key this guard + * on ch->gr_ram_userd_defers: the switch path resets defers to 0, so a + * defers-guard would have stopped only the first of those six. Only an + * UNSERVED latch - the c140 class, where submissions stayed frozen + * while the client's own block never landed - may yield to a freshly + * validated block inside the client's ~10 s DMA-test window. The + * pump's confirm/reject/defer ladder still owns the latch's lifetime + * (defer bound 32, then reject -> the RAM scan re-adopts fresh). + */ + if (ch->submissions != ch->gr_ram_userd_latch_sub) + return false; if (!svc_gr_ram_userd_scan(vgpu, ch, &npa, &nput, &nget)) return false; if (npa == ch->userd_pa) -- cgit v1.2.3