diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_sema_service.c | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index af4534b..471f5ae 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -30528,6 +30528,8 @@ int gsp_sema_service_add_map(u64 gpu_va, u64 pa, u64 len, u32 ap) */ static u64 svc_xw_cnt_pa; static u64 svc_xw_mem_pa; +static u32 svc_xw_last_c; /* last counter read (delta learning) */ +static u32 svc_xw_delta; /* last observed per-frame counter step */ static struct task_struct *svc_xw_task; static int svc_xw_mirror_loop(void *unused) @@ -30549,9 +30551,31 @@ static int svc_xw_mirror_loop(void *unused) &c, sizeof(c)) && !svc_read_ap(vgpu, svc_xw_mem_pa, SVC_APERTURE_SYS, &cur, sizeof(cur))) { - u32 m = (cur & 0xfffc0000u) | - ((c >> 2) & 0x3ffffu); - + u32 m; + /* + * SESSION 148 (r866): write the member one learned + * frame-step AHEAD of the counter. The driver's + * frame path increments its counter and *then* + * enters the wait; a member that only tracks the + * counter therefore always loses that entry-check + * race (mirror latency > driver gap) and each wait + * pays the driver's ~3 s re-check sleep - measured + * as one "(0)" success print every 20-80 s and a + * client hanging on its X socket for minutes. + * With member = counter + last-delta the driver's + * check succeeds on the FIRST probe after its own + * increment (the increment lands exactly on the + * pre-written value), so frames complete at the + * driver's own pace. Delta is learned from each + * observed counter change; 0 until the first change. + */ + if (c != svc_xw_last_c) { + if (svc_xw_last_c) + svc_xw_delta = c - svc_xw_last_c; + svc_xw_last_c = c; + } + m = (cur & 0xfffc0000u) | + (((u64)(c + svc_xw_delta) >> 2) & 0x3ffffu); if (m != cur) svc_write_ap(vgpu, svc_xw_mem_pa, SVC_APERTURE_SYS, &m, sizeof(m)); |
