summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/gsp_sema_service.c118
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);
/*