summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/gsp_sema_service.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index fa76162..e972732 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -13130,6 +13130,33 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
if (ch->userd_wait_fresh) {
ch->last_get = 0;
ch->userd_wait_fresh = false;
+ } else if (ch->engine_type && ch->gpfifo_entries &&
+ ch->last_get > put &&
+ ch->submissions < ch->gpfifo_entries / 2) {
+ /*
+ * ISSUE-0002 (r73): a SECOND (or later) drop
+ * while the channel is still fresh. The
+ * discovery-time put was residual (the previous
+ * session's counter, e.g. 67) and the pump had
+ * already consumed the live entries 0..k; the
+ * guest's counter then settled at a value below
+ * the pump's read position (r73 rank2: put=1
+ * with last_get=2 after the r48 resync). The
+ * loop condition last_get != put then marches
+ * forward through ~1023 slots the producer has
+ * not written in this epoch, holding each
+ * unreadable stale entry for the full CE grace
+ * (one fake release per 8 s) - the client
+ * appears wedged. Never stay ahead of the
+ * producer: rewind to its position. A genuine
+ * ring wrap cannot be fresh (it needs a full
+ * ring of submissions), so this cannot skip a
+ * live entry.
+ */
+ pr_info_ratelimited("sema-chan: fresh put drop h=0x%x rank=%u put=%u last=%u -> rewind\n",
+ ch->h_object, ch->ce_index, put,
+ (u32)ch->last_get);
+ ch->last_get = put;
}
bitmap_zero(ch->slot_done_epoch, SVC_GPFIFO_MAX_BITS);
}