summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_sema_service.c50
1 files changed, 47 insertions, 3 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index a3783dc..6fa1813 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -394,6 +394,16 @@ struct svc_channel {
* even if still unresolved - bounded zeros, never
* a hang); m156: re-held while the window is
* live so a busy forward gets its real retry */
+ /*
+ * r509: one-shot verdict of the absolute bound. The expiry call
+ * pushes the deadline (so the hold window restarts) and latches this
+ * flag; the r351 retry-forward block consumes it within the same
+ * pass. Without the latch the two call sites in one pass could not
+ * both observe the expiry (the first push of the deadline made the
+ * second call see a fresh window - r213-r215's arming bug in
+ * reverse).
+ */
+ bool gr_hold_bound_hit;
unsigned long gr_hold_deadline; /* GRFIX FIX1b: hard expiry of the data-
* stalled hold for gr_hold_dead_va.
* Fixed once on the first hold of that
@@ -19161,6 +19171,18 @@ static bool svc_gr_hold_bound_expired(struct svc_channel *ch, u64 launch_va)
* forever (the same identity bug class as the opdef=955/13/0
* streams2 wedge). The first hold arms; others ride it; a fresh
* bound arms once the previous one has passed.
+ *
+ * r509: the bound must actually REPORT expiry. The historical arming
+ * rule re-armed the deadline on the very call that detected expiry
+ * and then compared against the NEW deadline - so the function could
+ * never return true, and a data-stalled launch whose arguments never
+ * resolved held its entry forever (r508 witness: matmul plus ten
+ * sibling channels in "GR hold ... data args unresolved" with zero
+ * GR-STALL-hold-bound lines for 10+ minutes; the designed
+ * retry-forward + consume never ran). The expiry is now one-shot:
+ * push the deadline, latch gr_hold_bound_hit for the r351 block of
+ * the same pass, return true. A fresh arm clears the latch (and the
+ * once-per-launch retry log).
*/
if (!ch->gr_hold_dead_va ||
time_after_eq(jiffies, ch->gr_hold_deadline)) {
@@ -19168,6 +19190,8 @@ static bool svc_gr_hold_bound_expired(struct svc_channel *ch, u64 launch_va)
ch->gr_hold_dead_since = jiffies;
ch->gr_hold_deadline = jiffies + msecs_to_jiffies(cap_ms);
ch->gr_hold_exp_logged = false;
+ ch->gr_hold_bound_hit = false;
+ return false;
}
/*
* r420: pause the per-launch consumption bound while the backend
@@ -19190,7 +19214,18 @@ static bool svc_gr_hold_bound_expired(struct svc_channel *ch, u64 launch_va)
launch_va);
return false;
}
- return time_after_eq(jiffies, ch->gr_hold_deadline);
+ if (time_after_eq(jiffies, ch->gr_hold_deadline)) {
+ /*
+ * r509: one-shot expiry. Push the deadline so the hold window
+ * restarts for the caller's retry, latch the verdict for the
+ * second call site of this pass (the r351 retry-forward
+ * block), and report expired.
+ */
+ ch->gr_hold_deadline = jiffies + msecs_to_jiffies(cap_ms);
+ ch->gr_hold_bound_hit = true;
+ return true;
+ }
+ return false;
}
static void svc_gr_data_fill(struct nv_vgpu_device *vgpu,
@@ -22118,10 +22153,15 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
if (!fwd_guest_queued &&
!ch->engine_type &&
svc_gr_data_stalled &&
- svc_gr_hold_bound_expired(ch,
- svc_gr_launch_va(ch)) &&
+ ch->gr_hold_bound_hit &&
!ch->gr_hold_exp_logged) {
ch->gr_hold_exp_logged = true;
+ /* r509: the latch is this pass's only
+ * report of the expiry; clear it so the
+ * NEXT expiry cycle (gr_hold_exp_logged
+ * now set) falls through to the
+ * historical consume. */
+ ch->gr_hold_bound_hit = false;
svc.fwd_gr_hold_exp++;
/*
* r351: the bound firing used to
@@ -23191,6 +23231,10 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
ch->gr_hold_deadline;
svc.chan[k].gr_hold_exp_logged =
ch->gr_hold_exp_logged;
+ /* r509: the one-shot expiry latch is snapshot
+ * state too. */
+ svc.chan[k].gr_hold_bound_hit =
+ ch->gr_hold_bound_hit;
/* r361: the opdef absolute-bound record is
* snapshot state too (the GRFIX lesson) -
* without the write-back the deadline would