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.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 40926ee..020023a 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -3452,11 +3452,14 @@ static u64 map_add_pa;
static u64 map_add_len;
static u32 map_add_ap;
static bool map_add_pending;
+#define SVC_PIN_REWIND 8
static void svc_handle_map_add(void)
{
u32 ap = map_add_ap ? map_add_ap : SVC_APERTURE_SYS;
+ unsigned long flags;
u64 off;
+ int i;
if (!map_add_pending)
return;
@@ -3467,14 +3470,37 @@ static void svc_handle_map_add(void)
svc_lat_store(map_add_va + off, map_add_pa + off, ap);
}
/*
+ * A translation can be replaced after the pump already consumed
+ * pushes that release through it (a new client maps new physical
+ * pages at the same VA, or the first translation was wrong): the
+ * releases resolved against the old page, compared as stale against
+ * its values, and were dropped. Rewind every channel a few ring
+ * entries so those pushes are re-read under the new translation;
+ * the release/fill application paths are forward-progress guarded,
+ * so re-executing them is idempotent.
+ */
+ spin_lock_irqsave(&svc.chan_lock, flags);
+ for (i = 0; i < SVC_MAX_CHANNELS; i++) {
+ struct svc_channel *ch = &svc.chan[i];
+ u32 get;
+
+ if (!ch->valid || !ch->gpfifo_entries)
+ continue;
+ get = ch->last_get;
+ ch->last_get = (get >= SVC_PIN_REWIND) ? get - SVC_PIN_REWIND :
+ ch->gpfifo_entries - (SVC_PIN_REWIND - get);
+ }
+ spin_unlock_irqrestore(&svc.chan_lock, flags);
+
+ /*
* Releases that missed translation before this injection may be
* applicable now: keep the fast full-RAM sweep armed for a few
* seconds so they land without waiting for an unrelated stall.
*/
svc.fast_force_until = jiffies + 10 * HZ;
- pr_info("sema-svc: injected mapping va=0x%llx -> pa=0x%llx len=0x%llx (%s)\n",
+ pr_info("sema-svc: injected mapping va=0x%llx -> pa=0x%llx len=0x%llx (%s), rewound channels by %u\n",
map_add_va, map_add_pa, map_add_len,
- ap == SVC_APERTURE_FB ? "vidmem" : "sysmem");
+ ap == SVC_APERTURE_FB ? "vidmem" : "sysmem", SVC_PIN_REWIND);
map_add_pending = false;
complete(&map_add_done);
}