From 1b73a33cd440f556567f566c9a066869695203f7 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Fri, 23 Oct 2026 15:15:31 -0400 Subject: vgsp-gr r556: absolute 15 s per-launch deferral cap (single stall backstop) r553/r555 boots still show clients walking the individual defer/hold bounds for 400+ s: victory_reduce 430 s (same push VA re-deferred every pass, r554's 64-slot latch), victory_saxpy 254 s at write time with work_guard deferred climbing by the thousand. Each guard is bounded on its own, but their bounds interact and re-arm across re-decode passes. Arm an ABSOLUTE per-push-VA deadline on first sighting (64-slot table); once 15 s have passed, svc_gr_defer_expired() returns true and every defer site forwards best-effort: the r541 dstpend guard, the r543 arg-partial guard and the m150 data-stalled hold. 15 s sits far above the 0.5-2 s pin latency the deferrals exist to cover and far below every client-side timeout (>= 60 s), so the pin-late cases keep their window and no launch can be parked longer than the cap, whichever guard keeps winning. --- kernel/gsp_sema_service.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) (limited to 'kernel') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index b2cf8a5..a3366ba 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -20704,6 +20704,42 @@ static bool svc_gr_arg_defer_ok(u64 push_va) return true; } +/* + * r556: the ABSOLUTE per-launch deferral cap. Every defer path (r541 + * dstpend, r543 partial args, m150 data-stalled hold, busy-defer re-holds) + * is individually bounded, but the bounds interact and re-arm across + * re-decode passes; the r553/r555 boots show clients still walking these + * loops for 400+ s (victory_reduce 430 s, victory_saxpy 254 s at write + * time, work_guard deferred climbing by the thousand). This is the single + * backstop that makes "a launch can never be deferred for more than + * SVC_GR_DEFER_CAP_MS" true regardless of which guard keeps winning: the + * first sighting of a push VA arms an absolute deadline; once it passes, + * svc_gr_defer_expired() returns true and every defer site forwards + * best-effort. 15 s is well above the 0.5-2 s pin latency the deferrals + * exist to cover and well below every client-side timeout (>= 60 s). + */ +#define SVC_GR_DEFER_CAP_MS 15000u +static u64 svc_gr_defer_cap_va[SVC_GR_ARG_DEFER_SLOTS]; +static unsigned long svc_gr_defer_cap_j[SVC_GR_ARG_DEFER_SLOTS]; +static u32 svc_gr_defer_cap_pos; + +static bool svc_gr_defer_expired(u64 push_va) +{ + u32 i; + + if (!push_va) + return false; + for (i = 0; i < SVC_GR_ARG_DEFER_SLOTS; i++) { + if (svc_gr_defer_cap_va[i] == push_va) + return !time_before(jiffies, svc_gr_defer_cap_j[i] + + msecs_to_jiffies(SVC_GR_DEFER_CAP_MS)); + } + i = svc_gr_defer_cap_pos++ % SVC_GR_ARG_DEFER_SLOTS; + svc_gr_defer_cap_va[i] = push_va; + svc_gr_defer_cap_j[i] = jiffies; + return false; +} + /* * r548: is a forward still OWED for this push VA - a captured, never * offered candidate sitting in the candidate ring? The r547 saxpy stall: @@ -20887,7 +20923,8 @@ static bool svc_gr_request(struct nv_vgpu_device *vgpu, * busy-defer + gr_hold machinery as every other busy refusal, so it * can never hang the launch. */ - if (svc_gr_dstpend_overlap()) { + if (svc_gr_dstpend_overlap() && + !svc_gr_defer_expired(svc_gr_cand.push_va)) { clear_bit_unlock(SVC_FWD_INFLIGHT, &svc_fwd_state); mutex_unlock(&svc_fwd_lock); svc_gr_busy_defer = true; @@ -20913,6 +20950,7 @@ static bool svc_gr_request(struct nv_vgpu_device *vgpu, * delays, it cannot hang. */ if (svc_fwd_req.gr_arg_partial && !svc_gr_data_stalled && + !svc_gr_defer_expired(svc_gr_cand.push_va) && svc_gr_arg_defer_ok(svc_gr_cand.push_va)) { clear_bit_unlock(SVC_FWD_INFLIGHT, &svc_fwd_state); mutex_unlock(&svc_fwd_lock); @@ -20978,7 +21016,8 @@ static bool svc_gr_request(struct nv_vgpu_device *vgpu, } } } - if (svc_gr_data_stalled) { + if (svc_gr_data_stalled && + !svc_gr_defer_expired(svc_gr_cand.push_va)) { clear_bit_unlock(SVC_FWD_INFLIGHT, &svc_fwd_state); mutex_unlock(&svc_fwd_lock); svc.fwd_gr_refused++; -- cgit v1.2.3