summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/gsp_sema_service.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index d9c1387..1c6c41a 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -4643,6 +4643,38 @@ static void svc_counter_release_apply(struct nv_vgpu_device *vgpu, u32 h,
spin_unlock_irqrestore(&svc.chan_lock, flags);
if (!pa) {
/*
+ * Pool (UVM tracking) semaphores have no counter slot. The
+ * launch path normally writes them through the generic pool
+ * resolver, but it skips the write whenever it believes the
+ * release was already applied (or the word was unreadable at
+ * decode time). A decoded pool release must never be dropped
+ * here: apply it forward-only absolute through the pool
+ * writer - writing the payload when it is ahead of the word
+ * is idempotent for a monotonic tracker, so a duplicate can
+ * never double-count (ISSUE-0002: second-session releases
+ * were lost here and the guest waited forever).
+ */
+ if (svc_pool_sem_va(sem_va)) {
+ u32 pcur = 0;
+ int wrc;
+
+ if (svc_sem_read(vgpu, sem_va, &pcur))
+ return;
+ if (payload <= pcur)
+ return;
+ wrc = svc_sem_write(vgpu, h, sem_va, payload);
+ if (!wrc) {
+ svc.releases_applied++;
+ svc.post_hint_until = jiffies + 10 * HZ;
+ if (gsp_sema_dbg && svc.counter_rel_dbg < 256) {
+ svc.counter_rel_dbg++;
+ pr_info("sema-chan: rel-apply h=0x%x va=0x%llx pay=%u cur=%u -> pool rescue\n",
+ h, sem_va, payload, pcur);
+ }
+ }
+ return;
+ }
+ /*
* Still no slot: remember the payload so the slot
* registration (learn/auto/publish) flushes it. Dropping it
* leaves the client's tracker polling a value that never