Merge tag 'v3.14' into drm-intel-next-queued
[deliverable/linux.git] / drivers / gpu / drm / i915 / i915_gem_context.c
index 19fd3629795c5a2075664c8313c027983730085f..6043062ffce73477231fc053113b9eb8bce12607 100644 (file)
 static int do_switch(struct intel_ring_buffer *ring,
                     struct i915_hw_context *to);
 
+static void do_ppgtt_cleanup(struct i915_hw_ppgtt *ppgtt)
+{
+       struct drm_device *dev = ppgtt->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct i915_address_space *vm = &ppgtt->base;
+
+       if (ppgtt == dev_priv->mm.aliasing_ppgtt ||
+           (list_empty(&vm->active_list) && list_empty(&vm->inactive_list))) {
+               ppgtt->base.cleanup(&ppgtt->base);
+               return;
+       }
+
+       /*
+        * Make sure vmas are unbound before we take down the drm_mm
+        *
+        * FIXME: Proper refcounting should take care of this, this shouldn't be
+        * needed at all.
+        */
+       if (!list_empty(&vm->active_list)) {
+               struct i915_vma *vma;
+
+               list_for_each_entry(vma, &vm->active_list, mm_list)
+                       if (WARN_ON(list_empty(&vma->vma_link) ||
+                                   list_is_singular(&vma->vma_link)))
+                               break;
+
+               i915_gem_evict_vm(&ppgtt->base, true);
+       } else {
+               i915_gem_retire_requests(dev);
+               i915_gem_evict_vm(&ppgtt->base, false);
+       }
+
+       ppgtt->base.cleanup(&ppgtt->base);
+}
+
+static void ppgtt_release(struct kref *kref)
+{
+       struct i915_hw_ppgtt *ppgtt =
+               container_of(kref, struct i915_hw_ppgtt, ref);
+
+       do_ppgtt_cleanup(ppgtt);
+       kfree(ppgtt);
+}
+
 static size_t get_context_alignment(struct drm_device *dev)
 {
        if (IS_GEN6(dev))
@@ -171,6 +215,7 @@ create_vm_for_ctx(struct drm_device *dev, struct i915_hw_context *ctx)
                return ERR_PTR(ret);
        }
 
+       ppgtt->ctx = ctx;
        return ppgtt;
 }
 
@@ -258,8 +303,7 @@ i915_gem_create_context(struct drm_device *dev,
                 * context.
                 */
                ret = i915_gem_obj_ggtt_pin(ctx->obj,
-                                           get_context_alignment(dev),
-                                           false, false);
+                                           get_context_alignment(dev), 0);
                if (ret) {
                        DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret);
                        goto err_destroy;
@@ -335,8 +379,7 @@ void i915_gem_context_reset(struct drm_device *dev)
 
                if (i == RCS) {
                        WARN_ON(i915_gem_obj_ggtt_pin(dctx->obj,
-                                                     get_context_alignment(dev),
-                                                     false, false));
+                                                     get_context_alignment(dev), 0));
                        /* Fake a finish/inactive */
                        dctx->obj->base.write_domain = 0;
                        dctx->obj->active = 0;
@@ -612,8 +655,7 @@ static int do_switch(struct intel_ring_buffer *ring,
        /* 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);
+                                           get_context_alignment(ring->dev), 0);
                if (ret)
                        return ret;
        }
@@ -717,7 +759,7 @@ unpin_out:
  * i915_switch_context() - perform a GPU context switch.
  * @ring: ring for which we'll execute the context switch
  * @file_priv: file_priv associated with the context, may be NULL
- * @id: context id number
+ * @to: the context to switch to
  *
  * The context life cycle is simple. The context refcount is incremented and
  * decremented by 1 and create and destroy. If the context is in use by the GPU,
@@ -734,9 +776,11 @@ int i915_switch_context(struct intel_ring_buffer *ring,
 
        BUG_ON(file && to == NULL);
 
-       /* We have the fake context, but don't supports switching. */
-       if (!HAS_HW_CONTEXTS(ring->dev))
+       /* We have the fake context */
+       if (!HAS_HW_CONTEXTS(ring->dev)) {
+               ring->last_context = to;
                return 0;
+       }
 
        return do_switch(ring, to);
 }
@@ -749,9 +793,6 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
        struct i915_hw_context *ctx;
        int ret;
 
-       if (!(dev->driver->driver_features & DRIVER_GEM))
-               return -ENODEV;
-
        if (!HAS_HW_CONTEXTS(dev))
                return -ENODEV;
 
@@ -778,9 +819,6 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
        struct i915_hw_context *ctx;
        int ret;
 
-       if (!(dev->driver->driver_features & DRIVER_GEM))
-               return -ENODEV;
-
        if (args->ctx_id == DEFAULT_CONTEXT_ID)
                return -ENOENT;
 
This page took 0.033867 seconds and 5 git commands to generate.