[Intel-gfx] [PATCH] drm/i915/gem: Reduce ggtt_flush() from a wait-for-idle to a mere barrier flush
Chris Wilson
chris at chris-wilson.co.uk
Wed Nov 20 16:49:13 UTC 2019
Quoting Chris Wilson (2019-11-20 16:42:46)
> Since we use barriers, we need only explicitly flush those barriers to
> ensure tha we can reclaim the available ggtt for ourselves. The barrier
> flush was implicit inside the intel_gt_wait_for_idle() -- except because
> we use i915_gem_evict from inside an active timeline during execbuf, we
> could easily end up waiting upon ourselves.
>
> v2: Wait on the barriers to ensure that any context unpinning that can
> be done, will be done.
>
> Fixes: 7936a22dd466 ("drm/i915/gt: Wait for new requests in intel_gt_retire_requests()")
> Fixes: a46bfdc83fee ("drm/i915/gt: Wait for new requests in intel_gt_retire_requests()")
> Testcase: igt/gem_exec_reloc/basic-range
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
> ---
> .../gpu/drm/i915/gt/intel_engine_heartbeat.c | 8 +++-
> .../gpu/drm/i915/gt/intel_engine_heartbeat.h | 4 +-
> drivers/gpu/drm/i915/gt/selftest_context.c | 38 ++++---------------
> .../drm/i915/gt/selftest_engine_heartbeat.c | 7 +++-
> drivers/gpu/drm/i915/i915_gem_evict.c | 26 ++++++++++++-
> 5 files changed, 48 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
> index c91fd4e4af29..0173720af05a 100644
> --- a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
> +++ b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
> @@ -212,10 +212,14 @@ int intel_engine_pulse(struct intel_engine_cs *engine)
> return err;
> }
>
> -int intel_engine_flush_barriers(struct intel_engine_cs *engine)
> +int intel_engine_flush_barriers(struct intel_engine_cs *engine,
> + struct i915_request **out)
> {
> struct i915_request *rq;
>
> + if (out)
> + *out = NULL;
> +
> if (llist_empty(&engine->barrier_tasks))
> return 0;
>
> @@ -224,6 +228,8 @@ int intel_engine_flush_barriers(struct intel_engine_cs *engine)
> return PTR_ERR(rq);
>
> idle_pulse(engine, rq);
> + if (out)
> + *out = i915_request_get(rq);
> i915_request_add(rq);
>
> return 0;
> diff --git a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.h b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.h
> index a7b8c0f9e005..17e973d86f5c 100644
> --- a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.h
> +++ b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.h
> @@ -7,6 +7,7 @@
> #ifndef INTEL_ENGINE_HEARTBEAT_H
> #define INTEL_ENGINE_HEARTBEAT_H
>
> +struct i915_request;
> struct intel_engine_cs;
>
> void intel_engine_init_heartbeat(struct intel_engine_cs *engine);
> @@ -18,6 +19,7 @@ void intel_engine_park_heartbeat(struct intel_engine_cs *engine);
> void intel_engine_unpark_heartbeat(struct intel_engine_cs *engine);
>
> int intel_engine_pulse(struct intel_engine_cs *engine);
> -int intel_engine_flush_barriers(struct intel_engine_cs *engine);
> +int intel_engine_flush_barriers(struct intel_engine_cs *engine,
> + struct i915_request **barrier);
>
> #endif /* INTEL_ENGINE_HEARTBEAT_H */
> diff --git a/drivers/gpu/drm/i915/gt/selftest_context.c b/drivers/gpu/drm/i915/gt/selftest_context.c
> index 3586af636304..0c0f130802fb 100644
> --- a/drivers/gpu/drm/i915/gt/selftest_context.c
> +++ b/drivers/gpu/drm/i915/gt/selftest_context.c
> @@ -41,33 +41,6 @@ static int request_sync(struct i915_request *rq)
> return err;
> }
>
> -static int context_sync(struct intel_context *ce)
> -{
> - struct intel_timeline *tl = ce->timeline;
> - int err = 0;
> -
> - mutex_lock(&tl->mutex);
> - do {
> - struct dma_fence *fence;
> - long timeout;
> -
> - fence = i915_active_fence_get(&tl->last_request);
> - if (!fence)
> - break;
> -
> - timeout = dma_fence_wait_timeout(fence, false, HZ / 10);
> - if (timeout < 0)
> - err = timeout;
> - else
> - i915_request_retire_upto(to_request(fence));
> -
> - dma_fence_put(fence);
> - } while (!err);
> - mutex_unlock(&tl->mutex);
> -
> - return err;
> -}
> -
> static int __live_context_size(struct intel_engine_cs *engine,
> struct i915_gem_context *fixme)
> {
> @@ -202,6 +175,7 @@ static int __live_active_context(struct intel_engine_cs *engine,
> struct i915_gem_context *fixme)
> {
> unsigned long saved_heartbeat;
> + struct i915_request *barrier;
> struct intel_context *ce;
> int pass;
> int err;
> @@ -269,17 +243,21 @@ static int __live_active_context(struct intel_engine_cs *engine,
> }
>
> /* Now make sure our idle-barriers are flushed */
> - err = intel_engine_flush_barriers(engine);
> + err = intel_engine_flush_barriers(engine, &barrier);
> if (err)
> goto err;
>
> - err = context_sync(engine->kernel_context);
> - if (err)
> + if (i915_request_wait(barrier, 0, HZ / 5) < 0) {
> + i915_request_put(barrier);
> + err = -ETIME;
> goto err;
> + }
> + i915_request_put(barrier);
>
> if (!i915_active_is_idle(&ce->active)) {
> pr_err("context is still active!");
> err = -EINVAL;
> + goto err;
> }
>
> if (intel_engine_pm_is_awake(engine)) {
> diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c
> index f665a0e23c61..0bd9afc20ef3 100644
> --- a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c
> +++ b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c
> @@ -115,6 +115,11 @@ static int __live_idle_pulse(struct intel_engine_cs *engine,
> return err;
> }
>
> +static int wrap_engine_flush_barriers(struct intel_engine_cs *engine)
> +{
> + return intel_engine_flush_barriers(engine, NULL);
> +}
> +
> static int live_idle_flush(void *arg)
> {
> struct intel_gt *gt = arg;
> @@ -126,7 +131,7 @@ static int live_idle_flush(void *arg)
>
> for_each_engine(engine, gt, id) {
> intel_engine_pm_get(engine);
> - err = __live_idle_pulse(engine, intel_engine_flush_barriers);
> + err = __live_idle_pulse(engine, wrap_engine_flush_barriers);
> intel_engine_pm_put(engine);
> if (err)
> break;
> diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
> index 7e62c310290f..91daf87f491e 100644
> --- a/drivers/gpu/drm/i915/i915_gem_evict.c
> +++ b/drivers/gpu/drm/i915/i915_gem_evict.c
> @@ -28,7 +28,7 @@
>
> #include <drm/i915_drm.h>
>
> -#include "gem/i915_gem_context.h"
> +#include "gt/intel_engine_heartbeat.h"
> #include "gt/intel_gt_requests.h"
>
> #include "i915_drv.h"
> @@ -40,6 +40,9 @@ I915_SELFTEST_DECLARE(static struct igt_evict_ctl {
>
> static int ggtt_flush(struct intel_gt *gt)
> {
> + struct intel_engine_cs *engine;
> + enum intel_engine_id id;
> +
> /*
> * Not everything in the GGTT is tracked via vma (otherwise we
> * could evict as required with minimal stalling) so we are forced
> @@ -47,7 +50,26 @@ static int ggtt_flush(struct intel_gt *gt)
> * the hopes that we can then remove contexts and the like only
> * bound by their active reference.
> */
> - return intel_gt_wait_for_idle(gt, MAX_SCHEDULE_TIMEOUT);
> + intel_gt_retire_requests(gt);
> + for_each_engine(engine, gt, id) {
> + struct i915_request *barrier;
> + long err;
> +
> + /* A barrier will unpin anything that is ready to be unpinned */
> + err = intel_engine_flush_barriers(engine, &barrier);
> + if (err)
> + return err;
> +
> + err = i915_request_wait(barrier,
> + I915_WAIT_INTERRUPTIBLE,
> + MAX_SCHEDULE_TIMEOUT);
> + i915_request_put(barrier);
> + if (err)
> + return err;
It's still weaker than it was before, I can keep papering over it. :|
Long term plan is pipelined evictions. Oh boy.
-Chris
More information about the Intel-gfx
mailing list