diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_sema_service.c | 21 |
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); /* |
