diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-27 17:05:10 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-27 17:05:10 -0400 |
| commit | 00319db208aa8fa90b6ad03ef154815ed86d8225 (patch) | |
| tree | aa7c31f2cd99b3d9882f351188c915d0b67d192f /kernel/gsp_sema_service.c | |
| parent | 28c8c8e9635a072abe52b08b30b6d9607cfb0768 (diff) | |
| download | open-iov-00319db208aa8fa90b6ad03ef154815ed86d8225.tar.gz open-iov-00319db208aa8fa90b6ad03ef154815ed86d8225.zip | |
vgsp: xw-mirror writes one learned frame-step ahead of the counter
r866: the mirror tracked perfectly yet every wait still paid the driver's
~3 s re-check sleep (one '(0)' success print every 20-80 s; the GL client
hung minutes on its X socket). Cause: the driver increments its counter
and then enters the wait; a member that only tracks the counter always
loses that entry-check race (mirror wakes <=3 ms after the change; the
driver probes within microseconds), so the check fails and the driver
sleeps out its retry interval. Writing member = counter + last-observed-
delta (learned from each counter change, 0 until the first) makes the
driver's own increment land exactly on the pre-written member value, so
the first probe after submission succeeds and frames complete at the
driver's pace.
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -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)); |
