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.c95
1 files changed, 54 insertions, 41 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 2127f38..7475ea7 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -3671,6 +3671,39 @@ static void svc_counter_publish(struct nv_vgpu_device *vgpu,
ch->h_object, ch->counter_pa, val);
}
+/*
+ * Acknowledge a CE tracking-semaphore release without reading the push that
+ * carried it: write the expected payload into the semaphore the channel last
+ * released to (learned from a readable push; the pool index is allocated by
+ * UVM and does not match the channel rank). Returns false when there is
+ * nothing to fall back on. Caller owns expected_sem_payload bookkeeping.
+ */
+static bool svc_fake_release(struct nv_vgpu_device *vgpu, struct svc_channel *ch)
+{
+ u64 pool_va;
+ u64 spa = 0;
+ int sap = SVC_APERTURE_SYS;
+ u32 scur = 0;
+
+ if (!ch->engine_type || !ch->expected_sem_payload)
+ return false;
+
+ 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) {
+ u32 nv = ch->expected_sem_payload;
+
+ if (!svc_write_ap(vgpu, spa, sap, &nv, sizeof(nv)))
+ svc.releases_applied++;
+ }
+ svc.releases_faked++;
+ ch->expected_sem_payload++;
+ return true;
+}
+
static void svc_pump_channels(struct nv_vgpu_device *vgpu)
{
/* Only ever called from the service thread. */
@@ -3837,6 +3870,24 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
* its whole slot.
*/
svc_log_stalled_va(va);
+ /*
+ * With the fallback enabled the rescue
+ * is pointless for CE: it never
+ * executes the work anyway (only the
+ * release), and its multi-second RAM
+ * scan is what made the driver's
+ * progress waits expire. Acknowledge
+ * the release and move on.
+ */
+ if (gsp_sema_fake_rel &&
+ svc_fake_release(vgpu, ch)) {
+ ch->last_get = (idx + 1) %
+ ch->gpfifo_entries;
+ svc.gpfifo_skipped++;
+ stalled = true;
+ kfree(pb);
+ continue;
+ }
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);
@@ -3915,47 +3966,9 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
ch->h_object, va, len,
ch->rescue_fail);
ch->rescue_fail = 0;
- /*
- * The entry carried a tracking-
- * semaphore release we could not
- * read. Acknowledge it the way the
- * GPU would so the driver's wait
- * clears in one pass.
- */
- if (gsp_sema_fake_rel &&
- ch->engine_type &&
- ch->expected_sem_payload) {
- u64 pool_va =
- ch->last_rel_va ?
- ch->last_rel_va :
- 0x121000000ULL +
- 4ULL * ch->ce_index;
- u64 spa = 0;
- int sap =
- SVC_APERTURE_SYS;
- u32 scur = 0;
-
- if (!svc_lookup_trusted(
- vgpu,
- pool_va,
- &spa,
- &sap) &&
- !svc_read_ap(vgpu,
- spa, sap,
- &scur,
- sizeof(scur)) &&
- scur < ch->expected_sem_payload) {
- u32 nv =
- ch->expected_sem_payload;
-
- if (!svc_write_ap(vgpu,
- spa, sap,
- &nv,
- sizeof(nv)))
- svc.releases_applied++;
- }
- svc.releases_faked++;
- }
+ if (gsp_sema_fake_rel)
+ svc_fake_release(vgpu,
+ ch);
ch->last_get = (idx + 1) %
ch->gpfifo_entries;
svc.gpfifo_skipped++;