If the backend wishes to defer the wakeref parking, make it responsible for unlocking the wakeref (i.e. bumping the counter). This allows it to time the unlock much more carefully in case it happens to needs the wakeref to be active during its deferral. For instance, during engine parking we may choose to emit an idle barrier (a request). To do so, we borrow the engine->kernel_context timeline and to ensure exclusive access we keep the engine->wakeref.count as 0. However, to submit that request to HW may require a intel_engine_pm_get() (e.g. to keep the submission tasklet alive) and before we allow that we have to rewake our wakeref to avoid a recursive deadlock. Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@xxxxxxxxx> --- drivers/gpu/drm/i915/gt/intel_engine_pm.c | 4 +++- drivers/gpu/drm/i915/i915_request.c | 10 ++++++++-- drivers/gpu/drm/i915/i915_request.h | 1 + drivers/gpu/drm/i915/intel_wakeref.c | 4 +--- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index 6b15e3335dd6..ca12938d9f8d 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -68,9 +68,11 @@ static bool switch_to_kernel_context(struct intel_engine_cs *engine) /* Check again on the next retirement. */ engine->wakeref_serial = engine->serial + 1; - i915_request_add_active_barriers(rq); + __i915_request_commit(rq); + atomic_inc(&engine->wakeref.count); + __i915_request_queue(rq); return false; } diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 43175bada09e..3a0760ad56eb 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -1186,6 +1186,13 @@ struct i915_request *__i915_request_commit(struct i915_request *rq) list_add(&ring->active_link, &rq->i915->gt.active_rings); rq->emitted_jiffies = jiffies; + return prev; +} + +void __i915_request_queue(struct i915_request *rq) +{ + struct intel_engine_cs *engine = rq->engine; + /* * Let the backend know a new request has arrived that may need * to adjust the existing execution schedule due to a high priority @@ -1230,8 +1237,6 @@ struct i915_request *__i915_request_commit(struct i915_request *rq) } i915_sw_fence_commit(&rq->submit); local_bh_enable(); /* Kick the execlists tasklet if just scheduled */ - - return prev; } void i915_request_add(struct i915_request *rq) @@ -1244,6 +1249,7 @@ void i915_request_add(struct i915_request *rq) trace_i915_request_add(rq); prev = __i915_request_commit(rq); + __i915_request_queue(rq); /* * In typical scenarios, we do not expect the previous request on diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index 313df3c37158..984c8205a185 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/drivers/gpu/drm/i915/i915_request.h @@ -251,6 +251,7 @@ struct i915_request * __must_check i915_request_create(struct intel_context *ce); struct i915_request *__i915_request_commit(struct i915_request *request); +void __i915_request_queue(struct i915_request *rq); void i915_request_retire_upto(struct i915_request *rq); diff --git a/drivers/gpu/drm/i915/intel_wakeref.c b/drivers/gpu/drm/i915/intel_wakeref.c index d4443e81c1c8..868cc78048d0 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.c +++ b/drivers/gpu/drm/i915/intel_wakeref.c @@ -57,12 +57,10 @@ static void ____intel_wakeref_put_last(struct intel_wakeref *wf) if (!atomic_dec_and_test(&wf->count)) goto unlock; + /* ops->put() must reschedule its own release on error/deferral */ if (likely(!wf->ops->put(wf))) { rpm_put(wf); wake_up_var(&wf->wakeref); - } else { - /* ops->put() must schedule its own release on deferral */ - atomic_set_release(&wf->count, 1); } unlock: -- 2.23.0.rc1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx