drm/i915: First try the previous execbuffer location
authorChris Wilson <chris@chris-wilson.co.uk>
Fri, 16 Jun 2017 14:05:21 +0000 (15:05 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Fri, 16 Jun 2017 15:54:05 +0000 (16:54 +0100)
When choosing a slot for an execbuffer, we ideally want to use the same
address as last time (so that we don't have to rebind it) and the same
address as expected by the user (so that we don't have to fixup any
relocations pointing to it). If we first try to bind the incoming
execbuffer->offset from the user, or the currently bound offset that
should hopefully achieve the goal of avoiding the rebind cost and the
relocation penalty. However, if the object is not currently bound there
we don't want to arbitrarily unbind an object in our chosen position and
so choose to rebind/relocate the incoming object instead. After we
report the new position back to the user, on the next pass the
relocations should have settled down.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Joonas Lahtinen <joonas.lahtien@linux.intel.com>
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_gtt.h

index d91386f0e8402bfc801283fa86d6a3e0de69d8d0..3eaf07dfbe629fe42aa3b3ddc93706e269c8a00f 100644 (file)
@@ -336,10 +336,15 @@ eb_pin_vma(struct i915_execbuffer *eb,
 {
        u64 flags;
 
-       flags = vma->node.start;
-       flags |= PIN_USER | PIN_NONBLOCK | PIN_OFFSET_FIXED;
+       if (vma->node.size)
+               flags = vma->node.start;
+       else
+               flags = entry->offset & PIN_OFFSET_MASK;
+
+       flags |= PIN_USER | PIN_NOEVICT | PIN_OFFSET_FIXED;
        if (unlikely(entry->flags & EXEC_OBJECT_NEEDS_GTT))
                flags |= PIN_GLOBAL;
+
        if (unlikely(i915_vma_pin(vma, 0, 0, flags)))
                return;
 
@@ -469,8 +474,7 @@ eb_add_vma(struct i915_execbuffer *eb,
        __exec_to_vma(entry) = (uintptr_t)vma;
 
        err = 0;
-       if (vma->node.size)
-               eb_pin_vma(eb, entry, vma);
+       eb_pin_vma(eb, entry, vma);
        if (eb_vma_misplaced(entry, vma)) {
                eb_unreserve_vma(vma, entry);
 
index 4ff854e6413cf84f64ba4bed6abea83c085a6a01..205dd91d3601dcb6ddf7046aeb5af6860975c558 100644 (file)
@@ -3402,6 +3402,9 @@ int i915_gem_gtt_reserve(struct i915_address_space *vm,
        if (err != -ENOSPC)
                return err;
 
+       if (flags & PIN_NOEVICT)
+               return -ENOSPC;
+
        err = i915_gem_evict_for_node(vm, node, flags);
        if (err == 0)
                err = drm_mm_reserve_node(&vm->mm, node);
@@ -3516,6 +3519,9 @@ int i915_gem_gtt_insert(struct i915_address_space *vm,
        if (err != -ENOSPC)
                return err;
 
+       if (flags & PIN_NOEVICT)
+               return -ENOSPC;
+
        /* No free space, pick a slot at random.
         *
         * There is a pathological case here using a GTT shared between
index da9aa9f706e7c0d389dc578c0204bf827c168e05..1b2a56c3e5d3ab38251e02ed4d54a0c57ae653af 100644 (file)
@@ -589,6 +589,7 @@ int i915_gem_gtt_insert(struct i915_address_space *vm,
 #define PIN_MAPPABLE           BIT(1)
 #define PIN_ZONE_4G            BIT(2)
 #define PIN_NONFAULT           BIT(3)
+#define PIN_NOEVICT            BIT(4)
 
 #define PIN_MBZ                        BIT(5) /* I915_VMA_PIN_OVERFLOW */
 #define PIN_GLOBAL             BIT(6) /* I915_VMA_GLOBAL_BIND */