summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/gsp_sema_service.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 075a429..77ae4b4 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -4613,6 +4613,23 @@ static void svc_run_ops(struct nv_vgpu_device *vgpu, struct svc_memset_op *ops,
svc.memsets_nomap++;
else
svc.memsets_fail++;
+ /*
+ * ISSUE-0002 (r71): ANY failed op leaves work owed on this
+ * entry, not only an unresolvable operand. The pma scrub
+ * memsets resolve a bogus out-of-bounds vidmem destination
+ * through a walk before the scanner pins the real sysmem
+ * page; svc_copy fails them with -EINVAL, and the old code
+ * consumed the entry and applied the release anyway, leaving
+ * the client frozen in scrubCheckAndWaitForSize. Mark the
+ * pass as op-pending so the pump holds the entry and
+ * withholds its releases (bounded by SVC_OPDEF_HOLD_MS,
+ * exactly like the -ENOENT path): the retried decode checks
+ * the injected pins first and runs the memset once the real
+ * translation lands. On expiry the release is flushed and the
+ * op stays skipped (the pre-r62 fallback).
+ */
+ if (rc != 0 && rc != SVC_COPY_FORWARDED)
+ svc.op_tr_pending = 1;
if (gsp_sema_dbg && m->bytes == 256 && svc.sem256_log < 64) {
svc.sem256_log++;
pr_info("sema-256: type=%u dst=0x%llx src=0x%llx bytes=%llu rc=%d h=0x%x done=%llu nomap=%llu fail=%llu\n",