summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-22 00:10:36 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-22 00:10:36 -0400
commit6075628d72aae72e7ff4a882cb7ce28707ac220a (patch)
treea0660d68fc595dd205a3a029344e754315479afe
parentd8749ae001d1df02e5c84bfadfc5e78b5271830a (diff)
downloadopen-iov-6075628d72aae72e7ff4a882cb7ce28707ac220a.tar.gz
open-iov-6075628d72aae72e7ff4a882cb7ce28707ac220a.zip
r445 wedge hard re-arm experiment (gsp_phys_gr_wedge_rearm, default off): on the proven engine-wedged warm-sem-probe failure, one bounded recovery attempt - TSG PREEMPT bWait=1 (forced context save/unload) + the m155 extended re-arm (mode-35 lane-enable tail + GPFIFO schedules + doorbell) + a repeated probe - before the historical WEDGED break
-rw-r--r--kernel/gsp_phys_booter.c43
-rw-r--r--kernel/gsp_phys_gpu.c24
-rw-r--r--kernel/gsp_phys_gpu.h1
3 files changed, 68 insertions, 0 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 217f4e4..83f7802 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -15148,6 +15148,39 @@ static int gsp_phys_rmcall_ce_submit_locked(void __iomem *bar0, u64 src_va,
* semaphore. On timeout the existing status-queue drain runs and the helper
* returns -ETIMEDOUT; it never retries.
*/
+static int gsp_phys_rmcall_gr_resched_locked(void __iomem *bar0);
+static int gsp_phys_rmcall_gr_sem_push_locked(void __iomem *bar0);
+
+/*
+ * r445 wedge hard re-arm: the outcome-retry's warm semaphore probe proves the
+ * engine refused the channel's proven GR block (the sticky post-dispatch
+ * no-store wedge). One bounded recovery attempt instead of an immediate
+ * break: force a context save/unload with a bWait TSG preempt, re-run the
+ * mode-35 lane-enable tail + schedules (the m155 extended re-arm), then
+ * repeat the warm probe. Caller holds gsp_phys_rm_lock. Returns 0 when the
+ * engine executed the probe after the re-arm.
+ */
+static int gsp_phys_gr_wedge_hard_rearm_locked(void __iomem *bar0)
+{
+ u32 pre[2] = { 1u, 0u }; /* bWait=1, bManualTimeout=0 */
+ u32 rpc_result = 0, status = 0;
+ int ret;
+
+ ret = gsp_phys_rmcall_control(bar0, boot_stage.rmcall_tsg,
+ GSP_PHYS_RMCALL_CTRL_TSG_PREEMPT,
+ pre, sizeof(pre), sizeof(pre), NULL, 0,
+ &rpc_result, &status,
+ "TSG PREEMPT bWait=1 (r445 wedge hard re-arm)");
+ pr_warn("vgsp-gr: WEDGE-REARM preempt status=0x%x rpc=0x%x ret=%d\n",
+ status, rpc_result, ret);
+ ret = gsp_phys_rmcall_gr_resched_locked(bar0);
+ pr_warn("vgsp-gr: WEDGE-REARM resched ret=%d\n", ret);
+ ret = gsp_phys_rmcall_gr_sem_push_locked(bar0);
+ pr_warn("vgsp-gr: WEDGE-REARM probe rc=%d (engine %s after re-arm)\n",
+ ret, ret ? "still wedged" : "ALIVE");
+ return ret;
+}
+
static int gsp_phys_rmcall_gr_sem_push_locked(void __iomem *bar0)
{
struct gsp_phys_boot_chunk *userd_c =
@@ -20987,6 +21020,16 @@ gr_page_unmapped:
mutex_lock(&gsp_phys_rm_lock);
sp_ret = gsp_phys_rmcall_gr_sem_push_locked(
bar0);
+ /*
+ * r445: on a proven wedge, attempt one
+ * bounded preempt+resched hard re-arm
+ * before giving up (default off).
+ */
+ if (sp_ret &&
+ gsp_phys_gr_wedge_rearm_value())
+ sp_ret =
+ gsp_phys_gr_wedge_hard_rearm_locked(
+ bar0);
mutex_unlock(&gsp_phys_rm_lock);
pr_info("vgsp-gr: outcome retry %u: warm sem push rc=%d (engine %s)\n",
nw_attempts, sp_ret,
diff --git a/kernel/gsp_phys_gpu.c b/kernel/gsp_phys_gpu.c
index eadb4c2..b61929e 100644
--- a/kernel/gsp_phys_gpu.c
+++ b/kernel/gsp_phys_gpu.c
@@ -1174,6 +1174,30 @@ int gsp_phys_gr_nowrite_retries_value(void)
EXPORT_SYMBOL_GPL(gsp_phys_gr_nowrite_retries_value);
/*
+ * r445 wedge hard re-arm (gsp_phys_gr_wedge_rearm; default 0 = off). When the
+ * outcome-retry's warm GR semaphore probe proves the engine wedged for the
+ * context (the proven-sticky post-dispatch no-store state), this knob makes
+ * the submit attempt ONE bounded recovery instead of breaking immediately:
+ * a TSG PREEMPT(bWait=1) forces the FECS to save/unload the channel's
+ * context, then the mode-35 lane-enable tail + GPFIFO schedules are re-issued
+ * (the m155 extended re-arm) and the semaphore probe is repeated. A pass
+ * means the lane revived for this launch and the normal retry ladder
+ * continues; a fail leaves the historical WEDGED break. Read once per wedge
+ * episode. Off by default for A/B.
+ */
+static int gsp_phys_gr_wedge_rearm_param;
+module_param_named(gsp_phys_gr_wedge_rearm, gsp_phys_gr_wedge_rearm_param,
+ int, 0644);
+MODULE_PARM_DESC(gsp_phys_gr_wedge_rearm,
+ "r445: on the proven engine-wedged sem probe, attempt a bounded preempt+resched hard re-arm before giving up (default 0=off)");
+
+int gsp_phys_gr_wedge_rearm_value(void)
+{
+ return gsp_phys_gr_wedge_rearm_param ? 1 : 0;
+}
+EXPORT_SYMBOL_GPL(gsp_phys_gr_wedge_rearm_value);
+
+/*
* r410 wedge quiet window (gsp_phys_gr_wedge_quiet_ms; default 40000, clamped
* [0,120000]; 0 disables). The sticky per-lane no-execute wedge (100% of
* launches no-write while kept busy) is proven to CLEAR when the lane stays
diff --git a/kernel/gsp_phys_gpu.h b/kernel/gsp_phys_gpu.h
index 90783cb..46d841d 100644
--- a/kernel/gsp_phys_gpu.h
+++ b/kernel/gsp_phys_gpu.h
@@ -402,6 +402,7 @@ int gsp_phys_rmcall_gr_cwd_slot_value(void);
* retirement wait saw zero engine writes, independent of the timeout ladder's
* attempt counter (default 3, clamped [0,4]). */
int gsp_phys_gr_nowrite_retries_value(void);
+int gsp_phys_gr_wedge_rearm_value(void);
/* STALLFREE: absolute per-launch GR submit wall-clock budget in ms, clamped
* [10000,600000]; 0 = only the built-in per-ladder bounds (default 60000).