]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
drm/i915: Add a new "remapped" gtt_view
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Thu, 9 May 2019 12:21:52 +0000 (15:21 +0300)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Mon, 20 May 2019 15:04:47 +0000 (18:04 +0300)
To overcome display engine stride limits we'll want to remap the
pages in the GTT. To that end we need a new gtt_view type which
is just like the "rotated" type except not rotated.

v2: Use intel_remapped_plane_info base type
    s/unused/unused_mbz/ (Chris)
    Separate BUILD_BUG_ON()s (Chris)
    Use I915_GTT_PAGE_SIZE (Chris)
v3: Use i915_gem_object_get_dma_address() (Chris)
    Trim the sg (Tvrtko)
v4: Actually trim this time. Limit the max length
    to one row of pages to keep things simple

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190509122159.24376-2-ville.syrjala@linux.intel.com
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_gtt.h
drivers/gpu/drm/i915/i915_vma.c
drivers/gpu/drm/i915/i915_vma.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/selftests/i915_vma.c

index 072464a18050a3fa46134996f66157b4b0f67951..633a08c0f9079f65051b41557bf8946602d4c6a2 100644 (file)
@@ -212,6 +212,18 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
                                           vma->ggtt_view.rotated.plane[1].offset);
                                break;
 
+                       case I915_GGTT_VIEW_REMAPPED:
+                               seq_printf(m, ", remapped [(%ux%u, stride=%u, offset=%u), (%ux%u, stride=%u, offset=%u)]",
+                                          vma->ggtt_view.remapped.plane[0].width,
+                                          vma->ggtt_view.remapped.plane[0].height,
+                                          vma->ggtt_view.remapped.plane[0].stride,
+                                          vma->ggtt_view.remapped.plane[0].offset,
+                                          vma->ggtt_view.remapped.plane[1].width,
+                                          vma->ggtt_view.remapped.plane[1].height,
+                                          vma->ggtt_view.remapped.plane[1].stride,
+                                          vma->ggtt_view.remapped.plane[1].offset);
+                               break;
+
                        default:
                                MISSING_CASE(vma->ggtt_view.type);
                                break;
index 5801f5407589381c544afdf9b691db48ca9230dd..1ad3818d267614a6048d7932e4ecc3e79f024249 100644 (file)
@@ -2864,6 +2864,10 @@ i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
                               unsigned int n);
 
 dma_addr_t
+i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
+                                   unsigned long n,
+                                   unsigned int *len);
+dma_addr_t
 i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
                                unsigned long n);
 
index 2fcec1bfb0386fb5d79921d245bc9662ed2613d0..4e474bcf4c227fd9c6d06b760753b676d8808189 100644 (file)
@@ -5081,16 +5081,29 @@ i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
 }
 
 dma_addr_t
-i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
-                               unsigned long n)
+i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
+                                   unsigned long n,
+                                   unsigned int *len)
 {
        struct scatterlist *sg;
        unsigned int offset;
 
        sg = i915_gem_object_get_sg(obj, n, &offset);
+
+       if (len)
+               *len = sg_dma_len(sg) - (offset << PAGE_SHIFT);
+
        return sg_dma_address(sg) + (offset << PAGE_SHIFT);
 }
 
+dma_addr_t
+i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
+                               unsigned long n)
+{
+       return i915_gem_object_get_dma_address_len(obj, n, NULL);
+}
+
+
 int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align)
 {
        struct sg_table *pages;
index 8f5db787b7f277dfc2dc3defc317afe125b74ff7..9ed41aefb4563e28d4fcd2e738ab03d553bfa3f7 100644 (file)
@@ -3608,6 +3608,89 @@ err_st_alloc:
        return ERR_PTR(ret);
 }
 
+static struct scatterlist *
+remap_pages(struct drm_i915_gem_object *obj, unsigned int offset,
+           unsigned int width, unsigned int height,
+           unsigned int stride,
+           struct sg_table *st, struct scatterlist *sg)
+{
+       unsigned int row;
+
+       for (row = 0; row < height; row++) {
+               unsigned int left = width * I915_GTT_PAGE_SIZE;
+
+               while (left) {
+                       dma_addr_t addr;
+                       unsigned int length;
+
+                       /* We don't need the pages, but need to initialize
+                        * the entries so the sg list can be happily traversed.
+                        * The only thing we need are DMA addresses.
+                        */
+
+                       addr = i915_gem_object_get_dma_address_len(obj, offset, &length);
+
+                       length = min(left, length);
+
+                       st->nents++;
+
+                       sg_set_page(sg, NULL, length, 0);
+                       sg_dma_address(sg) = addr;
+                       sg_dma_len(sg) = length;
+                       sg = sg_next(sg);
+
+                       offset += length / I915_GTT_PAGE_SIZE;
+                       left -= length;
+               }
+
+               offset += stride - width;
+       }
+
+       return sg;
+}
+
+static noinline struct sg_table *
+intel_remap_pages(struct intel_remapped_info *rem_info,
+                 struct drm_i915_gem_object *obj)
+{
+       unsigned int size = intel_remapped_info_size(rem_info);
+       struct sg_table *st;
+       struct scatterlist *sg;
+       int ret = -ENOMEM;
+       int i;
+
+       /* Allocate target SG list. */
+       st = kmalloc(sizeof(*st), GFP_KERNEL);
+       if (!st)
+               goto err_st_alloc;
+
+       ret = sg_alloc_table(st, size, GFP_KERNEL);
+       if (ret)
+               goto err_sg_alloc;
+
+       st->nents = 0;
+       sg = st->sgl;
+
+       for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++) {
+               sg = remap_pages(obj, rem_info->plane[i].offset,
+                                rem_info->plane[i].width, rem_info->plane[i].height,
+                                rem_info->plane[i].stride, st, sg);
+       }
+
+       i915_sg_trim(st);
+
+       return st;
+
+err_sg_alloc:
+       kfree(st);
+err_st_alloc:
+
+       DRM_DEBUG_DRIVER("Failed to create remapped mapping for object size %zu! (%ux%u tiles, %u pages)\n",
+                        obj->base.size, rem_info->plane[0].width, rem_info->plane[0].height, size);
+
+       return ERR_PTR(ret);
+}
+
 static noinline struct sg_table *
 intel_partial_pages(const struct i915_ggtt_view *view,
                    struct drm_i915_gem_object *obj)
@@ -3686,6 +3769,11 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma)
                        intel_rotate_pages(&vma->ggtt_view.rotated, vma->obj);
                break;
 
+       case I915_GGTT_VIEW_REMAPPED:
+               vma->pages =
+                       intel_remap_pages(&vma->ggtt_view.remapped, vma->obj);
+               break;
+
        case I915_GGTT_VIEW_PARTIAL:
                vma->pages = intel_partial_pages(&vma->ggtt_view, vma->obj);
                break;
index 2fafa04c45ec099990aa80dd2d28c272cc4a503a..98fc71053f7c9a7d4d4ef63aa71d2509f67149ea 100644 (file)
@@ -163,11 +163,18 @@ typedef u64 gen8_ppgtt_pml4e_t;
 
 struct sg_table;
 
+struct intel_remapped_plane_info {
+       /* in gtt pages */
+       unsigned int width, height, stride, offset;
+} __packed;
+
+struct intel_remapped_info {
+       struct intel_remapped_plane_info plane[2];
+       unsigned int unused_mbz;
+} __packed;
+
 struct intel_rotation_info {
-       struct intel_rotation_plane_info {
-               /* tiles */
-               unsigned int width, height, stride, offset;
-       } plane[2];
+       struct intel_remapped_plane_info plane[2];
 } __packed;
 
 struct intel_partial_info {
@@ -179,12 +186,20 @@ enum i915_ggtt_view_type {
        I915_GGTT_VIEW_NORMAL = 0,
        I915_GGTT_VIEW_ROTATED = sizeof(struct intel_rotation_info),
        I915_GGTT_VIEW_PARTIAL = sizeof(struct intel_partial_info),
+       I915_GGTT_VIEW_REMAPPED = sizeof(struct intel_remapped_info),
 };
 
 static inline void assert_i915_gem_gtt_types(void)
 {
        BUILD_BUG_ON(sizeof(struct intel_rotation_info) != 8*sizeof(unsigned int));
        BUILD_BUG_ON(sizeof(struct intel_partial_info) != sizeof(u64) + sizeof(unsigned int));
+       BUILD_BUG_ON(sizeof(struct intel_remapped_info) != 9*sizeof(unsigned int));
+
+       /* Check that rotation/remapped shares offsets for simplicity */
+       BUILD_BUG_ON(offsetof(struct intel_remapped_info, plane[0]) !=
+                    offsetof(struct intel_rotation_info, plane[0]));
+       BUILD_BUG_ON(offsetofend(struct intel_remapped_info, plane[1]) !=
+                    offsetofend(struct intel_rotation_info, plane[1]));
 
        /* As we encode the size of each branch inside the union into its type,
         * we have to be careful that each branch has a unique size.
@@ -193,6 +208,7 @@ static inline void assert_i915_gem_gtt_types(void)
        case I915_GGTT_VIEW_NORMAL:
        case I915_GGTT_VIEW_PARTIAL:
        case I915_GGTT_VIEW_ROTATED:
+       case I915_GGTT_VIEW_REMAPPED:
                /* gcc complains if these are identical cases */
                break;
        }
@@ -204,6 +220,7 @@ struct i915_ggtt_view {
                /* Members need to contain no holes/padding */
                struct intel_partial_info partial;
                struct intel_rotation_info rotated;
+               struct intel_remapped_info remapped;
        };
 };
 
index d4d308b6d1d87d5646e3853b17e3ad67fad775ef..c68b435d406484596e202b5517f37e6b736f1f20 100644 (file)
@@ -159,6 +159,9 @@ vma_create(struct drm_i915_gem_object *obj,
                } else if (view->type == I915_GGTT_VIEW_ROTATED) {
                        vma->size = intel_rotation_info_size(&view->rotated);
                        vma->size <<= PAGE_SHIFT;
+               } else if (view->type == I915_GGTT_VIEW_REMAPPED) {
+                       vma->size = intel_remapped_info_size(&view->remapped);
+                       vma->size <<= PAGE_SHIFT;
                }
        }
 
@@ -484,7 +487,8 @@ void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
         * Explicitly disable for rotated VMA since the display does not
         * need the fence and the VMA is not accessible to other users.
         */
-       if (vma->ggtt_view.type == I915_GGTT_VIEW_ROTATED)
+       if (vma->ggtt_view.type == I915_GGTT_VIEW_ROTATED ||
+           vma->ggtt_view.type == I915_GGTT_VIEW_REMAPPED)
                return;
 
        fenceable = (vma->node.size >= vma->fence_size &&
index 6eab70953a57f7c254da4f386da1a15de055a81f..8543d2953cd1962b3daab91dc15e112d6c93ed36 100644 (file)
@@ -277,8 +277,11 @@ i915_vma_compare(struct i915_vma *vma,
         */
        BUILD_BUG_ON(I915_GGTT_VIEW_NORMAL >= I915_GGTT_VIEW_PARTIAL);
        BUILD_BUG_ON(I915_GGTT_VIEW_PARTIAL >= I915_GGTT_VIEW_ROTATED);
+       BUILD_BUG_ON(I915_GGTT_VIEW_ROTATED >= I915_GGTT_VIEW_REMAPPED);
        BUILD_BUG_ON(offsetof(typeof(*view), rotated) !=
                     offsetof(typeof(*view), partial));
+       BUILD_BUG_ON(offsetof(typeof(*view), rotated) !=
+                    offsetof(typeof(*view), remapped));
        return memcmp(&vma->ggtt_view.partial, &view->partial, view->type);
 }
 
index b53676e558cbf570ae451fbafdcb14b6494f9256..95c850d7faab9e4de2a23d1897f666599ddcaa7d 100644 (file)
@@ -1997,6 +1997,17 @@ unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info
        return size;
 }
 
+unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info)
+{
+       unsigned int size = 0;
+       int i;
+
+       for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++)
+               size += rem_info->plane[i].width * rem_info->plane[i].height;
+
+       return size;
+}
+
 static void
 intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
                        const struct drm_framebuffer *fb,
index 30b2d6ed2d5311c97e98a578ef57d2c9cc50a4d4..270f5bb43d9ba89a00a4d217d07b7acf3785b240 100644 (file)
@@ -1461,6 +1461,7 @@ unsigned int intel_fb_align_height(const struct drm_framebuffer *fb,
 void intel_add_fb_offsets(int *x, int *y,
                          const struct intel_plane_state *state, int plane);
 unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info);
+unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info);
 bool intel_has_pending_fb_unpin(struct drm_i915_private *dev_priv);
 void intel_mark_busy(struct drm_i915_private *dev_priv);
 void intel_mark_idle(struct drm_i915_private *dev_priv);
index fc594b030f5a71029cfdef8b134cffc5ec564abb..18dc221cb22b232cce01a23c8e570d66afdcf1ad 100644 (file)
@@ -397,8 +397,8 @@ assert_rotated(struct drm_i915_gem_object *obj,
        return sg;
 }
 
-static unsigned int rotated_size(const struct intel_rotation_plane_info *a,
-                                const struct intel_rotation_plane_info *b)
+static unsigned int rotated_size(const struct intel_remapped_plane_info *a,
+                                const struct intel_remapped_plane_info *b)
 {
        return a->width * a->height + b->width * b->height;
 }
@@ -408,7 +408,7 @@ static int igt_vma_rotate(void *arg)
        struct i915_ggtt *ggtt = arg;
        struct i915_address_space *vm = &ggtt->vm;
        struct drm_i915_gem_object *obj;
-       const struct intel_rotation_plane_info planes[] = {
+       const struct intel_remapped_plane_info planes[] = {
                { .width = 1, .height = 1, .stride = 1 },
                { .width = 2, .height = 2, .stride = 2 },
                { .width = 4, .height = 4, .stride = 4 },