summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/gsp_sema_service.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 3b56c36..715e458 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -406,6 +406,7 @@ static u32 svc_ring_n;
* rebuild start from the same empty state as a fresh boot.
*/
static u8 svc_sess_flush;
+static u8 svc_sess_active; /* a channel of a session has registered (until flush) */
static unsigned long svc_ring_done; /* CE ranks whose ring is pinned (session state) */
static u8 svc_pb_passes;
static u64 svc_pb_last;
@@ -925,6 +926,7 @@ void gsp_sema_service_channel_add(const struct sema_channel_desc *desc)
ch->gr_index = rank;
}
ch->valid = true;
+ svc_sess_active = 1;
ch->h_object = desc->h_object;
ch->engine_type = desc->engine_type;
ch->cid = desc->cid;
@@ -986,14 +988,21 @@ void gsp_sema_service_channel_del(u32 h_object)
* session in a new UVM VA space; its discovery state must not inherit
* this session's map/pins/page-directory latch. Request the flush
* here; it executes at the next rebuild (the only writer of that
- * state) just like a fresh boot would start empty.
+ * state) just like a fresh boot would start empty. Only the transition
+ * from "a session existed" to "empty" may request it: redundant
+ * deletes for handles that never registered would otherwise re-flush
+ * (and wipe) a session that started after the real one ended.
*/
- for (i = 0; i < SVC_MAX_CHANNELS; i++) {
- if (svc.chan[i].valid)
- break;
+ if (svc_sess_active) {
+ for (i = 0; i < SVC_MAX_CHANNELS; i++) {
+ if (svc.chan[i].valid)
+ break;
+ }
+ if (i == SVC_MAX_CHANNELS) {
+ svc_sess_active = 0;
+ svc_sess_flush = 1;
+ }
}
- if (i == SVC_MAX_CHANNELS)
- svc_sess_flush = 1;
spin_unlock_irqrestore(&svc.chan_lock, flags);
/*