summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_sema_service.c')
-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 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;
}
}
@@ -2526,6 +2543,21 @@ static int svc_thread(void *arg)
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
* than there are pages of guest RAM.