diff options
| -rw-r--r-- | kernel/gsp_sema_service.c | 81 |
1 files changed, 77 insertions, 4 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 53b8288..2019a35 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -13211,9 +13211,19 @@ static bool svc_gr_request(struct nv_vgpu_device *vgpu, * request's done/hw_rc are still being read. The capture falls back. */ if (svc_fwd_hold.active) { - svc_gr_busy_defer = !gsp_cuda_bridge_enabled(); svc.fwd_gr_refused++; svc.fwd_gr_fallback++; + /* + * m159: with the bridge disabled the capture is not consumed: + * the candidate survives for the caller's bounded + * wait+retry (the launch can still run once the active + * forward resolves). With the bridge enabled the fallback + * owns the work and consumes the candidate as before. + */ + if (!gsp_cuda_bridge_enabled()) { + svc_gr_busy_defer = true; + return false; + } svc_gr_bridge_fallback(vgpu); return false; } @@ -13221,9 +13231,12 @@ static bool svc_gr_request(struct nv_vgpu_device *vgpu, if (svc_fwd_paused || test_and_set_bit_lock(SVC_FWD_INFLIGHT, &svc_fwd_state)) { mutex_unlock(&svc_fwd_lock); - svc_gr_busy_defer = !gsp_cuda_bridge_enabled(); svc.fwd_gr_refused++; svc.fwd_gr_fallback++; + if (!gsp_cuda_bridge_enabled()) { + svc_gr_busy_defer = true; + return false; + } svc_gr_bridge_fallback(vgpu); return false; } @@ -14532,6 +14545,67 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) !ch->engine_type) ch->gr_hold_idx = ~0u; /* + * m159: a busy refusal (forward + * in flight / release hold + * active) means this launch CAN + * still run - only later. The + * candidate survives the refusal + * (the busy paths do not consume + * it), so wait bounded for the + * slot to free - resolving the + * active hold through its own + * channel, since this pump thread + * is the hold resolver - then + * retry the request inline. This + * serializes multi-launch clients + * (streams2: kernels 2/3 queued + * while kernel 1 is in flight) + * without losing their releases. + * On timeout the historical + * consume + soft-release path + * stands (bounded, never a hang). + */ + if (!fwd_guest_queued && + !ch->engine_type && + svc_gr_busy_defer) { + unsigned long wend = jiffies + + msecs_to_jiffies(4000); + + while (time_before(jiffies, + wend)) { + if (svc_fwd_hold.active && + svc_fwd_hold.vgpu == + vgpu) { + int hk; + + for (hk = 0; hk < n; hk++) { + if (local[hk].h_object != + svc_fwd_hold.ch_handle) + continue; + svc_fwd_hold_poll(vgpu, + &local[hk], + 0); + break; + } + } + if (!svc_fwd_hold.active && + !test_bit(SVC_FWD_INFLIGHT, + &svc_fwd_state) && + smp_load_acquire( + &svc_fwd_req.done)) + break; + msleep(5); + } + if (!svc_fwd_hold.active && + !test_bit(SVC_FWD_INFLIGHT, + &svc_fwd_state)) + fwd_guest_queued = + svc_fwd_request(vgpu, + ch); + if (fwd_guest_queued) + svc.fwd_gr_defer++; + } + /* * m150: the GR fill held this * launch because its high * argument pointers do not @@ -14549,8 +14623,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) */ if (!fwd_guest_queued && !ch->engine_type && - (svc_gr_data_stalled || - svc_gr_busy_defer) && + svc_gr_data_stalled && (ch->gr_hold_idx != (u32)idx || time_before(jiffies, ch->gr_hold_until))) { |
