summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-27 17:05:10 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-27 17:05:10 -0400
commit00319db208aa8fa90b6ad03ef154815ed86d8225 (patch)
treeaa7c31f2cd99b3d9882f351188c915d0b67d192f
parent28c8c8e9635a072abe52b08b30b6d9607cfb0768 (diff)
downloadopen-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.
-rw-r--r--kernel/gsp_sema_service.c30
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));