diff options
| -rw-r--r-- | kernel/gsp_sema_service.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 6e37b2f..0520c4f 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -425,6 +425,9 @@ struct svc_channel { * must reconcile the binding before the walk * (drop dead opdef slots whose since predates * the binding; log the transition) */ + unsigned long wd_newbind_hold_until; /* short hold window inside + * wd_newbind_until (residual-only, + * put==get; never delays fresh work) */ unsigned long wd_newbind_until; /* STALLFREE: freshness window of a * new binding; inside it an * unmapped/undecoded GR entry is held @@ -16604,6 +16607,15 @@ static void svc_userd_sweep(struct nv_vgpu_device *vgpu, struct svc_channel *ch, * window of extra latency on first contact. */ #define SVC_GR_NEWBIND_MS 3000u +/* + * STALLFREE r237: the HOLD part of the window must be shorter than the + * window itself. r237-2: the 3 s hold on T2's residual ring delayed its + * GP_GET past the guest's ~3 s ctx-init patience (T2 unwound with a + * zeroed PROMOTE_CTX at binding+3.46 s, exactly when the host finally + * consumed the residual). The guest needs GP_GET to advance promptly; + * the rebuild lands in ~0.8 s, so 1.2 s is enough for one attempt. + */ +#define SVC_GR_NEWBIND_HOLD_MS 1200u static void svc_gr_stale_wedge_check(struct nv_vgpu_device *vgpu, struct svc_channel *ch, u32 put, u32 get) @@ -17195,6 +17207,8 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) svc_opdef_drop_channel(vgpu, ch->h_object, jiffies); ch->wd_newbind_until = jiffies + msecs_to_jiffies(SVC_GR_NEWBIND_MS); + ch->wd_newbind_hold_until = jiffies + + msecs_to_jiffies(SVC_GR_NEWBIND_HOLD_MS); /* * Bounded proof (r234 asks): the window was armed for * THIS binding; if a later stall shows no such line, @@ -17719,9 +17733,10 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) !entry_replay && svc_rel_count == rel_n_iter && svc_gr_qmd_seen == 0 && - ch->wd_newbind_until && + put == get && + ch->wd_newbind_hold_until && time_before(jiffies, - ch->wd_newbind_until)) { + ch->wd_newbind_hold_until)) { if (!ch->defer_since) ch->defer_since = jiffies; @@ -18805,9 +18820,10 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) * the rebuild caught up). */ if (!ch->engine_type && - ch->wd_newbind_until && + put == get && + ch->wd_newbind_hold_until && time_before(jiffies, - ch->wd_newbind_until)) { + ch->wd_newbind_hold_until)) { svc.rebuild_now = true; if (svc.gr_pending_map < 16) { svc.gr_pending_map++; @@ -19045,6 +19061,8 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) svc.chan[k].wd_nocap_put = ch->wd_nocap_put; svc.chan[k].wd_chanswitch = ch->wd_chanswitch; svc.chan[k].wd_newbind_until = ch->wd_newbind_until; + svc.chan[k].wd_newbind_hold_until = + ch->wd_newbind_hold_until; svc.chan[k].pushpg_va = ch->pushpg_va; svc.chan[k].pushpg_n = ch->pushpg_n; svc.chan[k].content_max = ch->content_max; |
