From 5c9d18abaac6ce45c8faec26b3f3b637cd764eb5 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Thu, 24 Sep 2026 02:29:04 -0400 Subject: kernel: completion-event hints and GSP-RM state introspection - re-post the completion event for a bounded window after a channel completes work (notifier consumed or semaphore release applied), so a client that starts waiting after the edge-triggered wake-up still gets a wake-up; the OS event classes carry no source object, so the hint broadcasts to the registered events - add rmstate (dump msgq cursors, guest consumption position, event table) and rmpost (post an event record by index or to all) debug parameters, both executing in kthreads because the IOMMU read path only works with a NULL current->mm or the mapping owner's mm - report the underlying error codes from the event post path --- kernel/gsp_sema_service.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'kernel/gsp_sema_service.c') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 10d6b80..b66cfd7 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -190,6 +190,15 @@ struct sema_svc { u64 last_build; u64 last_scan; + /* + * Completion hint window: after a channel completes work the client is + * waiting on, keep re-posting the event for a few seconds. A client + * that starts waiting after the completion would otherwise lose the + * (edge-triggered) wake-up. + */ + u64 post_hint_until; + u64 last_hint; + /* registered guest channels (GPFIFO-driven push execution) */ spinlock_t chan_lock; struct svc_channel chan[SVC_MAX_CHANNELS]; @@ -1642,6 +1651,7 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, cur + payload : payload; if (!svc_sem_write(vgpu, va, cur)) svc.releases_applied++; + svc.post_hint_until = jiffies + 10 * HZ; } } off += 4 + count * 4; @@ -1701,6 +1711,7 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, if (!svc_sem_write(vgpu, va, st.rs_payload)) svc.releases_applied++; + svc.post_hint_until = jiffies + 10 * HZ; break; } default: @@ -1825,6 +1836,7 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, cur = st.sem_payload; if (!svc_sem_write(vgpu, sem_va, cur)) svc.releases_applied++; + svc.post_hint_until = jiffies + 10 * HZ; } /* release ends the push */ n_ops = 0; @@ -1928,6 +1940,7 @@ static u32 svc_apply_page_data(struct nv_vgpu_device *vgpu, const u8 *buf, if (svc_sem_write(vgpu, va, payload) == 0) { svc.releases_applied++; + svc.post_hint_until = jiffies + 10 * HZ; applied++; if (payload != cur + 1) { svc.releases_jumped++; @@ -2212,6 +2225,10 @@ static void svc_notify_complete(struct nv_vgpu_device *vgpu, * thread waits on (a real GPU would raise an interrupt here). */ gsp_rm_post_channel_event(vgpu, ch->h_object); + + /* Keep the completion visible to clients that start waiting + * after the event fired. */ + svc.post_hint_until = jiffies + 10 * HZ; } } @@ -2525,6 +2542,21 @@ static int svc_thread(void *arg) svc.doorbell_pending = false; svc_pump_channels(vgpu); + /* + * Completion hint: re-post the events for a few seconds after a + * completion, so a client that starts waiting after the + * edge-triggered wake-up still observes it. + */ + if (time_before(jiffies, (unsigned long)svc.post_hint_until) && + time_after(jiffies, (unsigned long)svc.last_hint + HZ / 2)) { + int rc; + + svc.last_hint = jiffies; + rc = gsp_rm_post_all_events(vgpu); + pr_info_ratelimited("sema-svc: completion hint rc=%d\n", + rc); + } + /* * Fast path for the pushes themselves: every mapped page is a * candidate pushbuffer page, and there are far fewer of those -- cgit v1.2.3