From e9f5cfb561f7dc94b610e3130dfee9f3325d7d6d Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Sat, 24 Oct 2026 04:17:32 -0400 Subject: vgsp-gr r598 diag: peek the ring slots past GP_PUT at the launch decision The r568 lever is the driver's ring WRITE pointer, not the GPFIFO put: the b copy entry exists in the ring before the client publishes GP_PUT. Add a bounded diagnostic (gsp_phys_gr_peek) that, when a channel reads as drained, dumps up to four slots past last_get with {va,len} and whether the slot already executed that exact entry - so the next fix can be grounded in what is actually written ahead of the put. --- kernel/gsp_sema_service.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'kernel/gsp_sema_service.c') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index f1a31df..65b8ac1 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -21148,6 +21148,65 @@ static bool svc_ce_stream_backlog(struct nv_vgpu_device *vgpu) return false; } +/* + * r598 diag: the driver's ring WRITE pointer, not the GPFIFO put. The r568 + * draw needs the copy entries that are already written into the ring but + * whose GP_PUT has not been published yet. When the put says the ring is + * drained, peek at the slots immediately after the consumption position and + * log their {va,len} plus whether the slot already executed that exact + * entry. Bounded per launch, gated by gsp_phys_gr_peek. + */ +u32 gsp_phys_gr_peek; + +static void svc_gr_peek_lookahead(struct nv_vgpu_device *vgpu, + const struct svc_channel *self) +{ + u32 k, logged = 0; + + if (!gsp_phys_gr_peek || !svc_pass_local) + return; + for (k = 0; k < svc_pass_local_n && logged < 8; k++) { + const struct svc_channel *c = &svc_pass_local[k]; + u32 put = 0, j; + + if (!c->valid || c->h_object == self->h_object || + !c->gpfifo_va || !c->gpfifo_entries || !c->userd_pa) + continue; + if (svc_read_ap(vgpu, c->userd_pa + SVC_USERD_GP_PUT, + c->userd_as, &put, sizeof(put))) + continue; + put %= c->gpfifo_entries; + if (put != ((u32)c->last_get % c->gpfifo_entries)) + continue; /* real published backlog */ + pr_info("vgsp-gr: peek h=0x%x put=%u last=%u\n", + c->h_object, put, (u32)c->last_get); + for (j = 1; j <= 4; j++) { + u32 idx = ((u32)c->last_get + j) % c->gpfifo_entries; + u8 ent[SVC_GPFIFO_ENTRY_SIZE]; + u32 e0, e1, len; + u64 va; + + if (svc_read_va(vgpu, + c->gpfifo_va + + (u64)idx * SVC_GPFIFO_ENTRY_SIZE, + ent, sizeof(ent))) + break; + memcpy(&e0, ent, 4); + memcpy(&e1, ent + 4, 4); + va = ((u64)(e1 & 0xff) << 32) | + (u64)(e0 & 0xfffffffc); + len = ((e1 >> 10) & 0x1fffff) << 2; + if (!va || !len || len > SVC_PUSH_MAX) + break; + pr_info("vgsp-gr: peek +%u idx=%u va=0x%llx len=%u ident_match=%d\n", + j, idx, va, len, + c->slot_ops_ident[idx] == + ((u64)e0 | ((u64)e1 << 32))); + } + logged++; + } +} + /* * r576 DIAG: the GR launch-decision witness (gsp_phys_gr_dec_log=N budget * per boot). Logged from svc_gr_request right after the fill, for launches @@ -21401,6 +21460,7 @@ static bool svc_gr_request(struct nv_vgpu_device *vgpu, * historical forward stands (witnessed) - the guard delays a launch, * it never refuses one, so it cannot recreate r588's mail refusal. */ + svc_gr_peek_lookahead(vgpu, ch); if (svc_ce_stream_backlog(vgpu)) { if (!svc_gr_defer_expired(svc_gr_cand.push_va)) { clear_bit_unlock(SVC_FWD_INFLIGHT, &svc_fwd_state); -- cgit v1.2.3