summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_rm_emulation.c16
-rw-r--r--kernel/gsp_sema_service.c57
2 files changed, 69 insertions, 4 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c
index 4420810..0cef9e7 100644
--- a/kernel/gsp_rm_emulation.c
+++ b/kernel/gsp_rm_emulation.c
@@ -903,6 +903,22 @@ static int gsp_rm_post_channel_event_common(struct nv_vgpu_device *vgpu,
if (!rm->events[i].valid || rm->events[i].h_src != h_src)
continue;
+ /*
+ * r1780: the directly-associated post is the flood path. The
+ * X channel's completion edge fires per consumed submission and
+ * the 48/s burst cap then drops the wake-ups a blocked client is
+ * waiting for (live: "event burst capped (48/48), dropped
+ * total=3000", DDX "Failed to idle DMA"). A re-post within
+ * GSPRM_EVENT_HINT_DEDUP adds no wake-up - the client re-reads
+ * channel state on any event and the 0.5 s hint re-posts late
+ * waiters - so apply the dedup the fallback loop already uses.
+ */
+ if (!force &&
+ time_before(jiffies,
+ rm->events[i].last_post +
+ GSPRM_EVENT_HINT_DEDUP))
+ continue;
+
gsp_rm_fill_ev_payload(rm, i, payload);
{
int rc = gsp_rm_send_flags(ctx, gsp_rm_ev_function(),
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 7e389f8..96e135b 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -43835,6 +43835,35 @@ static void svc_gr_util_sweep(struct nv_vgpu_device *vgpu,
svc_gr_util_sweep_n(vgpu, ch, 0);
}
+/*
+ * Wrap-aware PUT progress for the speculative latch.
+ *
+ * A USERD adopted by the FB/VRAM shape scan carries GPFIFO ring indices in
+ * [0, entries] (the shape gate rejects put > entries; `entries` is the
+ * wrapped/empty value). Such a producer legitimately wraps entries -> 0:
+ * h=0x1000013 (ent=65536, latch=65536) later reads put=12, and the raw
+ * `put > latch` judge saw a decrease, rejected the live block and cleared
+ * userd_ok - the X/DDX channel then waited forever in "Failed to idle
+ * DMA". For that class compare modulo entries (entries is a power of two):
+ * a step of 1..entries/2 is forward progress; anything else (backward
+ * jump or more than half the ring) keeps the old reject path.
+ *
+ * Channels whose PUT is a free-running counter keep the raw comparison:
+ * the guest-RAM scan (SYS aperture, gr_ram_ring) explicitly admits puts
+ * far above entries (measured put=12 with entries=2 and put=16 with
+ * entries=32768), the kick family (0xbfef00xx) authors its own free-
+ * running count, and a non-power-of-two ring has no usable mask. A
+ * one-slot ring is excluded too: every put aliases, so there is no
+ * modulo progress to measure.
+ */
+static bool svc_userd_put_wrap(const struct svc_channel *ch)
+{
+ u32 entries = ch->gpfifo_entries;
+
+ return entries >= 2 && !(entries & (entries - 1)) &&
+ ch->userd_as == SVC_APERTURE_FB && !svc_kick_family(ch);
+}
+
static void svc_pump_channels(struct nv_vgpu_device *vgpu)
{
if (svc_pdb_disc_pending) {
@@ -44665,6 +44694,12 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
(!ch->gr_ram_userd_confirmed ||
(kfam && put < ch->gr_ram_userd_latch_put))) {
bool stepped;
+ bool wrap = svc_userd_put_wrap(ch);
+ u32 wstep = wrap ?
+ (put - ch->gr_ram_userd_latch_put) &
+ (ch->gpfifo_entries - 1) : 0;
+ bool moved = wrap ? wstep != 0 :
+ put != ch->gr_ram_userd_latch_put;
if (!ch->gr_ram_userd_latch_at)
ch->gr_ram_userd_latch_at = jiffies;
@@ -44678,10 +44713,25 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
* at ~10 Hz. A forward jump is not evidence of a
* stale latch: only a decrease (wrong actor / reused
* block) or the 15 s no-advance bound is.
+ *
+ * WRAP-FIX: for a ring-index PUT (FB shape scan,
+ * power-of-two entries) "forward" is modulo entries.
+ * h=0x1000013 legitimately wrapped 65536 -> 12 and
+ * the raw compare rejected the live block; see
+ * svc_userd_put_wrap().
*/
- stepped = put > ch->gr_ram_userd_latch_put;
+ stepped = wrap ?
+ (wstep && wstep <= ch->gpfifo_entries / 2) :
+ put > ch->gr_ram_userd_latch_put;
if (stepped) {
ch->gr_ram_userd_confirmed = true;
+ if (wrap &&
+ put < ch->gr_ram_userd_latch_put)
+ pr_info_ratelimited("sema-chan: GR USERD h=0x%x pa=0x%llx speculative latch wrap accepted (put %u latch %u ent %u step %u)\n",
+ ch->h_object, ch->userd_pa,
+ put,
+ ch->gr_ram_userd_latch_put,
+ ch->gpfifo_entries, wstep);
pr_info("sema-chan: GR USERD h=0x%x pa=0x%llx speculative latch CONFIRMED (put %u -> %u)\n",
ch->h_object, ch->userd_pa,
ch->gr_ram_userd_latch_put, put);
@@ -44718,7 +44768,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
}
ch->gr_ram_userd_latch_put = put;
ch->gr_ram_userd_latch_at = jiffies;
- } else if (put != ch->gr_ram_userd_latch_put ||
+ } else if (moved ||
time_after(jiffies,
ch->gr_ram_userd_latch_at +
msecs_to_jiffies(15000))) {
@@ -44728,8 +44778,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
pr_info("sema-chan: GR USERD h=0x%x pa=0x%llx speculative latch REJECTED (put=%u latch=%u%s)\n",
ch->h_object, ch->userd_pa, put,
ch->gr_ram_userd_latch_put,
- put != ch->gr_ram_userd_latch_put ?
- "" : " no advance in 15 s");
+ moved ? "" : " no advance in 15 s");
/*
* SESSION 153-CONT-5: one stale window must not
* kill the pipeline. Remember the rejected