diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2016-06-24 14:55:57 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2016-06-24 15:03:14 +0100 |
commit | 6e5a5beb8e344b1ab929de0c8446a61a70ed94ba (patch) | |
tree | 1bfb6d8e8fc086c5b3ee78aa025d93d5cc84dbe9 /drivers/gpu/drm/i915/i915_gem_evict.c | |
parent | ec602a0dfb394ac3a5f91d03c4d6fab6e45302cc (diff) |
drm/i915: Split idling from forcing context switch
We only need to force a switch to the kernel context placeholder during
eviction. All other uses of i915_gpu_idle() just want to wait until
existing work on the GPU is idle. Rename i915_gpu_idle() to
i915_gem_wait_for_idle() to avoid any implications about "parking" the
context first.
v2: Tweak an error message if the wait fails for the ilk vtd w/a
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1466776558-21516-6-git-send-email-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_evict.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_evict.c | 51 |
1 files changed, 47 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index b144c3f5c650..5741b58d186c 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -33,6 +33,37 @@ #include "intel_drv.h" #include "i915_trace.h" +static int switch_to_pinned_context(struct drm_i915_private *dev_priv) +{ + struct intel_engine_cs *engine; + + if (i915.enable_execlists) + return 0; + + for_each_engine(engine, dev_priv) { + struct drm_i915_gem_request *req; + int ret; + + if (engine->last_context == NULL) + continue; + + if (engine->last_context == dev_priv->kernel_context) + continue; + + req = i915_gem_request_alloc(engine, dev_priv->kernel_context); + if (IS_ERR(req)) + return PTR_ERR(req); + + ret = i915_switch_context(req); + i915_add_request_no_flush(req); + if (ret) + return ret; + } + + return 0; +} + + static bool mark_free(struct i915_vma *vma, struct list_head *unwind) { @@ -150,11 +181,17 @@ none: /* Only idle the GPU and repeat the search once */ if (pass++ == 0) { - ret = i915_gpu_idle(dev); + struct drm_i915_private *dev_priv = to_i915(dev); + + ret = switch_to_pinned_context(dev_priv); if (ret) return ret; - i915_gem_retire_requests(to_i915(dev)); + ret = i915_gem_wait_for_idle(dev_priv); + if (ret) + return ret; + + i915_gem_retire_requests(dev_priv); goto search_again; } @@ -261,11 +298,17 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle) trace_i915_gem_evict_vm(vm); if (do_idle) { - ret = i915_gpu_idle(vm->dev); + struct drm_i915_private *dev_priv = to_i915(vm->dev); + + ret = switch_to_pinned_context(dev_priv); + if (ret) + return ret; + + ret = i915_gem_wait_for_idle(dev_priv); if (ret) return ret; - i915_gem_retire_requests(to_i915(vm->dev)); + i915_gem_retire_requests(dev_priv); WARN_ON(!list_empty(&vm->active_list)); } |