summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_sema_service.c67
1 files changed, 47 insertions, 20 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 83bae47..4c46bf3 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -7528,27 +7528,49 @@ static struct svc_wait_hold *svc_wait_hold_get(u32 h, bool create)
}
/*
- * r506w: bounded per-VA failure latch for virtual ops. A virtual op that
- * keeps failing -ENOENT (an unresolvable VA) re-runs on every decode pass
- * and sets svc.op_tr_pending each time, so its push holds for the full
+ * r506w/r507a: bounded per-VA failure latch for virtual ops. A virtual op
+ * that keeps failing -ENOENT (an unresolvable VA) re-runs on every decode
+ * pass and sets svc.op_tr_pending each time, so its push holds for the full
* SVC_OPDEF_HOLD_MS opdef bound - a client whose stream carries such an op
* (r505/r506 witness: the RM's channel-progress zeroing at 0x2000c0xxx
* after the first client, dst never translated) ground its whole stream
* at ~10 s per push ("hang after DEVICE" for matmul/multikernel).
- * After SVC_OPFAIL_LATCH failures of the same VA the op still attempts
- * the write but no longer forces the hold: the entry consumes promptly and
- * its withheld release is applied, exactly the outcome the expired bound
+ *
+ * The window must still cover the legitimate pin-late retry (observed
+ * pin latency 0.5-2 s: the H2D copy's operands land a moment after the
+ * push, r507 matmul's 1 MB UVA copy at 0x7136... needed >8 fast passes),
+ * so the latch is TIME-based: the FIRST failure of a VA arms a
+ * SVC_OPDEF_HOLD_MS window during which the op holds its entry exactly as
+ * before; after a full bound with no success the op still attempts the
+ * write but no longer forces the hold - the entry consumes promptly and
+ * its withheld release applies, exactly the outcome the expired bound
* already sanctioned (op stays skipped, release delivered), minus the
- * 10 s tax per pass. Service-thread only, like every other op path.
+ * 10 s tax per subsequent pass. A success clears the record (a later
+ * failure gets a fresh window). Service-thread only, like every other op
+ * path.
+ */
+#define SVC_OPFAIL_MAX 32
+/*
+ * r507a: the op-failure window rides the opdef hold bound (10000 ms,
+ * SVC_OPDEF_HOLD_MS defined further down). Keep the literal here so the
+ * latch (used by svc_run_ops) precedes that define.
*/
-#define SVC_OPFAIL_LATCH 8
-#define SVC_OPFAIL_MAX 16
+#define SVC_OPFAIL_WINDOW_MS 10000u
static struct {
u64 va;
- u32 n;
+ unsigned long since;
} svc_opfail[SVC_OPFAIL_MAX];
static u32 svc_opfail_log;
+static void svc_opfail_clear(u64 va)
+{
+ u32 i;
+
+ for (i = 0; i < SVC_OPFAIL_MAX; i++)
+ if (svc_opfail[i].va == va)
+ svc_opfail[i].va = 0;
+}
+
static bool svc_opfail_latched(u64 va)
{
u32 i;
@@ -7556,21 +7578,24 @@ static bool svc_opfail_latched(u64 va)
for (i = 0; i < SVC_OPFAIL_MAX; i++) {
if (svc_opfail[i].va == va) {
- svc_opfail[i].n++;
- if (svc_opfail[i].n == SVC_OPFAIL_LATCH &&
- svc_opfail_log < 32) {
- svc_opfail_log++;
- pr_info("sema-svc: OPFAIL-LATCH va=0x%llx n=%u (op no longer holds its entry)\n",
- va, svc_opfail[i].n);
+ if (time_after_eq(jiffies,
+ svc_opfail[i].since +
+ msecs_to_jiffies(SVC_OPFAIL_WINDOW_MS))) {
+ if (svc_opfail_log < 32) {
+ svc_opfail_log++;
+ pr_info("sema-svc: OPFAIL-LATCH va=0x%llx (>=%u ms of failures; op no longer holds its entry)\n",
+ va, SVC_OPFAIL_WINDOW_MS);
+ }
+ return true;
}
- return svc_opfail[i].n >= SVC_OPFAIL_LATCH;
+ return false;
}
if (!svc_opfail[i].va && free_i == SVC_OPFAIL_MAX)
free_i = i;
}
if (free_i < SVC_OPFAIL_MAX) {
svc_opfail[free_i].va = va;
- svc_opfail[free_i].n = 1;
+ svc_opfail[free_i].since = jiffies;
}
return false;
}
@@ -7832,9 +7857,11 @@ svc_wait_done:
*/
if (rc == SVC_COPY_FORWARDED)
continue;
- if (rc == 0)
+ if (rc == 0) {
svc.memsets_done++;
- else if (rc == -ENOENT)
+ /* r507a: a success re-arms the failure window. */
+ svc_opfail_clear(m->dst);
+ } else if (rc == -ENOENT)
svc.memsets_nomap++;
else
svc.memsets_fail++;