summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_sema_service.c')
-rw-r--r--kernel/gsp_sema_service.c32
1 files changed, 18 insertions, 14 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index dc4b7b1..48c070b 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -120,6 +120,18 @@ struct sema_map_entry {
/* ------------------------------------------------------------------ */
#define SVC_MAX_CHANNELS 128
+/*
+ * Fixed GR completion-counter pool total for the emulated device profile:
+ * the client allocates this many GR channels and zips them in ascending
+ * handle order onto descending 0x10-byte counter slots, so rank r owns
+ * slot 0x20400fec0 + (TOTAL-1-r)*0x10. The live channel count must never
+ * be used here: channels register progressively, and an early pass with a
+ * partial count claims the slots that the full mapping needs for later
+ * ranks (observed: ranks 6..9 installed at the n_gr=16 mapping, then every
+ * later rank's correct slot was already owned and rejected, no GR counter
+ * was ever published and the client's tracker never advanced).
+ */
+#define SVC_GR_COUNTER_TOTAL 20
#define SVC_GPFIFO_ENTRY_SIZE 8
/* GPFIFO slots tracked for the increment-release one-shot bitmap. The rings
* are 1024 entries in practice; the cap only bounds the per-channel state. */
@@ -10357,31 +10369,23 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
/* Only ever called from the service thread. */
static struct svc_channel local[SVC_MAX_CHANNELS];
/*
- * Total GR channels the client ever had in the current generation.
- * The counter-slot layout is fixed when the client allocates all its
- * channels, so the slot must not be recomputed with a shrinking live
- * count (a teardown pass would re-target the wrong slot).
+ * Fixed GR counter pool total (see SVC_GR_COUNTER_TOTAL). The live
+ * count grows as the client registers channels, so it must not be
+ * used to derive counter slots: an early pass with a partial count
+ * poisons every later rank's slot.
*/
- static int svc_gr_max;
unsigned long flags;
int i, k, n = 0, n_gr = 0;
bool stalled = false;
spin_lock_irqsave(&svc.chan_lock, flags);
for (i = 0; i < SVC_MAX_CHANNELS; i++) {
- if (svc.chan[i].valid) {
+ if (svc.chan[i].valid)
local[n++] = svc.chan[i];
- if (!svc.chan[i].engine_type)
- n_gr++;
- }
}
spin_unlock_irqrestore(&svc.chan_lock, flags);
- if (n_gr > svc_gr_max)
- svc_gr_max = n_gr;
- else if (!n_gr)
- svc_gr_max = 0;
- n_gr = svc_gr_max;
+ n_gr = SVC_GR_COUNTER_TOTAL;
/*
* P6b wave 1.5: a hold whose channel is absent from this pass's