summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-09 08:56:21 -0500
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-09 08:56:21 -0500
commitf10714c927bab9f93ddaeb2a6786b42cb41264a3 (patch)
tree75d99d96e75507e2706cd54ed61bfc4d290b611a /kernel/gsp_sema_service.c
parenta3060a5485dd31eae5015d415fd29c29afa6f2bb (diff)
downloadopen-iov-f10714c927bab9f93ddaeb2a6786b42cb41264a3.tar.gz
open-iov-f10714c927bab9f93ddaeb2a6786b42cb41264a3.zip
vgsp: retry deferred display completions; escalate the UVM init-slot release
Two live walls from the r1649/r1650 windowed-GZDoom runs: 1. Display completion wake-up. All NV01_EVENT registrations carry hSrcResource=0, so gsp_rm_post_channel_event() always takes the shotgun fallback, which skips events posted within the 250 ms hint dedup. When the display UPDATE is the channel's last push, the pump's retry was gated on new work (put != consumed) and never ran, so the X server's flip wait spun in _nv018351rm/os_schedule forever. Add gsp_rm_post_channel_event_force() (bypasses only the hint dedup; the event burst cap and status-ring free-space discipline still apply), a per-channel event_retry_at, and an idle-pass retry every 250 ms that logs "re-posted after deferral". Also move event_burst_at after the cap check so refused retries cannot keep the window fresh. 2. UVM channel init slot. r1651 gdb proved the channel's tracker entry waits for value 2 while the authored pool word reads 1; a manual write of 2 cleared uvm_push_end_and_wait. The channel's control-entry + init pushes are boot-time configuration, so keep the rank slot moving for 10 s after first submission: one attempt per 250 ms per rank, escalating 1->2->3->4 through every published VAS translation. Values beyond that need the real CE push decode. Evidence: backups/evidence-20261002-victory/r1649/ (X spin perf, event journal), r1650/ (re-post lines), r1651/ (tracker entry value=2, manual write clears the spin).
Diffstat (limited to 'kernel/gsp_sema_service.c')
-rw-r--r--kernel/gsp_sema_service.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 11c4540..c9abc71 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -969,6 +969,9 @@ static unsigned long svc_ring_done; /* CE ranks whose ring is pinned (session st
* channel registration and cleared by svc_session_flush.
*/
static unsigned long svc_ce_initrel_done;
+static unsigned long svc_ce_initrel_until[32]; /* re-fan-out window per rank */
+static unsigned long svc_ce_initrel_next[32]; /* next retry per rank */
+static u32 svc_ce_initrel_val[32]; /* last value authored per rank */
static u32 svc_ce_initrel_log;
/* Per-guest session records (one per open mdev; see SVC_MAX_CHANNELS for the channel cap). */
@@ -2019,6 +2022,9 @@ static void svc_chan_rearm_rank(struct svc_channel *ch)
clear_bit(ch->ce_index, &svc_ring_done);
clear_bit(ch->ce_index, &svc_pb_done);
clear_bit(ch->ce_index, &svc_ce_initrel_done);
+ svc_ce_initrel_until[ch->ce_index] = 0;
+ svc_ce_initrel_next[ch->ce_index] = 0;
+ svc_ce_initrel_val[ch->ce_index] = 0;
} else {
clear_bit(ch->gr_index, &svc_gr_ring_done);
/*
@@ -22644,6 +22650,9 @@ static void svc_session_flush(void)
memset(svc_ce_hold_since, 0, sizeof(svc_ce_hold_since));
memset(svc_ce_firstsub_off, 0, sizeof(svc_ce_firstsub_off));
svc_ce_initrel_done = 0;
+ memset(svc_ce_initrel_until, 0, sizeof(svc_ce_initrel_until));
+ memset(svc_ce_initrel_next, 0, sizeof(svc_ce_initrel_next));
+ memset(svc_ce_initrel_val, 0, sizeof(svc_ce_initrel_val));
svc_ce_initrel_log = 0;
svc_fb_claim_reset();
svc_userd_sweep_log = 0;
@@ -25546,6 +25555,16 @@ static void svc_ce_init_rel_author(struct nv_vgpu_device *vgpu,
return;
if (test_and_set_bit(ch->ce_index, &svc_ce_initrel_done))
return;
+ /*
+ * r1650: keep re-fanning the rank slot for a short window. The UVM
+ * pool page can move (and a per-client VAS directory can be
+ * discovered) seconds after the first submission, so a single
+ * one-shot write can race the translation; the counter is
+ * forward-only, so the pump's periodic re-write is harmless.
+ */
+ svc_ce_initrel_until[ch->ce_index] = jiffies + 10 * HZ;
+ svc_ce_initrel_next[ch->ce_index] =
+ jiffies + msecs_to_jiffies(250);
/*
* UVM's per-channel tracking semaphore is pool slot rank (allocation
@@ -25555,6 +25574,7 @@ static void svc_ce_init_rel_author(struct nv_vgpu_device *vgpu,
tva = SVC_UVM_POOL_MAP_BASE + 4ULL * (u64)ch->ce_index;
svc.cur_ch = ch->h_object;
wrc = svc_sem_write(vgpu, ch->h_object, tva, 1);
+ svc_ce_initrel_val[ch->ce_index] = 1;
pr_info("sema-ceinit: h=0x%x rank=%u tracker=0x%llx val=1 %s (%s; init push release)\n",
ch->h_object, ch->ce_index, tva,
wrc == 0 ? "ok" : (wrc == -ENOENT ? "queued" : "failed"), why);
@@ -40431,6 +40451,40 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
}
/*
+ * r1650: keep the UVM rank-slot release moving for a short
+ * window. Two effects need it: the pool page can move / a
+ * per-client VAS directory can be discovered seconds later
+ * (r1649: the one-shot write landed on a stale page before
+ * the live directory existed), and the channel's init
+ * sequence queues more than one push (r1651 gdb: the rank-0
+ * tracker entry waited for value 2 while the authored word
+ * read 1; a manual write of 2 cleared uvm_push_end_and_wait).
+ * Forward-only and idempotent, one attempt per 250 ms per
+ * rank for 10 s, escalating 1 -> 2 -> 3 -> 4: the channel's
+ * control-entry + init pushes are boot-time configuration,
+ * so completing them host-side is the same shortcut the
+ * first release already uses. Values beyond that need the
+ * real CE push decode and are not authored here.
+ */
+ if (ch->engine_type && ch->ce_index < 32 &&
+ test_bit(ch->ce_index, &svc_ce_initrel_done) &&
+ time_before(jiffies, svc_ce_initrel_until[ch->ce_index]) &&
+ time_after_eq(jiffies,
+ svc_ce_initrel_next[ch->ce_index])) {
+ u64 tva2 = SVC_UVM_POOL_MAP_BASE +
+ 4ULL * (u64)ch->ce_index;
+
+ svc_ce_initrel_next[ch->ce_index] =
+ jiffies + msecs_to_jiffies(250);
+ if (svc_ce_initrel_val[ch->ce_index] < 4) {
+ svc_ce_initrel_val[ch->ce_index]++;
+ svc_pool_write_all_vas(vgpu, ch->h_object,
+ tva2,
+ svc_ce_initrel_val[ch->ce_index]);
+ }
+ }
+
+ /*
* P6c C3: a latched fault notifier is released when the guest
* submits more work (GPFIFO put advanced past the value at
* delivery), alongside the guest-ack read in