summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
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