diff options
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 54 |
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 |
