diff options
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 118 |
1 files changed, 114 insertions, 4 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 5c2001b..01eddd3 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -2606,6 +2606,7 @@ static struct { u64 pdb; u32 entries; bool vidmem; + bool aged_out; /* CONT.401: registered-once guard for the age-out */ unsigned long stamp; /* r537: park time for the bounded fallback */ } svc_vas_cand[SVC_VAS_CAND_MAX]; @@ -2630,6 +2631,7 @@ void gsp_sema_service_vaspace_candidate_add(u32 h_vaspace, u64 pdb, svc_vas_cand[i].pdb = pdb; svc_vas_cand[i].entries = entries; svc_vas_cand[i].vidmem = vidmem; + svc_vas_cand[i].aged_out = false; /* CONT.401: recycled slot */ svc_vas_cand[i].stamp = jiffies; return; } @@ -2637,6 +2639,60 @@ void gsp_sema_service_vaspace_candidate_add(u32 h_vaspace, u64 pdb, } /* + * CONT.401: a client restart rebuilds its page directory under the SAME VAS + * handle (observed: X VAS 0x10005 pdb 0x12a82f000 -> 0x14b259000). The + * CONT.400 "never downgrade verified" guard then pins the previous session's + * directory forever: the pump serves stale ring/push pages, consumes zero + * entries, and the DDX pushbuffer NOP test times out ("Failed to initialize + * DMA" / "Failed to allocate push buffer"). Return true when a parked + * candidate names a different directory for this handle, i.e. the stored + * verified directory is stale. + */ +static bool svc_vaspace_stale_candidate(u32 h_vaspace) +{ + unsigned long flags; + u64 stored = 0; + bool stale = false; + int i; + + if (!h_vaspace) + return false; + spin_lock_irqsave(&svc.vas_lock, flags); + for (i = 0; i < SVC_MAX_VASPACES; i++) + if (svc.vas[i].valid && svc.vas[i].verified && + svc.vas[i].h_vaspace == h_vaspace) { + stored = svc.vas[i].pdb; + break; + } + if (stored) + for (i = 0; i < SVC_VAS_CAND_MAX; i++) + if (svc_vas_cand[i].valid && + svc_vas_cand[i].h_vaspace == h_vaspace && + svc_vas_cand[i].pdb != stored) { + stale = true; + break; + } + spin_unlock_irqrestore(&svc.vas_lock, flags); + return stale; +} + +/* CONT.401: drop the verified mark so a rebuilt directory can install. */ +static void svc_vaspace_demote(u32 h_vaspace) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&svc.vas_lock, flags); + for (i = 0; i < SVC_MAX_VASPACES; i++) + if (svc.vas[i].valid && svc.vas[i].h_vaspace == h_vaspace) { + svc.vas[i].verified = false; + break; + } + memset(svc.lat, 0, sizeof(svc.lat)); + spin_unlock_irqrestore(&svc.vas_lock, flags); +} + +/* * r537 bounded fallback: register a parked candidate that has waited for * its content-verified ring walk longer than SVC_VAS_CAND_AGE_MS. The * verification (svc_vas_candidates_verify) needs the client's ring to be @@ -2722,6 +2778,15 @@ static void svc_vas_candidates_age_out(struct nv_vgpu_device *vgpu) time_before(jiffies, svc_vas_cand[i].stamp + msecs_to_jiffies(svc_vas_cand_age_ms))) continue; + /* + * CONT.401: register the fallback directory exactly once. + * Re-registering (and re-logging) on every pump pass flooded + * dmesg at ~50 Hz with sema_vas_cand_ms=1 and kept the pump + * busy, which starved the ring content scan. The candidate + * stays parked (valid=1) for the verified upgrade path. + */ + if (svc_vas_cand[i].aged_out) + continue; memset(&d, 0, sizeof(d)); d.h_vaspace = svc_vas_cand[i].h_vaspace; d.pdb = svc_vas_cand[i].pdb; @@ -2741,6 +2806,7 @@ static void svc_vas_candidates_age_out(struct nv_vgpu_device *vgpu) d.h_vaspace, svc_vas_cand_age_ms, d.pdb, d.num_entries); gsp_sema_service_vaspace_add(&d); + svc_vas_cand[i].aged_out = true; svc_vas_cand[i].stamp = jiffies; } } @@ -29441,19 +29507,38 @@ static void svc_chan_vas_candidate_promote(struct nv_vgpu_device *vgpu, * upgrade it by content until a walk proves it. Only a verified * directory lets us skip the walk. */ - if (!h || svc_vaspace_verified(h) || !ch->gpfifo_va || - ch->gpfifo_entries < 2) { + if (!h || !ch->gpfifo_va || ch->gpfifo_entries < 2) { /* CONT.400 diag: name the exact early-return reason. */ if ((ch->h_object & 0xfffff000u) == 0xbeef0000u && time_after(jiffies, svc_promote_diag_at)) { svc_promote_diag_at = jiffies + msecs_to_jiffies(2000); - pr_info("sema-svc: VAS-PROMOTE h=0x%x skip (h=0x%x verified=%d gpfifo=0x%llx entries=%u)\n", + pr_info("sema-svc: VAS-PROMOTE h=0x%x skip (h=0x%x gpfifo=0x%llx entries=%u)\n", ch->h_object, h, - h ? svc_vaspace_verified(h) : -1, ch->gpfifo_va, ch->gpfifo_entries); } return; } + if (svc_vaspace_verified(h)) { + /* + * CONT.401: see svc_vaspace_stale_candidate(). Only a verified + * directory with no contradicting parked candidate lets us + * skip the content walk; a rebuilt one is demoted first. + */ + if (!svc_vaspace_stale_candidate(h)) { + if ((ch->h_object & 0xfffff000u) == 0xbeef0000u && + time_after(jiffies, svc_promote_diag_at)) { + svc_promote_diag_at = jiffies + + msecs_to_jiffies(2000); + pr_info("sema-svc: VAS-PROMOTE h=0x%x skip (h=0x%x verified=1 gpfifo=0x%llx entries=%u)\n", + ch->h_object, h, + ch->gpfifo_va, ch->gpfifo_entries); + } + return; + } + pr_info("sema-svc: VAS 0x%x verified directory is stale (rebuilt pdb parked); demoting for re-validation\n", + h); + svc_vaspace_demote(h); + } for (i = 0; i < SVC_VAS_CAND_MAX; i++) { u64 wpa = 0; int wap = SVC_APERTURE_SYS; @@ -41300,6 +41385,31 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) * only after the X client's 10 s window. Content-gate it * against this channel's GPFIFO. */ + /* + * CONT.401: re-arm the GR ring content scan while the client + * is live, BEFORE the USERD probe. When the USERD block never + * passes svc_userd_probe() (ok=0, the exact unresolved-ring + * state) the pump `continue`s further down and never reaches + * the keep-alive at the end of the loop, so the bounded scan + * budget (40 slices) retires and the ring is never found. Read + * the raw GP_PUT from the registered USERD block and grant a + * fresh budget whenever it moves. + */ + if (!ch->engine_type && ch->h_object != 0x31415900u && + ch->gr_index < 32 && !ch->gr_ram_ring && ch->userd_pa && + !test_bit(ch->gr_index, &svc_gr_ring_done)) { + u32 rput = 0; + + if (!svc_read_ap(vgpu, ch->userd_pa + SVC_USERD_GP_PUT, + ch->userd_as, &rput, sizeof(rput)) && + rput && rput != ch->gr_ram_kick) { + ch->gr_ram_kick = rput; + ch->gr_ram_passes = 0; + ch->gr_ram_cursor = 0; + ch->gr_ram_refresh_at = jiffies + + msecs_to_jiffies(SVC_GR_RAM_REFRESH_MS); + } + } svc_chan_vas_candidate_promote(vgpu, ch); svc_ring_autopin(vgpu, ch); /* |
