diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_sema_service.c | 30 |
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); } |
