[Intel-gfx] [PATCH 09/16] drm/i915/gt: ce->inflight updates are now serialised
Tvrtko Ursulin
tvrtko.ursulin at linux.intel.com
Wed Nov 25 09:34:23 UTC 2020
On 24/11/2020 11:42, Chris Wilson wrote:
> Since schedule-in and schedule-out are now both always under the tasklet
> bitlock, we can reduce the individual atomic operations to simple
> instructions and worry less.
>
> This notably eliminates the race observed with intel_context_inflight in
> __engine_unpark().
>
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/2583
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> ---
> drivers/gpu/drm/i915/gt/intel_lrc.c | 52 ++++++++++++++---------------
> 1 file changed, 25 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
> index 49a80f940e73..3a6a9539b54e 100644
> --- a/drivers/gpu/drm/i915/gt/intel_lrc.c
> +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
> @@ -1358,11 +1358,11 @@ __execlists_schedule_in(struct i915_request *rq)
> ce->lrc.ccid = ce->tag;
> } else {
> /* We don't need a strict matching tag, just different values */
> - unsigned int tag = ffs(READ_ONCE(engine->context_tag));
> + unsigned int tag = __ffs(engine->context_tag);
>
> - GEM_BUG_ON(tag == 0 || tag >= BITS_PER_LONG);
> - clear_bit(tag - 1, &engine->context_tag);
> - ce->lrc.ccid = tag << (GEN11_SW_CTX_ID_SHIFT - 32);
> + GEM_BUG_ON(tag >= BITS_PER_LONG);
> + __clear_bit(tag, &engine->context_tag);
> + ce->lrc.ccid = (1 + tag) << (GEN11_SW_CTX_ID_SHIFT - 32);
>
> BUILD_BUG_ON(BITS_PER_LONG > GEN12_MAX_CONTEXT_HW_ID);
> }
> @@ -1375,6 +1375,8 @@ __execlists_schedule_in(struct i915_request *rq)
> execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_IN);
> intel_engine_context_in(engine);
>
> + CE_TRACE(ce, "schedule-in, ccid:%x\n", ce->lrc.ccid);
> +
> return engine;
> }
>
> @@ -1386,13 +1388,10 @@ static inline void execlists_schedule_in(struct i915_request *rq, int idx)
> GEM_BUG_ON(!intel_engine_pm_is_awake(rq->engine));
> trace_i915_request_in(rq, idx);
>
> - old = READ_ONCE(ce->inflight);
> - do {
> - if (!old) {
> - WRITE_ONCE(ce->inflight, __execlists_schedule_in(rq));
> - break;
> - }
> - } while (!try_cmpxchg(&ce->inflight, &old, ptr_inc(old)));
> + old = ce->inflight;
> + if (!old)
> + old = __execlists_schedule_in(rq);
> + WRITE_ONCE(ce->inflight, ptr_inc(old));
>
> GEM_BUG_ON(intel_context_inflight(ce) != rq->engine);
> }
> @@ -1406,12 +1405,11 @@ static void kick_siblings(struct i915_request *rq, struct intel_context *ce)
> tasklet_hi_schedule(&ve->base.execlists.tasklet);
> }
>
> -static inline void
> -__execlists_schedule_out(struct i915_request *rq,
> - struct intel_engine_cs * const engine,
> - unsigned int ccid)
> +static inline void __execlists_schedule_out(struct i915_request *rq)
> {
> struct intel_context * const ce = rq->context;
> + struct intel_engine_cs * const engine = rq->engine;
> + unsigned int ccid;
>
> /*
> * NB process_csb() is not under the engine->active.lock and hence
> @@ -1419,6 +1417,8 @@ __execlists_schedule_out(struct i915_request *rq,
> * refrain from doing non-trivial work here.
> */
>
> + CE_TRACE(ce, "schedule-out, ccid:%x\n", ce->lrc.ccid);
> +
> if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
> execlists_check_context(ce, engine, "after");
>
> @@ -1430,12 +1430,13 @@ __execlists_schedule_out(struct i915_request *rq,
> i915_request_completed(rq))
> intel_engine_add_retire(engine, ce->timeline);
>
> + ccid = ce->lrc.ccid;
> ccid >>= GEN11_SW_CTX_ID_SHIFT - 32;
> ccid &= GEN12_MAX_CONTEXT_HW_ID;
> if (ccid < BITS_PER_LONG) {
> GEM_BUG_ON(ccid == 0);
> GEM_BUG_ON(test_bit(ccid - 1, &engine->context_tag));
> - set_bit(ccid - 1, &engine->context_tag);
> + __set_bit(ccid - 1, &engine->context_tag);
> }
>
> intel_context_update_runtime(ce);
> @@ -1456,26 +1457,23 @@ __execlists_schedule_out(struct i915_request *rq,
> */
> if (ce->engine != engine)
> kick_siblings(rq, ce);
> -
> - intel_context_put(ce);
> }
>
> static inline void
> execlists_schedule_out(struct i915_request *rq)
> {
> struct intel_context * const ce = rq->context;
> - struct intel_engine_cs *cur, *old;
> - u32 ccid;
>
> trace_i915_request_out(rq);
>
> - ccid = rq->context->lrc.ccid;
> - old = READ_ONCE(ce->inflight);
> - do
> - cur = ptr_unmask_bits(old, 2) ? ptr_dec(old) : NULL;
> - while (!try_cmpxchg(&ce->inflight, &old, cur));
> - if (!cur)
> - __execlists_schedule_out(rq, old, ccid);
> + GEM_BUG_ON(!ce->inflight);
> + ce->inflight = ptr_dec(ce->inflight);
> + if (!intel_context_inflight_count(ce)) {
> + GEM_BUG_ON(ce->inflight != rq->engine);
> + __execlists_schedule_out(rq);
> + WRITE_ONCE(ce->inflight, NULL);
> + intel_context_put(ce);
> + }
>
> i915_request_put(rq);
> }
>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
Regards,
Tvrtko
More information about the Intel-gfx
mailing list