drm/i915: Split out !RCS legacy context switching

Having the !RCS legacy context switch threaded through the RCS switching
code makes it much harder to follow and understand. In the next patch, I
want to fix a bug handling the incomplete switch, this is made much
simpler if we segregate the two paths now.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel@ffwll.ch>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Reviewed-by: Daniel Vetter <daniel@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1460565315-7748-14-git-send-email-chris@chris-wilson.co.uk
This commit is contained in:
Chris Wilson 2016-04-13 17:35:13 +01:00
parent 349f2ccff9
commit e1a8daa2d1
1 changed files with 38 additions and 36 deletions

View File

@ -609,7 +609,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
return ret; return ret;
} }
static inline bool should_skip_switch(struct intel_engine_cs *engine, static inline bool skip_rcs_switch(struct intel_engine_cs *engine,
struct intel_context *from, struct intel_context *from,
struct intel_context *to) struct intel_context *to)
{ {
@ -626,15 +626,17 @@ static inline bool should_skip_switch(struct intel_engine_cs *engine,
static bool static bool
needs_pd_load_pre(struct intel_engine_cs *engine, struct intel_context *to) needs_pd_load_pre(struct intel_engine_cs *engine, struct intel_context *to)
{ {
struct drm_i915_private *dev_priv = engine->dev->dev_private;
if (!to->ppgtt) if (!to->ppgtt)
return false; return false;
if (INTEL_INFO(engine->dev)->gen < 8) if (engine->last_context == to &&
!(intel_engine_flag(engine) & to->ppgtt->pd_dirty_rings))
return false;
if (engine->id != RCS)
return true; return true;
if (engine != &dev_priv->engine[RCS]) if (INTEL_INFO(engine->dev)->gen < 8)
return true; return true;
return false; return false;
@ -661,32 +663,24 @@ needs_pd_load_post(struct intel_engine_cs *engine, struct intel_context *to,
return false; return false;
} }
static int do_switch(struct drm_i915_gem_request *req) static int do_rcs_switch(struct drm_i915_gem_request *req)
{ {
struct intel_context *to = req->ctx; struct intel_context *to = req->ctx;
struct intel_engine_cs *engine = req->engine; struct intel_engine_cs *engine = req->engine;
struct drm_i915_private *dev_priv = req->i915;
struct intel_context *from = engine->last_context; struct intel_context *from = engine->last_context;
u32 hw_flags = 0; u32 hw_flags = 0;
bool uninitialized = false; bool uninitialized = false;
int ret, i; int ret, i;
if (from != NULL && engine == &dev_priv->engine[RCS]) { if (skip_rcs_switch(engine, from, to))
BUG_ON(from->legacy_hw_ctx.rcs_state == NULL);
BUG_ON(!i915_gem_obj_is_pinned(from->legacy_hw_ctx.rcs_state));
}
if (should_skip_switch(engine, from, to))
return 0; return 0;
/* Trying to pin first makes error handling easier. */ /* Trying to pin first makes error handling easier. */
if (engine == &dev_priv->engine[RCS]) {
ret = i915_gem_obj_ggtt_pin(to->legacy_hw_ctx.rcs_state, ret = i915_gem_obj_ggtt_pin(to->legacy_hw_ctx.rcs_state,
get_context_alignment(engine->dev), get_context_alignment(engine->dev),
0); 0);
if (ret) if (ret)
return ret; return ret;
}
/* /*
* Pin can switch back to the default context if we end up calling into * Pin can switch back to the default context if we end up calling into
@ -709,12 +703,6 @@ static int do_switch(struct drm_i915_gem_request *req)
to->ppgtt->pd_dirty_rings &= ~intel_engine_flag(engine); to->ppgtt->pd_dirty_rings &= ~intel_engine_flag(engine);
} }
if (engine != &dev_priv->engine[RCS]) {
if (from)
i915_gem_context_unreference(from);
goto done;
}
/* /*
* Clear this page out of any CPU caches for coherent swap-in/out. Note * Clear this page out of any CPU caches for coherent swap-in/out. Note
* that thanks to write = false in this call and us not setting any gpu * that thanks to write = false in this call and us not setting any gpu
@ -802,7 +790,6 @@ static int do_switch(struct drm_i915_gem_request *req)
uninitialized = !to->legacy_hw_ctx.initialized; uninitialized = !to->legacy_hw_ctx.initialized;
to->legacy_hw_ctx.initialized = true; to->legacy_hw_ctx.initialized = true;
done:
i915_gem_context_reference(to); i915_gem_context_reference(to);
engine->last_context = to; engine->last_context = to;
@ -817,7 +804,6 @@ done:
return 0; return 0;
unpin_out: unpin_out:
if (engine->id == RCS)
i915_gem_object_ggtt_unpin(to->legacy_hw_ctx.rcs_state); i915_gem_object_ggtt_unpin(to->legacy_hw_ctx.rcs_state);
return ret; return ret;
} }
@ -843,17 +829,33 @@ int i915_switch_context(struct drm_i915_gem_request *req)
WARN_ON(i915.enable_execlists); WARN_ON(i915.enable_execlists);
WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
if (req->ctx->legacy_hw_ctx.rcs_state == NULL) { /* We have the fake context */ if (engine->id != RCS ||
if (req->ctx != engine->last_context) { req->ctx->legacy_hw_ctx.rcs_state == NULL) {
i915_gem_context_reference(req->ctx); struct intel_context *to = req->ctx;
if (needs_pd_load_pre(engine, to)) {
int ret;
trace_switch_mm(engine, to);
ret = to->ppgtt->switch_mm(to->ppgtt, req);
if (ret)
return ret;
/* Doing a PD load always reloads the page dirs */
to->ppgtt->pd_dirty_rings &= ~intel_engine_flag(engine);
}
if (to != engine->last_context) {
i915_gem_context_reference(to);
if (engine->last_context) if (engine->last_context)
i915_gem_context_unreference(engine->last_context); i915_gem_context_unreference(engine->last_context);
engine->last_context = req->ctx; engine->last_context = to;
} }
return 0; return 0;
} }
return do_switch(req); return do_rcs_switch(req);
} }
static bool contexts_enabled(struct drm_device *dev) static bool contexts_enabled(struct drm_device *dev)