From a6cee384160b3210911838f79a8082d541da00f5 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Tue, 29 Sep 2026 16:20:42 -0400 Subject: sema-svc: never consume a CE entry whose release was not delivered The fake-release fallback acknowledged unreadable CE pushes even when the tracking-semaphore pool page had no translation yet, so the GPFIFO entry was consumed without writing the semaphore the client waits on (observed: client stuck in UVM_GPU_REGISTER while CE channel 2's release never landed, its push-buffer pin arriving ~2 s later). - svc_fake_release now reports failure when the pool page cannot be translated/read/written instead of pretending success. - CE channels with the fallback enabled leave the entry pending (no multi-second RAM rescue) until the pool pin lands; the skip path only consumes an entry when the release was actually delivered. --- kernel/gsp_sema_service.c | 69 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 10 deletions(-) (limited to 'kernel/gsp_sema_service.c') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 5bff6ca..21f0de0 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -3990,13 +3990,24 @@ static bool svc_fake_release(struct nv_vgpu_device *vgpu, struct svc_channel *ch pool_va = ch->last_rel_va ? ch->last_rel_va : 0x121000000ULL + 4ULL * ch->ce_index; - if (!svc_lookup_trusted(vgpu, pool_va, &spa, &sap) && - !svc_read_ap(vgpu, spa, sap, &scur, sizeof(scur)) && - scur < ch->expected_sem_payload) { + /* + * The release can only be delivered when the pool page translates. + * A missing translation is transient (the client's pool page is pinned + * a moment after the channel appears), so report failure and let the + * caller keep the GPFIFO entry pending: consuming it without writing + * the semaphore leaves the client waiting forever. + */ + if (svc_lookup_trusted(vgpu, pool_va, &spa, &sap)) + return false; + if (svc_read_ap(vgpu, spa, sap, &scur, sizeof(scur))) + return false; + + if (scur < ch->expected_sem_payload) { u32 nv = ch->expected_sem_payload; - if (!svc_write_ap(vgpu, spa, sap, &nv, sizeof(nv))) - svc.releases_applied++; + if (svc_write_ap(vgpu, spa, sap, &nv, sizeof(nv))) + return false; + svc.releases_applied++; } svc.releases_faked++; ch->expected_sem_payload++; @@ -4212,8 +4223,8 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) * progress waits expire. Acknowledge * the release and move on. */ - if (gsp_sema_fake_rel && - svc_fake_release(vgpu, ch)) { +if (gsp_sema_fake_rel && + svc_fake_release(vgpu, ch)) { ch->last_get = (idx + 1) % ch->gpfifo_entries; svc.gpfifo_skipped++; @@ -4221,6 +4232,29 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) kfree(pb); continue; } + if (gsp_sema_fake_rel && + ch->engine_type) { + /* + * CE channel and the + * pool page is not + * translated yet: the + * pin lands a moment + * later, so keep the + * entry pending + * instead of burning a + * multi-second RAM + * rescue. Consuming it + * now would drop the + * release the client + * waits on. + */ + if (!ch->defer_since) + ch->defer_since = + jiffies; + svc.gpfifo_nomap++; + kfree(pb); + break; + } if (svc.false_trans && svc.false_trans < 8) pr_info("sema-svc: false translation for push va=0x%llx (h=0x%x len=%u) - rescuing\n", va, ch->h_object, len); @@ -4305,11 +4339,26 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) pr_info("sema-chan: skipping stale entry h=0x%x va=0x%llx len=%u after %u failed rescues\n", ch->h_object, va, len, ch->rescue_fail); + if (gsp_sema_fake_rel && + !svc_fake_release(vgpu, ch)) { + /* + * The release could not be + * delivered (pool page not + * translated yet): keep the + * entry pending so a pin that + * lands shortly still applies + * it instead of silently + * dropping the client's wait. + */ + if (!ch->defer_since) + ch->defer_since = + jiffies; + svc.gpfifo_nomap++; + kfree(pb); + break; + } ch->rescue_fail = 0; ch->defer_since = 0; - if (gsp_sema_fake_rel) - svc_fake_release(vgpu, - ch); ch->last_get = (idx + 1) % ch->gpfifo_entries; svc.gpfifo_skipped++; -- cgit v1.2.3