summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_sema_service.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 3692246..309210d 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -7714,6 +7714,36 @@ static int svc_chan_userd(struct nv_vgpu_device *vgpu, struct svc_channel *ch,
int ring_alt = ring_ap == SVC_APERTURE_FB ? SVC_APERTURE_SYS
: SVC_APERTURE_FB;
+ /*
+ * ISSUE-0002 (r40): prefer the layout-derived CE USERD and accept it
+ * while it is still idle. In a second session the registered userdMem
+ * offset (pool-relative, see below) aliases a DIFFERENT rank's real
+ * USERD whose stale put/get from the previous session won the
+ * coherent-pair probe while this channel's true block was still 0/0:
+ * c2 rank0 read rank3's stale 1/1 at FB 0xf0000 and the pump never
+ * followed rank0's own GP_PUT. The true CE USERD sits at
+ * ring + 0x10000 in the ring's aperture - confirmed by the guest
+ * CPU mapping of gpFifoGpuVa (GPU VA gpfifo+0x20000 maps to BAR
+ * offset ring+0x10000) and by every CE rank that resolved correctly.
+ * An idle (0/0) read is accepted here because the guest writes the
+ * block on the channel's first push; only unreadable or incoherent
+ * candidates fall through to the old list.
+ */
+ if (ring_pa && ch->engine_type != 0) {
+ u32 p = 0, g = 0;
+ int rc = svc_userd_probe(vgpu, ring_pa + 0x10000, ring_ap,
+ ch->gpfifo_entries, &p, &g);
+
+ if (rc == 0 || rc == -EAGAIN) {
+ ch->userd_pa = ring_pa + 0x10000;
+ ch->userd_as = ring_ap;
+ ch->userd_ok = true;
+ *put = p;
+ *get = g;
+ return 0;
+ }
+ }
+
if (ring_pa) {
cand[nc] = ring_pa + 0x2000; as[nc++] = ring_ap;
cand[nc] = ring_pa + 0x2000; as[nc++] = ring_alt;