summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_sema_service.c81
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))) {