From be6e5ee20e50b3109b74bdd9c18f15f8f8c3f724 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Fri, 9 Oct 2026 21:16:49 -0400 Subject: vgsp-sema: re-seed and apply the first release of a fresh CE channel when the pool word is residue (ISSUE-0002) A fresh session's first CE release could read a previous session's value through the just-injected pool pin (r64: cur=134 pay=1; r63: cur=114696). svc_init_expected_payload seeded the channel expectation from that residue, the release candidate then skipped as stale (payload <= cur) and the client's first tracker wait never completed. When the first GPFIFO entry of a fresh CE channel (submissions == 0) decodes a pool release whose word reads ahead of the payload, treat the word as residue: re-seed expected_sem_payload/entry_want from the payload and apply the release absolute instead of skipping. Monotonic trackers make the absolute write idempotent; displaced pins stay owned by the fan-out/pending paths. Bounded 'sema-chan: pool residue' diagnostic plus a residue counter in the drain line. --- kernel/gsp_sema_service.c | 67 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) (limited to 'kernel') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 77a1fae..d69be19 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -573,6 +573,14 @@ struct sema_svc { u64 sem_write_reresolve; /* writes re-resolved after read-back */ u64 pool_alt_applied; /* pool releases fanned to a * displaced pin (ISSUE-0002) */ + u64 pool_residue; /* fresh-channel first releases whose + * pool word read far ahead of the + * payload (previous session's + * value in a reused pool page); + * re-seeded from the payload and + * applied instead of skipped as + * stale (ISSUE-0002 r63/r64) */ + u64 pool_residue_log; /* residue diagnostic budget */ u64 pushpg_fallback; /* injected pin rejected by content */ u64 gpfifo_skipped; /* stale entries consumed */ u64 gpfifo_rescued; /* unreadable push made readable @@ -3287,10 +3295,10 @@ static void svc_rebuild(struct nv_vgpu_device *vgpu) svc.releases_faked, svc.releases_recovered, svc.ops_once_skipped, svc.ops_reident, svc.opdef_held, svc.opdef_applied, svc.opdef_expired); - pr_info("sema-svc: counter pub_calls=%llu gr_rel=%llu reresolve=%llu pushpg_fb=%llu altw=%llu\n", + pr_info("sema-svc: counter pub_calls=%llu gr_rel=%llu reresolve=%llu pushpg_fb=%llu altw=%llu residue=%llu\n", svc.counter_pub_calls, svc.gr_rel_applied, svc.sem_write_reresolve, svc.pushpg_fallback, - svc.pool_alt_applied); + svc.pool_alt_applied, svc.pool_residue); if (svc.resc_run) pr_info("sema-svc: rescue_run=%llu (multi-page content pins)\n", svc.resc_run); @@ -6494,6 +6502,61 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, (DMA_SEM_REDUCTION_EN(dma) && DMA_SEM_REDUCTION(dma) == SEM_REDUCTION_INC) ? 1 : 0); + } else if (svc_pool_sem_va(sem_va) && + ch && ch->engine_type && + !ch->submissions && + cur > st.sem_payload) { + /* + * ISSUE-0002 (r63/r64): the + * first GPFIFO entry of a + * fresh CE channel carries + * the release that starts + * the channel's tracker. + * When the pool word + * already reads far ahead + * of the decoded payload + * through the injected pin, + * the word cannot be this + * session's live tracker + * (no entry of this channel + * has executed yet): it is + * the previous session's + * value in a reused pool + * page. svc_init_expected_ + * payload seeded the + * expectation from that + * residue, so the release + * was skipped as stale + * (payload <= cur) and the + * client's first tracker + * wait never completed + * (r64: cur=134, pay=1; + * r63: cur=114696). + * Re-seed the expectation + * from the payload and + * apply it absolute: for a + * monotonic tracker that is + * the exact value the + * client polls, and the + * fan-out/pending paths + * still own any displaced + * pin. + */ + ch->expected_sem_payload = + st.sem_payload; + ch->entry_want = st.sem_payload; + have_cur = true; + pending = 1; + svc.pool_residue++; + if (svc.pool_residue_log < 32) { + svc.pool_residue_log++; + pr_info("sema-chan: pool residue h=0x%x rank=%u va=0x%llx pay=%u cur=%u -> re-seed + apply (fresh channel)\n", + ch->h_object, + ch->ce_index, + sem_va, + st.sem_payload, + cur); + } } else if (svc_pool_sem_va(sem_va) && (svc_pool_hold_active() || !cur)) { /* -- cgit v1.2.3