@@ -611,31 +611,58 @@ mi_set_context(struct intel_engine_cs *ring,
return ret;
}
-static int do_switch(struct intel_engine_cs *ring,
- struct intel_context *to)
+static void do_switch_fini_common(struct intel_engine_cs *ring,
+ struct intel_context *from,
+ struct intel_context *to)
+{
+ if (likely(from))
+ i915_gem_context_unreference(from);
+ i915_gem_context_reference(to);
+ ring->last_context = to;
+}
+
+static int do_switch_xcs(struct intel_engine_cs *ring,
+ struct intel_context *from,
+ struct intel_context *to)
+{
+ struct drm_device *dev = ring->dev;
+ struct i915_hw_ppgtt *ppgtt = ctx_to_ppgtt(to);
+ int ret;
+
+ BUG_ON(from && from->legacy_hw_ctx.rcs_state != NULL);
+
+ if (USES_FULL_PPGTT(dev)) {
+ ret = ppgtt->switch_mm(ppgtt, ring, false);
+ if (ret)
+ return ret;
+ }
+
+ if (from)
+ do_switch_fini_common(ring, from, to);
+
+ return 0;
+}
+
+static int do_switch_rcs(struct intel_engine_cs *ring,
+ struct intel_context *from,
+ struct intel_context *to)
{
struct drm_i915_private *dev_priv = ring->dev->dev_private;
- struct intel_context *from = ring->last_context;
struct i915_hw_ppgtt *ppgtt = ctx_to_ppgtt(to);
u32 hw_flags = 0;
bool uninitialized = false;
int ret, i;
- if (from != NULL && ring == &dev_priv->ring[RCS]) {
+ if (from != NULL) {
BUG_ON(from->legacy_hw_ctx.rcs_state == NULL);
- BUG_ON(!i915_gem_obj_is_pinned(from->legacy_hw_ctx.rcs_state));
+ BUG_ON(!i915_gem_obj_ggtt_bound(from->legacy_hw_ctx.rcs_state));
}
- if (from == to && !to->remap_slice)
- return 0;
-
/* Trying to pin first makes error handling easier. */
- if (ring == &dev_priv->ring[RCS]) {
- ret = i915_gem_obj_ggtt_pin(to->legacy_hw_ctx.rcs_state,
- get_context_alignment(ring->dev), 0);
- if (ret)
- return ret;
- }
+ ret = i915_gem_obj_ggtt_pin(to->legacy_hw_ctx.rcs_state,
+ get_context_alignment(ring->dev), 0);
+ if (ret)
+ return ret;
/*
* Pin can switch back to the default context if we end up calling into
@@ -650,12 +677,6 @@ static int do_switch(struct intel_engine_cs *ring,
goto unpin_out;
}
- if (ring != &dev_priv->ring[RCS]) {
- if (from)
- i915_gem_context_unreference(from);
- goto done;
- }
-
/*
* 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
@@ -714,15 +735,11 @@ static int do_switch(struct intel_engine_cs *ring,
/* obj is kept alive until the next request by its active ref */
i915_gem_object_ggtt_unpin(from->legacy_hw_ctx.rcs_state);
- i915_gem_context_unreference(from);
}
uninitialized = !to->legacy_hw_ctx.initialized && from == NULL;
to->legacy_hw_ctx.initialized = true;
-
-done:
- i915_gem_context_reference(to);
- ring->last_context = to;
+ do_switch_fini_common(ring, from, to);
if (uninitialized) {
ret = i915_gem_render_state_init(ring);
@@ -733,8 +750,7 @@ done:
return 0;
unpin_out:
- if (ring->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;
}
@@ -752,6 +768,7 @@ int i915_switch_context(struct intel_engine_cs *ring,
struct intel_context *to)
{
struct drm_i915_private *dev_priv = ring->dev->dev_private;
+ struct intel_context *from = ring->last_context;
WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
@@ -765,7 +782,13 @@ int i915_switch_context(struct intel_engine_cs *ring,
return 0;
}
- return do_switch(ring, to);
+ if (from == to && !to->remap_slice)
+ return 0;
+
+ if (ring->id == RCS)
+ return do_switch_rcs(ring, from, to);
+ else
+ return do_switch_xcs(ring, from, to);
}
static bool hw_context_enabled(struct drm_device *dev)