diff options
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 62 |
1 files changed, 59 insertions, 3 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 603e9f0..435386e 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -39161,6 +39161,46 @@ static void svc_fwd_gr_work(void) } } + /* + * Chain the saved-window release behind a successful host pack + * carrier: the carrier's launch poll owns the single forwarding slot + * for up to sema_mme_fast_ms, and the client's 3D channel may tear + * down before the next service pass fires the armed release (c779: + * release ARM at +0.1 s, beef channel unregistered ~2.2 s later -> + * MME-CARRY-HOLD reason=no-channel). Wait out the release's settle + * grace inside this slot, claim it, and run the release work + * directly, so the saved window reaches the engine while the channel + * is still alive. The release work owns the outcome publish and the + * INFLIGHT clear. + */ + if (!hw_rc && svc_fwd_req.gr_synthetic && !svc_fwd_req.gr_release && + gsp_phys_gr_mme_release_chain_enabled()) { + unsigned long deadline = jiffies + msecs_to_jiffies(500); + u32 rheld = 0, rwin = 0; + bool took = false; + + while (gsp_phys_gr_mme_release_waiting() && + time_before(jiffies, deadline)) { + if (gsp_phys_gr_mme_release_take( + svc_fwd_req.gr_h_object, &rheld, &rwin)) { + took = true; + break; + } + msleep(10); + } + if (took) { + pr_info("vgsp-gr: MME-CARRY-FIRE mode=release held=%u win=%u h=0x%x push=0x%llx (chained after the pack carrier)\n", + rheld, rwin, svc_fwd_req.gr_h_object, + (unsigned long long)SVC_GR_CARRIER_PUSH_VA); + svc_fwd_req.gr_release = true; + svc_fwd_req.gr_synthetic = true; + svc_fwd_req.done = false; + svc_fwd_req.hw_rc = 0; + svc_fwd_gr_release_work(); + return; + } + } + svc_fwd_req.fault = cp.fault; svc_fwd_req.hw_rc = hw_rc; /* @@ -50113,6 +50153,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) u32 carry_h = 0; if (gsp_phys_gr_mme_carry_peek(&carry_h)) { + const char *why = "no-channel"; int ci; for (ci = 0; ci < n; ci++) { @@ -50120,16 +50161,31 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) if (c->h_object != carry_h || c->engine_type) continue; - if (svc_gr_cand_unoffered_for(carry_h)) + why = NULL; + if (svc_gr_cand_unoffered_for(carry_h)) { + why = "client-candidate"; break; + } if (svc_fwd_hold.active || - test_bit(SVC_FWD_INFLIGHT, &svc_fwd_state)) + test_bit(SVC_FWD_INFLIGHT, &svc_fwd_state)) { + why = "request-inflight"; break; - if (gsp_phys_gr_mme_fe_defer_wanted(carry_h, 2)) + } + if (gsp_phys_gr_mme_fe_defer_wanted(carry_h, 2)) { + why = "fe-defer"; break; + } (void)svc_gr_carrier_request(vgpu, c, false); break; } + /* + * An armed carrier that is due but cannot go out names + * its blocker (c781: it sat armed until the beef + * channel unregistered, with no receipt at all). + */ + if (why) + pr_info_ratelimited("vgsp-gr: MME-CARRY-WAIT reason=%s h=0x%x\n", + why, carry_h); } } |
