summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/gsp_sema_service.c69
1 files changed, 59 insertions, 10 deletions
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++;