From: Maarten Lankhorst <[email protected]>

The rotation details belong in xe_fb_pin.c, while the operations involving
GGTT belong to xe_ggtt.c. As directly locking xe_ggtt etc results in
exposing all of xe_ggtt details anyway, create a special function that
allocates a ggtt_node, and allow display to populate it using a callback
as a compromise.

Signed-off-by: Maarten Lankhorst <[email protected]>
Reviewed-by: Matthew Brost <[email protected]>
---
 drivers/gpu/drm/xe/display/xe_fb_pin.c | 111 ++++++++++++-------------
 drivers/gpu/drm/xe/xe_ggtt.c           |  92 ++++++++++++++------
 drivers/gpu/drm/xe/xe_ggtt.h           |   9 +-
 drivers/gpu/drm/xe/xe_ggtt_types.h     |   8 +-
 4 files changed, 132 insertions(+), 88 deletions(-)

diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c 
b/drivers/gpu/drm/xe/display/xe_fb_pin.c
index 6b362695d6b61..99f2863daebb5 100644
--- a/drivers/gpu/drm/xe/display/xe_fb_pin.c
+++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c
@@ -167,12 +167,13 @@ static int __xe_pin_fb_vma_dpt(const struct 
intel_framebuffer *fb,
 }
 
 static void
-write_ggtt_rotated(struct xe_bo *bo, struct xe_ggtt *ggtt, u32 *ggtt_ofs, u32 
bo_ofs,
+write_ggtt_rotated(struct xe_ggtt *ggtt, u32 *ggtt_ofs,
+                  u64 pte_flags,
+                  xe_ggtt_set_pte_fn write_pte,
+                  struct xe_bo *bo, u32 bo_ofs,
                   u32 width, u32 height, u32 src_stride, u32 dst_stride)
 {
-       struct xe_device *xe = xe_bo_device(bo);
        u32 column, row;
-       u64 pte = ggtt->pt_ops->pte_encode_flags(bo, 
xe->pat.idx[XE_CACHE_NONE]);
 
        for (column = 0; column < width; column++) {
                u32 src_idx = src_stride * (height - 1) + column + bo_ofs;
@@ -180,7 +181,7 @@ write_ggtt_rotated(struct xe_bo *bo, struct xe_ggtt *ggtt, 
u32 *ggtt_ofs, u32 bo
                for (row = 0; row < height; row++) {
                        u64 addr = xe_bo_addr(bo, src_idx * XE_PAGE_SIZE, 
XE_PAGE_SIZE);
 
-                       ggtt->pt_ops->ggtt_set_pte(ggtt, *ggtt_ofs, pte | addr);
+                       write_pte(ggtt, *ggtt_ofs, pte_flags | addr);
                        *ggtt_ofs += XE_PAGE_SIZE;
                        src_idx -= src_stride;
                }
@@ -190,6 +191,28 @@ write_ggtt_rotated(struct xe_bo *bo, struct xe_ggtt *ggtt, 
u32 *ggtt_ofs, u32 bo
        }
 }
 
+struct fb_rotate_args {
+       const struct i915_gtt_view *view;
+       struct xe_bo *bo;
+};
+
+static void write_ggtt_rotated_node(struct xe_ggtt *ggtt, struct xe_ggtt_node 
*node,
+                                   u64 pte_flags, xe_ggtt_set_pte_fn 
write_pte, void *data)
+{
+       struct fb_rotate_args *args = data;
+       struct xe_bo *bo = args->bo;
+       const struct intel_rotation_info *rot_info = &args->view->rotated;
+       u32 ggtt_ofs = node->base.start;
+
+       for (u32 i = 0; i < ARRAY_SIZE(rot_info->plane); i++)
+               write_ggtt_rotated(ggtt, &ggtt_ofs, pte_flags, write_pte,
+                                  bo, rot_info->plane[i].offset,
+                                  rot_info->plane[i].width,
+                                  rot_info->plane[i].height,
+                                  rot_info->plane[i].src_stride,
+                                  rot_info->plane[i].dst_stride);
+}
+
 static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb,
                                const struct i915_gtt_view *view,
                                struct i915_vma *vma,
@@ -200,70 +223,40 @@ static int __xe_pin_fb_vma_ggtt(const struct 
intel_framebuffer *fb,
        struct xe_device *xe = to_xe_device(fb->base.dev);
        struct xe_tile *tile0 = xe_device_get_root_tile(xe);
        struct xe_ggtt *ggtt = tile0->mem.ggtt;
+       u64 pte, size;
        u32 align;
-       int ret;
-
-       /* TODO: Consider sharing framebuffer mapping?
-        * embed i915_vma inside intel_framebuffer
-        */
-       xe_pm_runtime_get_noresume(xe);
-       ret = mutex_lock_interruptible(&ggtt->lock);
-       if (ret)
-               goto out;
+       int ret = 0;
 
        align = XE_PAGE_SIZE;
-       if (xe_bo_is_vram(bo) && ggtt->flags & XE_GGTT_FLAGS_64K)
-               align = max_t(u32, align, SZ_64K);
+       if (xe_bo_is_vram(bo) && xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K)
+               align = max(align, SZ_64K);
 
+       /* Fast case, preallocated GGTT view? */
        if (bo->ggtt_node[tile0->id] && view->type == I915_GTT_VIEW_NORMAL) {
                vma->node = bo->ggtt_node[tile0->id];
-       } else if (view->type == I915_GTT_VIEW_NORMAL) {
-               vma->node = xe_ggtt_node_init(ggtt);
-               if (IS_ERR(vma->node)) {
-                       ret = PTR_ERR(vma->node);
-                       goto out_unlock;
-               }
-
-               ret = xe_ggtt_node_insert_locked(vma->node, bo->size, align, 0);
-               if (ret) {
-                       xe_ggtt_node_fini(vma->node);
-                       goto out_unlock;
-               }
-
-               xe_ggtt_map_bo(ggtt, vma->node, bo, xe->pat.idx[XE_CACHE_NONE]);
-       } else {
-               u32 i, ggtt_ofs;
-               const struct intel_rotation_info *rot_info = &view->rotated;
-
-               /* display seems to use tiles instead of bytes here, so convert 
it back.. */
-               u32 size = intel_rotation_info_size(rot_info) * XE_PAGE_SIZE;
-
-               vma->node = xe_ggtt_node_init(ggtt);
-               if (IS_ERR(vma->node)) {
-                       ret = PTR_ERR(vma->node);
-                       goto out_unlock;
-               }
-
-               ret = xe_ggtt_node_insert_locked(vma->node, size, align, 0);
-               if (ret) {
-                       xe_ggtt_node_fini(vma->node);
-                       goto out_unlock;
-               }
+               return 0;
+       }
 
-               ggtt_ofs = vma->node->base.start;
+       /* TODO: Consider sharing framebuffer mapping?
+        * embed i915_vma inside intel_framebuffer
+        */
+       xe_pm_runtime_get_noresume(xe);
 
-               for (i = 0; i < ARRAY_SIZE(rot_info->plane); i++)
-                       write_ggtt_rotated(bo, ggtt, &ggtt_ofs,
-                                          rot_info->plane[i].offset,
-                                          rot_info->plane[i].width,
-                                          rot_info->plane[i].height,
-                                          rot_info->plane[i].src_stride,
-                                          rot_info->plane[i].dst_stride);
-       }
+       if (view->type == I915_GTT_VIEW_NORMAL)
+               size = bo->size;
+       else
+               /* display uses tiles instead of bytes here, so convert it 
back.. */
+               size = intel_rotation_info_size(&view->rotated) * XE_PAGE_SIZE;
+
+       pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe->pat.idx[XE_CACHE_NONE]);
+       vma->node = xe_ggtt_node_insert_transform(ggtt, bo, pte,
+                                                 ALIGN(size, align), align,
+                                                 view->type == 
I915_GTT_VIEW_NORMAL ?
+                                                 NULL : 
write_ggtt_rotated_node,
+                                                 &(struct 
fb_rotate_args){view, bo});
+       if (IS_ERR(vma->node))
+               ret = PTR_ERR(vma->node);
 
-out_unlock:
-       mutex_unlock(&ggtt->lock);
-out:
        xe_pm_runtime_put(xe);
        return ret;
 }
diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c
index 4c58626f002f9..c9ee2a4ff8ab9 100644
--- a/drivers/gpu/drm/xe/xe_ggtt.c
+++ b/drivers/gpu/drm/xe/xe_ggtt.c
@@ -479,19 +479,7 @@ void xe_ggtt_shift_nodes(struct xe_ggtt *ggtt, s64 shift)
        mutex_unlock(&ggtt->lock);
 }
 
-/**
- * xe_ggtt_node_insert_locked - Locked version to insert a &xe_ggtt_node into 
the GGTT
- * @node: the &xe_ggtt_node to be inserted
- * @size: size of the node
- * @align: alignment constrain of the node
- * @mm_flags: flags to control the node behavior
- *
- * It cannot be called without first having called xe_ggtt_init() once.
- * To be used in cases where ggtt->lock is already taken.
- *
- * Return: 0 on success or a negative error code on failure.
- */
-int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node,
+static int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node,
                               u32 size, u32 align, u32 mm_flags)
 {
        return drm_mm_insert_node_generic(&node->ggtt->mm, &node->base, size, 
align, 0,
@@ -528,9 +516,13 @@ int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 
size, u32 align)
  * @ggtt: the &xe_ggtt where the new node will later be inserted/reserved.
  *
  * This function will allocate the struct %xe_ggtt_node and return its pointer.
- * This struct will then be freed after the node removal upon 
xe_ggtt_node_remove().
- * Having %xe_ggtt_node struct allocated doesn't mean that the node is already 
allocated
- * in GGTT. Only xe_ggtt_node_insert() will ensure the node is inserted or 
reserved in GGTT.
+ * This struct will then be freed after the node removal upon
+ * xe_ggtt_node_remove().
+ *
+ * Having %xe_ggtt_node struct allocated doesn't mean that the node is already
+ * allocated in GGTT. Only xe_ggtt_node_insert() or allocation through
+ * xe_ggtt_node_insert_transform() will ensure the node is inserted or reserved
+ * in GGTT.
  *
  * Return: A pointer to %xe_ggtt_node struct on success. An ERR_PTR otherwise.
  **/
@@ -579,13 +571,12 @@ bool xe_ggtt_node_allocated(const struct xe_ggtt_node 
*node)
  * @ggtt: the &xe_ggtt where node will be mapped
  * @node: the &xe_ggtt_node where this BO is mapped
  * @bo: the &xe_bo to be mapped
- * @pat_index: Which pat_index to use.
+ * @pte: The pte flags to append.
  */
-void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node,
-                   struct xe_bo *bo, u16 pat_index)
+static void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node,
+                          struct xe_bo *bo, u64 pte)
 {
-
-       u64 start, pte, end;
+       u64 start, end;
        struct xe_res_cursor cur;
 
        if (XE_WARN_ON(!node))
@@ -594,7 +585,6 @@ void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct 
xe_ggtt_node *node,
        start = node->base.start;
        end = start + bo->size;
 
-       pte = ggtt->pt_ops->pte_encode_flags(bo, pat_index);
        if (!xe_bo_is_vram(bo) && !xe_bo_is_stolen(bo)) {
                xe_assert(xe_bo_device(bo), bo->ttm.ttm);
 
@@ -624,12 +614,65 @@ void xe_ggtt_map_bo_unlocked(struct xe_ggtt *ggtt, struct 
xe_bo *bo)
 {
        u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : 
XE_CACHE_WB;
        u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode];
+       u64 pte;
 
        mutex_lock(&ggtt->lock);
-       xe_ggtt_map_bo(ggtt, bo->ggtt_node[ggtt->tile->id], bo, pat_index);
+       pte = ggtt->pt_ops->pte_encode_flags(bo, pat_index);
+       xe_ggtt_map_bo(ggtt, bo->ggtt_node[ggtt->tile->id], bo, pte);
        mutex_unlock(&ggtt->lock);
 }
 
+/**
+ * xe_ggtt_node_insert_transform - Insert a newly allocated &xe_ggtt_node into 
the GGTT
+ * @ggtt: the &xe_ggtt where the node will inserted/reserved.
+ * @bo: The bo to be transformed
+ * @pte_flags: The extra GGTT flags to add to mapping.
+ * @size: size of the node
+ * @align: required alignment for node
+ * @transform: transformation function that will populate the GGTT node, or 
NULL for linear mapping.
+ * @arg: Extra argument to pass to the transformation function.
+ *
+ * This function allows inserting a GGTT node with a custom transformation 
function.
+ * This is useful for display to allow inserting rotated framebuffers to GGTT.
+ *
+ * Return: A pointer to %xe_ggtt_node struct on success. An ERR_PTR otherwise.
+ */
+struct xe_ggtt_node *xe_ggtt_node_insert_transform(struct xe_ggtt *ggtt,
+                                                  struct xe_bo *bo, u64 
pte_flags,
+                                                  u64 size, u32 align,
+                                                  xe_ggtt_transform_cb 
transform, void *arg)
+{
+       struct xe_ggtt_node *node;
+       int ret;
+
+       node = xe_ggtt_node_init(ggtt);
+       if (IS_ERR(node))
+               return ERR_CAST(node);
+
+       if (mutex_lock_interruptible(&ggtt->lock) < 0) {
+               ret = -ERESTARTSYS;
+               goto err;
+       }
+
+       ret = xe_ggtt_node_insert_locked(node, size, align, 0);
+       if (ret)
+               goto err_unlock;
+
+       if (transform)
+               transform(ggtt, node, pte_flags, ggtt->pt_ops->ggtt_set_pte, 
arg);
+       else
+               xe_ggtt_map_bo(ggtt, node, bo, pte_flags);
+
+       mutex_unlock(&ggtt->lock);
+       return node;
+
+err_unlock:
+       mutex_unlock(&ggtt->lock);
+err:
+       xe_ggtt_node_fini(node);
+       return ERR_PTR(ret);
+}
+
 static int __xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo,
                                  u64 start, u64 end)
 {
@@ -668,8 +711,9 @@ static int __xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, 
struct xe_bo *bo,
        } else {
                u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? 
XE_CACHE_NONE : XE_CACHE_WB;
                u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode];
+               u64 pte = ggtt->pt_ops->pte_encode_flags(bo, pat_index);
 
-               xe_ggtt_map_bo(ggtt, bo->ggtt_node[tile_id], bo, pat_index);
+               xe_ggtt_map_bo(ggtt, bo->ggtt_node[tile_id], bo, pte);
        }
        mutex_unlock(&ggtt->lock);
 
diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h
index c00d6c8f687ac..e25b40845456d 100644
--- a/drivers/gpu/drm/xe/xe_ggtt.h
+++ b/drivers/gpu/drm/xe/xe_ggtt.h
@@ -21,12 +21,13 @@ void xe_ggtt_node_fini(struct xe_ggtt_node *node);
 void xe_ggtt_shift_nodes(struct xe_ggtt *ggtt, s64 shift);
 
 int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align);
-int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node,
-                              u32 size, u32 align, u32 mm_flags);
+struct xe_ggtt_node *
+xe_ggtt_node_insert_transform(struct xe_ggtt *ggtt,
+                             struct xe_bo *bo, u64 pte,
+                             u64 size, u32 align,
+                             xe_ggtt_transform_cb transform, void *arg);
 void xe_ggtt_node_remove(struct xe_ggtt_node *node, bool invalidate);
 bool xe_ggtt_node_allocated(const struct xe_ggtt_node *node);
-void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node,
-                   struct xe_bo *bo, u16 pat_index);
 void xe_ggtt_map_bo_unlocked(struct xe_ggtt *ggtt, struct xe_bo *bo);
 int xe_ggtt_insert_bo(struct xe_ggtt *ggtt, struct xe_bo *bo);
 int xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo,
diff --git a/drivers/gpu/drm/xe/xe_ggtt_types.h 
b/drivers/gpu/drm/xe/xe_ggtt_types.h
index a27919302d6b2..f4aa5671cb3e3 100644
--- a/drivers/gpu/drm/xe/xe_ggtt_types.h
+++ b/drivers/gpu/drm/xe/xe_ggtt_types.h
@@ -71,6 +71,11 @@ struct xe_ggtt_node {
        bool invalidate_on_remove;
 };
 
+typedef void (*xe_ggtt_set_pte_fn)(struct xe_ggtt *ggtt, u64 addr, u64 pte);
+typedef void (*xe_ggtt_transform_cb)(struct xe_ggtt *ggtt,
+                                    struct xe_ggtt_node *node,
+                                    u64 pte_flags,
+                                    xe_ggtt_set_pte_fn set_pte, void *arg);
 /**
  * struct xe_ggtt_pt_ops - GGTT Page table operations
  * Which can vary from platform to platform.
@@ -78,8 +83,9 @@ struct xe_ggtt_node {
 struct xe_ggtt_pt_ops {
        /** @pte_encode_flags: Encode PTE flags for a given BO */
        u64 (*pte_encode_flags)(struct xe_bo *bo, u16 pat_index);
+
        /** @ggtt_set_pte: Directly write into GGTT's PTE */
-       void (*ggtt_set_pte)(struct xe_ggtt *ggtt, u64 addr, u64 pte);
+       xe_ggtt_set_pte_fn ggtt_set_pte;
 };
 
 #endif
-- 
2.45.2

Reply via email to