summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_gem_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_context.c')
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.c60
1 files changed, 35 insertions, 25 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 165a5c7d9424..ebe0f67eac08 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -288,17 +288,15 @@ i915_gem_create_context(struct drm_device *dev,
DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret);
goto err_destroy;
}
+
+ ctx->vm = &dev_priv->mm.aliasing_ppgtt->base;
}
} else if (USES_ALIASING_PPGTT(dev)) {
/* For platforms which only have aliasing PPGTT, we fake the
* address space and refcounting. */
- kref_get(&dev_priv->mm.aliasing_ppgtt->ref);
- }
-
- /* TODO: Until full ppgtt... */
- if (USES_ALIASING_PPGTT(dev))
ctx->vm = &dev_priv->mm.aliasing_ppgtt->base;
- else
+ kref_get(&dev_priv->mm.aliasing_ppgtt->ref);
+ } else
ctx->vm = &dev_priv->gtt.base;
return ctx;
@@ -500,7 +498,7 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file)
mutex_lock(&dev->struct_mutex);
file_priv->private_default_ctx =
- i915_gem_create_context(dev, file_priv, false);
+ i915_gem_create_context(dev, file_priv, USES_FULL_PPGTT(dev));
mutex_unlock(&dev->struct_mutex);
if (IS_ERR(file_priv->private_default_ctx)) {
@@ -587,6 +585,7 @@ static int do_switch(struct intel_ring_buffer *ring,
{
struct drm_i915_private *dev_priv = ring->dev->dev_private;
struct i915_hw_context *from = ring->last_context;
+ struct i915_hw_ppgtt *ppgtt = ctx_to_ppgtt(to);
u32 hw_flags = 0;
int ret, i;
@@ -598,17 +597,15 @@ static int do_switch(struct intel_ring_buffer *ring,
if (from == to && from->last_ring == ring && !to->remap_slice)
return 0;
- if (ring != &dev_priv->ring[RCS]) {
- if (from)
- i915_gem_context_unreference(from);
- goto done;
+ /* Trying to pin first makes error handling easier. */
+ if (ring == &dev_priv->ring[RCS]) {
+ ret = i915_gem_obj_ggtt_pin(to->obj,
+ get_context_alignment(ring->dev),
+ false, false);
+ if (ret)
+ return ret;
}
- ret = i915_gem_obj_ggtt_pin(to->obj, get_context_alignment(ring->dev),
- false, false);
- if (ret)
- return ret;
-
/*
* Pin can switch back to the default context if we end up calling into
* evict_everything - as a last ditch gtt defrag effort that also
@@ -616,6 +613,18 @@ 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 (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
@@ -625,10 +634,8 @@ static int do_switch(struct intel_ring_buffer *ring,
* XXX: We need a real interface to do this instead of trickery.
*/
ret = i915_gem_object_set_to_gtt_domain(to->obj, false);
- if (ret) {
- i915_gem_object_ggtt_unpin(to->obj);
- return ret;
- }
+ if (ret)
+ goto unpin_out;
if (!to->obj->has_global_gtt_mapping) {
struct i915_vma *vma = i915_gem_obj_to_vma(to->obj,
@@ -640,10 +647,8 @@ static int do_switch(struct intel_ring_buffer *ring,
hw_flags |= MI_RESTORE_INHIBIT;
ret = mi_set_context(ring, to, hw_flags);
- if (ret) {
- i915_gem_object_ggtt_unpin(to->obj);
- return ret;
- }
+ if (ret)
+ goto unpin_out;
for (i = 0; i < MAX_L3_SLICES; i++) {
if (!(to->remap_slice & (1<<i)))
@@ -688,6 +693,11 @@ done:
to->last_ring = ring;
return 0;
+
+unpin_out:
+ if (ring->id == RCS)
+ i915_gem_object_ggtt_unpin(to->obj);
+ return ret;
}
/**
@@ -736,7 +746,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
if (ret)
return ret;
- ctx = i915_gem_create_context(dev, file_priv, false);
+ ctx = i915_gem_create_context(dev, file_priv, USES_FULL_PPGTT(dev));
mutex_unlock(&dev->struct_mutex);
if (IS_ERR(ctx))
return PTR_ERR(ctx);