drm/i915: Choose not to evict faultable objects from the GGTT
authorChris Wilson <chris@chris-wilson.co.uk>
Thu, 18 Aug 2016 16:17:05 +0000 (17:17 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Thu, 18 Aug 2016 21:36:55 +0000 (22:36 +0100)
Often times we do not want to evict mapped objects from the GGTT as
these are quite expensive to teardown and frequently reused (causing an
equally, if not more so, expensive setup). In particular, when faulting
in a new object we want to avoid evicting an active object, or else we
may trigger a page-fault-of-doom as we ping-pong between evicting two
objects.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20160818161718.27187-26-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_evict.c
drivers/gpu/drm/i915/i915_gem_gtt.h

index 9811980d6837e9fdd57fec5a3191a66301c75e66..a13290a8ba308bc9dc6c0d5b4ba1c23815fdc38f 100644 (file)
@@ -1706,6 +1706,7 @@ int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf)
        struct i915_vma *vma;
        pgoff_t page_offset;
        unsigned long pfn;
+       unsigned int flags;
        int ret;
 
        /* We don't use vmf->pgoff since that has the fake offset */
@@ -1735,9 +1736,16 @@ int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf)
                goto err_unlock;
        }
 
+       /* If the object is smaller than a couple of partial vma, it is
+        * not worth only creating a single partial vma - we may as well
+        * clear enough space for the full object.
+        */
+       flags = PIN_MAPPABLE;
+       if (obj->base.size > 2 * MIN_CHUNK_PAGES << PAGE_SHIFT)
+               flags |= PIN_NONBLOCK | PIN_NONFAULT;
+
        /* Now pin it into the GTT as needed */
-       vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
-                                      PIN_MAPPABLE | PIN_NONBLOCK);
+       vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, flags);
        if (IS_ERR(vma)) {
                struct i915_ggtt_view view;
                unsigned int chunk_size;
index f76c06e9267736c50060d5281e49baff6ba77d6c..815d5fbe07acaa935dc17eca3cbc6de660ed7b6f 100644 (file)
@@ -47,7 +47,7 @@ gpu_is_idle(struct drm_i915_private *dev_priv)
 }
 
 static bool
-mark_free(struct i915_vma *vma, struct list_head *unwind)
+mark_free(struct i915_vma *vma, unsigned int flags, struct list_head *unwind)
 {
        if (i915_vma_is_pinned(vma))
                return false;
@@ -55,6 +55,9 @@ mark_free(struct i915_vma *vma, struct list_head *unwind)
        if (WARN_ON(!list_empty(&vma->exec_list)))
                return false;
 
+       if (flags & PIN_NONFAULT && vma->obj->fault_mappable)
+               return false;
+
        list_add(&vma->exec_list, unwind);
        return drm_mm_scan_add_block(&vma->node);
 }
@@ -129,7 +132,7 @@ search_again:
        phase = phases;
        do {
                list_for_each_entry(vma, *phase, vm_link)
-                       if (mark_free(vma, &eviction_list))
+                       if (mark_free(vma, flags, &eviction_list))
                                goto found;
        } while (*++phase);
 
index c88af2ab553892bb4d1c0f4b09209075328286fb..9248a0e0b28679f8a6f5195a3ddce75e326b11ce 100644 (file)
@@ -637,6 +637,7 @@ void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj);
 #define PIN_NONBLOCK           BIT(0)
 #define PIN_MAPPABLE           BIT(1)
 #define PIN_ZONE_4G            BIT(2)
+#define PIN_NONFAULT           BIT(3)
 
 #define PIN_MBZ                        BIT(5) /* I915_VMA_PIN_OVERFLOW */
 #define PIN_GLOBAL             BIT(6) /* I915_VMA_GLOBAL_BIND */