diff options
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index c46cbbb..5bff6ca 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -481,6 +481,21 @@ void gsp_sema_service_channel_add(const struct sema_channel_desc *desc) } if (ch) { int k; + u64 keep_counter_pa = 0; + u8 keep_gr_index = 0, keep_ce_index = 0; + bool same = ch->valid && ch->h_object == desc->h_object; + + /* + * A re-registration of the same channel must not lose the + * counter slot learned for it (the RM re-issues registration + * for an existing channel on some control paths, and the + * counter layout does not change). + */ + if (same) { + keep_counter_pa = ch->counter_pa; + keep_gr_index = ch->gr_index; + keep_ce_index = ch->ce_index; + } memset(ch, 0, sizeof(*ch)); /* @@ -520,6 +535,11 @@ void gsp_sema_service_channel_add(const struct sema_channel_desc *desc) ch->notifier_pa = desc->notifier_pa; ch->notifier_as = desc->notifier_as ? desc->notifier_as : SVC_APERTURE_SYS; + if (same) { + ch->counter_pa = keep_counter_pa; + ch->gr_index = keep_gr_index; + ch->ce_index = keep_ce_index; + } } spin_unlock_irqrestore(&svc.chan_lock, flags); @@ -3987,6 +4007,13 @@ 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). + */ + static int svc_gr_max; unsigned long flags; int i, k, n = 0, n_gr = 0; bool stalled = false; @@ -4001,6 +4028,12 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) } 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; + for (i = 0; i < n; i++) { struct svc_channel *ch = &local[i]; u64 ring_pa = 0; @@ -4354,6 +4387,14 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) svc.chan[k].rescue_last = ch->rescue_last; svc.chan[k].rescue_fail = ch->rescue_fail; svc.chan[k].defer_since = ch->defer_since; + /* + * Persist the counter slot autoreg resolved on the + * snapshot: without this the next pass re-derives + * it (with a different live GR count during + * teardown) and the publishes target the wrong + * slot. + */ + svc.chan[k].counter_pa = ch->counter_pa; break; } } @@ -4620,7 +4661,7 @@ int gsp_sema_service_dump_channels(void) * could not take a batch at all. */ #define SVC_PIN_REWIND 8 -#define SVC_MAP_ADD_MAX 64 +#define SVC_MAP_ADD_MAX 4096 struct svc_map_add_req { u64 va; |
