diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_sema_service.c | 32 |
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 |
