@@ -667,13 +667,12 @@ static int do_switch(struct intel_ring_buffer *ring,
*/
from = ring->last_context;
- if (USES_FULL_PPGTT(ring->dev)) {
- ret = ppgtt->switch_mm(ppgtt, ring, false);
- if (ret)
- goto unpin_out;
- }
-
if (ring != &dev_priv->ring[RCS]) {
+ if (USES_FULL_PPGTT(ring->dev)) {
+ ret = ppgtt->switch_mm(ppgtt, ring, false);
+ if (ret)
+ goto unpin_out;
+ }
if (from)
i915_gem_context_unreference(from);
goto done;
@@ -711,6 +710,19 @@ static int do_switch(struct intel_ring_buffer *ring,
if (ret)
goto unpin_out;
+ if (USES_FULL_PPGTT(ring->dev)) {
+ ret = ppgtt->switch_mm(ppgtt, ring, false);
+ /* The hardware context switch is emitted, but we haven't
+ * actually changed the state - so it's probably safe to bail
+ * here. Still, let the user know something dangerous has
+ * happened.
+ */
+ if (ret) {
+ DRM_ERROR("Failed to change address space on context switch\n");
+ goto unpin_out;
+ }
+ }
+
for (i = 0; i < MAX_L3_SLICES; i++) {
if (!(to->remap_slice & (1<<i)))
continue;
On GEN8 the PDPs are saved and restored with context, which means we must set them after the context switch has occurred. If we do not do this, we end up saving the new PDPs for the old context. The next patch will go one step further and actually only load the PDPs once. Example of a problem LRI PDPs 1 MI_SET_CONTEXT bar LRI_PDPs 2 MI_SET_CONTEXT foo // save PDPs 2 to bar's context // load foos PDPs LRI PDPs 1 MI_SET_CONTEXT bar // save PDPs 1 to foo's context It's all wacky. This should allow full PPGTT on Broadwell to work. Signed-off-by: Ben Widawsky <ben@bwidawsk.net> --- drivers/gpu/drm/i915/i915_gem_context.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)