drm/i915: Try GGTT mmapping whole object as partial
authorChris Wilson <chris@chris-wilson.co.uk>
Sat, 30 Jun 2018 09:05:09 +0000 (10:05 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Mon, 2 Jul 2018 16:36:09 +0000 (17:36 +0100)
If the whole object is already pinned by HW for use as scanout, we will
fail to move it to the mappable region and so must resort to using a
partial VMA covering the whole object.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=104513
Fixes: aa136d9d72c2 ("drm/i915: Convert partial ggtt vma to full ggtt if it spans the entire object")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Matthew Auld <matthew.william.auld@gmail.com>
Reviewed-by: Matthew Auld <matthew.william.auld@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180630090509.469-1-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_vma.c

index 8954db6ab083b1f0deedb508b4db3998add05580..048b722cf27cfc28ca6800bbf89fb8c4bf149739 100644 (file)
@@ -2006,7 +2006,6 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
        bool write = !!(vmf->flags & FAULT_FLAG_WRITE);
        struct i915_vma *vma;
        pgoff_t page_offset;
-       unsigned int flags;
        int ret;
 
        /* We don't use vmf->pgoff since that has the fake offset */
@@ -2042,27 +2041,34 @@ vm_fault_t i915_gem_fault(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, flags);
+       vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
+                                      PIN_MAPPABLE |
+                                      PIN_NONBLOCK |
+                                      PIN_NONFAULT);
        if (IS_ERR(vma)) {
                /* Use a partial view if it is bigger than available space */
                struct i915_ggtt_view view =
                        compute_partial_view(obj, page_offset, MIN_CHUNK_PAGES);
+               unsigned int flags;
 
-               /* Userspace is now writing through an untracked VMA, abandon
+               flags = PIN_MAPPABLE;
+               if (view.type == I915_GGTT_VIEW_NORMAL)
+                       flags |= PIN_NONBLOCK; /* avoid warnings for pinned */
+
+               /*
+                * Userspace is now writing through an untracked VMA, abandon
                 * all hope that the hardware is able to track future writes.
                 */
                obj->frontbuffer_ggtt_origin = ORIGIN_CPU;
 
-               vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, PIN_MAPPABLE);
+               vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, flags);
+               if (IS_ERR(vma) && !view.type) {
+                       flags = PIN_MAPPABLE;
+                       view.type = I915_GGTT_VIEW_PARTIAL;
+                       vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, flags);
+               }
        }
        if (IS_ERR(vma)) {
                ret = PTR_ERR(vma);
index d0e606e9b27a4fb87f012ff937ac3a8d20e19b4d..de2b6d65e865e2a99a979a7f9e280dc852408cb8 100644 (file)
@@ -143,7 +143,7 @@ vma_create(struct drm_i915_gem_object *obj,
                                                     obj->base.size >> PAGE_SHIFT));
                        vma->size = view->partial.size;
                        vma->size <<= PAGE_SHIFT;
-                       GEM_BUG_ON(vma->size >= obj->base.size);
+                       GEM_BUG_ON(vma->size > obj->base.size);
                } else if (view->type == I915_GGTT_VIEW_ROTATED) {
                        vma->size = intel_rotation_info_size(&view->rotated);
                        vma->size <<= PAGE_SHIFT;