]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/gpu/drm/i915/gem/i915_gem_domain.c
drm/i915/gem: Track ggtt writes from userspace on the bound vma
[linux.git] / drivers / gpu / drm / i915 / gem / i915_gem_domain.c
index 9c58e8fac1d977c02dca65df0a4cb7b9ab715158..9aebcf2631918fbcc779d3c95456f6abbc4a031f 100644 (file)
@@ -12,6 +12,7 @@
 #include "i915_gem_ioctls.h"
 #include "i915_gem_object.h"
 #include "i915_vma.h"
+#include "i915_gem_lmem.h"
 
 static void __i915_gem_object_flush_for_display(struct drm_i915_gem_object *obj)
 {
@@ -27,7 +28,7 @@ static void __i915_gem_object_flush_for_display(struct drm_i915_gem_object *obj)
 
 void i915_gem_object_flush_if_display(struct drm_i915_gem_object *obj)
 {
-       if (!READ_ONCE(obj->pin_global))
+       if (!i915_gem_object_is_framebuffer(obj))
                return;
 
        i915_gem_object_lock(obj);
@@ -148,9 +149,17 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
        GEM_BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
        obj->read_domains |= I915_GEM_DOMAIN_GTT;
        if (write) {
+               struct i915_vma *vma;
+
                obj->read_domains = I915_GEM_DOMAIN_GTT;
                obj->write_domain = I915_GEM_DOMAIN_GTT;
                obj->mm.dirty = true;
+
+               spin_lock(&obj->vma.lock);
+               for_each_ggtt_vma(vma, obj)
+                       if (i915_vma_is_bound(vma, I915_VMA_GLOBAL_BIND))
+                               i915_vma_set_ggtt_write(vma);
+               spin_unlock(&obj->vma.lock);
        }
 
        i915_gem_object_unpin_pages(obj);
@@ -288,14 +297,21 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
                        if (!drm_mm_node_allocated(&vma->node))
                                continue;
 
-                       ret = i915_vma_bind(vma, cache_level, PIN_UPDATE);
+                       /* Wait for an earlier async bind, need to rewrite it */
+                       ret = i915_vma_sync(vma);
+                       if (ret)
+                               return ret;
+
+                       ret = i915_vma_bind(vma, cache_level, PIN_UPDATE, NULL);
                        if (ret)
                                return ret;
                }
        }
 
-       list_for_each_entry(vma, &obj->vma.list, obj_link)
-               vma->node.color = cache_level;
+       list_for_each_entry(vma, &obj->vma.list, obj_link) {
+               if (i915_vm_has_cache_coloring(vma->vm))
+                       vma->node.color = cache_level;
+       }
        i915_gem_object_set_cache_coherency(obj, cache_level);
        obj->cache_dirty = true; /* Always invalidate stale cachelines */
 
@@ -389,16 +405,11 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
        if (ret)
                goto out;
 
-       ret = mutex_lock_interruptible(&i915->drm.struct_mutex);
-       if (ret)
-               goto out;
-
        ret = i915_gem_object_lock_interruptible(obj);
        if (ret == 0) {
                ret = i915_gem_object_set_cache_level(obj, level);
                i915_gem_object_unlock(obj);
        }
-       mutex_unlock(&i915->drm.struct_mutex);
 
 out:
        i915_gem_object_put(obj);
@@ -417,17 +428,18 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
                                     const struct i915_ggtt_view *view,
                                     unsigned int flags)
 {
+       struct drm_i915_private *i915 = to_i915(obj->base.dev);
        struct i915_vma *vma;
        int ret;
 
        assert_object_held(obj);
 
-       /* Mark the global pin early so that we account for the
-        * display coherency whilst setting up the cache domains.
-        */
-       obj->pin_global++;
+       /* Frame buffer must be in LMEM (no migration yet) */
+       if (HAS_LMEM(i915) && !i915_gem_object_is_lmem(obj))
+               return ERR_PTR(-EINVAL);
 
-       /* The display engine is not coherent with the LLC cache on gen6.  As
+       /*
+        * The display engine is not coherent with the LLC cache on gen6.  As
         * a result, we make sure that the pinning that is about to occur is
         * done with uncached PTEs. This is lowest common denominator for all
         * chipsets.
@@ -437,14 +449,13 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
         * with that bit in the PTE to main memory with just one PIPE_CONTROL.
         */
        ret = i915_gem_object_set_cache_level(obj,
-                                             HAS_WT(to_i915(obj->base.dev)) ?
+                                             HAS_WT(i915) ?
                                              I915_CACHE_WT : I915_CACHE_NONE);
-       if (ret) {
-               vma = ERR_PTR(ret);
-               goto err_unpin_global;
-       }
+       if (ret)
+               return ERR_PTR(ret);
 
-       /* As the user may map the buffer once pinned in the display plane
+       /*
+        * As the user may map the buffer once pinned in the display plane
         * (e.g. libkms for the bootup splash), we have to ensure that we
         * always use map_and_fenceable for all scanout buffers. However,
         * it may simply be too big to fit into mappable, in which case
@@ -461,22 +472,19 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
        if (IS_ERR(vma))
                vma = i915_gem_object_ggtt_pin(obj, view, 0, alignment, flags);
        if (IS_ERR(vma))
-               goto err_unpin_global;
+               return vma;
 
        vma->display_alignment = max_t(u64, vma->display_alignment, alignment);
 
        __i915_gem_object_flush_for_display(obj);
 
-       /* It should now be out of any other write domains, and we can update
+       /*
+        * It should now be out of any other write domains, and we can update
         * the domain values for our changes.
         */
        obj->read_domains |= I915_GEM_DOMAIN_GTT;
 
        return vma;
-
-err_unpin_global:
-       obj->pin_global--;
-       return vma;
 }
 
 static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
@@ -491,6 +499,7 @@ static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
                if (!drm_mm_node_allocated(&vma->node))
                        continue;
 
+               GEM_BUG_ON(vma->vm != &i915->ggtt.vm);
                list_move_tail(&vma->vm_link, &vma->vm->bound_list);
        }
        mutex_unlock(&i915->ggtt.vm.mutex);
@@ -500,7 +509,8 @@ static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
 
                spin_lock_irqsave(&i915->mm.obj_lock, flags);
 
-               if (obj->mm.madv == I915_MADV_WILLNEED)
+               if (obj->mm.madv == I915_MADV_WILLNEED &&
+                   !atomic_read(&obj->mm.shrink_pin))
                        list_move_tail(&obj->mm.link, &i915->mm.shrink_list);
 
                spin_unlock_irqrestore(&i915->mm.obj_lock, flags);
@@ -514,12 +524,6 @@ i915_gem_object_unpin_from_display_plane(struct i915_vma *vma)
 
        assert_object_held(obj);
 
-       if (WARN_ON(obj->pin_global == 0))
-               return;
-
-       if (--obj->pin_global == 0)
-               vma->display_alignment = I915_GTT_MIN_ALIGNMENT;
-
        /* Bump the LRU to try and avoid premature eviction whilst flipping  */
        i915_gem_object_bump_inactive_ggtt(obj);