Skip to content

Commit 004311a

Browse files
author
Maarten Lankhorst
committed
drm/xe: Convert xe_fb_pin to use a callback for insertion into GGTT
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 <maarten.lankhorst@linux.intel.com> Reviewed-by: Matthew Brost <matthew.brost@intel.com> Reviewed-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com> Signed-off-by: Maarten Lankhorst <dev@lankhorst.se> Link: https://patch.msgid.link/20260108101014.579906-11-dev@lankhorst.se
1 parent 22437f3 commit 004311a

4 files changed

Lines changed: 131 additions & 81 deletions

File tree

drivers/gpu/drm/xe/display/xe_fb_pin.c

Lines changed: 51 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -171,20 +171,21 @@ static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb,
171171
}
172172

173173
static void
174-
write_ggtt_rotated(struct xe_bo *bo, struct xe_ggtt *ggtt, u32 *ggtt_ofs, u32 bo_ofs,
174+
write_ggtt_rotated(struct xe_ggtt *ggtt, u32 *ggtt_ofs,
175+
u64 pte_flags,
176+
xe_ggtt_set_pte_fn write_pte,
177+
struct xe_bo *bo, u32 bo_ofs,
175178
u32 width, u32 height, u32 src_stride, u32 dst_stride)
176179
{
177-
struct xe_device *xe = xe_bo_device(bo);
178180
u32 column, row;
179-
u64 pte = ggtt->pt_ops->pte_encode_flags(bo, xe->pat.idx[XE_CACHE_NONE]);
180181

181182
for (column = 0; column < width; column++) {
182183
u32 src_idx = src_stride * (height - 1) + column + bo_ofs;
183184

184185
for (row = 0; row < height; row++) {
185186
u64 addr = xe_bo_addr(bo, src_idx * XE_PAGE_SIZE, XE_PAGE_SIZE);
186187

187-
ggtt->pt_ops->ggtt_set_pte(ggtt, *ggtt_ofs, pte | addr);
188+
write_pte(ggtt, *ggtt_ofs, pte_flags | addr);
188189
*ggtt_ofs += XE_PAGE_SIZE;
189190
src_idx -= src_stride;
190191
}
@@ -194,6 +195,28 @@ write_ggtt_rotated(struct xe_bo *bo, struct xe_ggtt *ggtt, u32 *ggtt_ofs, u32 bo
194195
}
195196
}
196197

198+
struct fb_rotate_args {
199+
const struct i915_gtt_view *view;
200+
struct xe_bo *bo;
201+
};
202+
203+
static void write_ggtt_rotated_node(struct xe_ggtt *ggtt, struct xe_ggtt_node *node,
204+
u64 pte_flags, xe_ggtt_set_pte_fn write_pte, void *data)
205+
{
206+
struct fb_rotate_args *args = data;
207+
struct xe_bo *bo = args->bo;
208+
const struct intel_rotation_info *rot_info = &args->view->rotated;
209+
u32 ggtt_ofs = node->base.start;
210+
211+
for (u32 i = 0; i < ARRAY_SIZE(rot_info->plane); i++)
212+
write_ggtt_rotated(ggtt, &ggtt_ofs, pte_flags, write_pte,
213+
bo, rot_info->plane[i].offset,
214+
rot_info->plane[i].width,
215+
rot_info->plane[i].height,
216+
rot_info->plane[i].src_stride,
217+
rot_info->plane[i].dst_stride);
218+
}
219+
197220
static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb,
198221
const struct i915_gtt_view *view,
199222
struct i915_vma *vma,
@@ -204,66 +227,43 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb,
204227
struct xe_device *xe = to_xe_device(fb->base.dev);
205228
struct xe_tile *tile0 = xe_device_get_root_tile(xe);
206229
struct xe_ggtt *ggtt = tile0->mem.ggtt;
230+
u64 pte, size;
207231
u32 align;
208-
int ret;
232+
int ret = 0;
209233

210234
/* TODO: Consider sharing framebuffer mapping?
211235
* embed i915_vma inside intel_framebuffer
212236
*/
213237
guard(xe_pm_runtime_noresume)(xe);
214-
ACQUIRE(mutex_intr, lock)(&ggtt->lock);
215-
ret = ACQUIRE_ERR(mutex_intr, &lock);
216-
if (ret)
217-
return ret;
218238

219239
align = XE_PAGE_SIZE;
220-
if (xe_bo_is_vram(bo) && ggtt->flags & XE_GGTT_FLAGS_64K)
221-
align = max_t(u32, align, SZ_64K);
240+
if (xe_bo_is_vram(bo) && xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K)
241+
align = max(align, SZ_64K);
222242

243+
/* Fast case, preallocated GGTT view? */
223244
if (bo->ggtt_node[tile0->id] && view->type == I915_GTT_VIEW_NORMAL) {
224245
vma->node = bo->ggtt_node[tile0->id];
225-
} else if (view->type == I915_GTT_VIEW_NORMAL) {
226-
vma->node = xe_ggtt_node_init(ggtt);
227-
if (IS_ERR(vma->node))
228-
return PTR_ERR(vma->node);
229-
230-
ret = xe_ggtt_node_insert_locked(vma->node, xe_bo_size(bo), align, 0);
231-
if (ret) {
232-
xe_ggtt_node_fini(vma->node);
233-
return ret;
234-
}
235-
236-
xe_ggtt_map_bo(ggtt, vma->node, bo, xe->pat.idx[XE_CACHE_NONE]);
237-
} else {
238-
u32 i, ggtt_ofs;
239-
const struct intel_rotation_info *rot_info = &view->rotated;
240-
241-
/* display seems to use tiles instead of bytes here, so convert it back.. */
242-
u32 size = intel_rotation_info_size(rot_info) * XE_PAGE_SIZE;
243-
244-
vma->node = xe_ggtt_node_init(ggtt);
245-
if (IS_ERR(vma->node)) {
246-
ret = PTR_ERR(vma->node);
247-
return ret;
248-
}
249-
250-
ret = xe_ggtt_node_insert_locked(vma->node, size, align, 0);
251-
if (ret) {
252-
xe_ggtt_node_fini(vma->node);
253-
return ret;
254-
}
255-
256-
ggtt_ofs = vma->node->base.start;
257-
258-
for (i = 0; i < ARRAY_SIZE(rot_info->plane); i++)
259-
write_ggtt_rotated(bo, ggtt, &ggtt_ofs,
260-
rot_info->plane[i].offset,
261-
rot_info->plane[i].width,
262-
rot_info->plane[i].height,
263-
rot_info->plane[i].src_stride,
264-
rot_info->plane[i].dst_stride);
246+
return 0;
265247
}
266248

249+
/* TODO: Consider sharing framebuffer mapping?
250+
* embed i915_vma inside intel_framebuffer
251+
*/
252+
if (view->type == I915_GTT_VIEW_NORMAL)
253+
size = xe_bo_size(bo);
254+
else
255+
/* display uses tiles instead of bytes here, so convert it back.. */
256+
size = intel_rotation_info_size(&view->rotated) * XE_PAGE_SIZE;
257+
258+
pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe->pat.idx[XE_CACHE_NONE]);
259+
vma->node = xe_ggtt_node_insert_transform(ggtt, bo, pte,
260+
ALIGN(size, align), align,
261+
view->type == I915_GTT_VIEW_NORMAL ?
262+
NULL : write_ggtt_rotated_node,
263+
&(struct fb_rotate_args){view, bo});
264+
if (IS_ERR(vma->node))
265+
ret = PTR_ERR(vma->node);
266+
267267
return ret;
268268
}
269269

drivers/gpu/drm/xe/xe_ggtt.c

Lines changed: 67 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -636,20 +636,8 @@ void xe_ggtt_shift_nodes_locked(struct xe_ggtt *ggtt, s64 shift)
636636
}
637637
}
638638

639-
/**
640-
* xe_ggtt_node_insert_locked - Locked version to insert a &xe_ggtt_node into the GGTT
641-
* @node: the &xe_ggtt_node to be inserted
642-
* @size: size of the node
643-
* @align: alignment constrain of the node
644-
* @mm_flags: flags to control the node behavior
645-
*
646-
* It cannot be called without first having called xe_ggtt_init() once.
647-
* To be used in cases where ggtt->lock is already taken.
648-
*
649-
* Return: 0 on success or a negative error code on failure.
650-
*/
651-
int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node,
652-
u32 size, u32 align, u32 mm_flags)
639+
static int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node,
640+
u32 size, u32 align, u32 mm_flags)
653641
{
654642
return drm_mm_insert_node_generic(&node->ggtt->mm, &node->base, size, align, 0,
655643
mm_flags);
@@ -687,9 +675,11 @@ int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align)
687675
* This function will allocate the struct %xe_ggtt_node and return its pointer.
688676
* This struct will then be freed after the node removal upon xe_ggtt_node_remove()
689677
* or xe_ggtt_node_remove_balloon_locked().
690-
* Having %xe_ggtt_node struct allocated doesn't mean that the node is already allocated
691-
* in GGTT. Only the xe_ggtt_node_insert(), xe_ggtt_node_insert_locked(),
692-
* xe_ggtt_node_insert_balloon_locked() will ensure the node is inserted or reserved in GGTT.
678+
*
679+
* Having %xe_ggtt_node struct allocated doesn't mean that the node is already
680+
* allocated in GGTT. Only xe_ggtt_node_insert(), allocation through
681+
* xe_ggtt_node_insert_transform(), or xe_ggtt_node_insert_balloon_locked() will ensure the node is inserted or reserved
682+
* in GGTT.
693683
*
694684
* Return: A pointer to %xe_ggtt_node struct on success. An ERR_PTR otherwise.
695685
**/
@@ -752,13 +742,12 @@ size_t xe_ggtt_node_pt_size(const struct xe_ggtt_node *node)
752742
* @ggtt: the &xe_ggtt where node will be mapped
753743
* @node: the &xe_ggtt_node where this BO is mapped
754744
* @bo: the &xe_bo to be mapped
755-
* @pat_index: Which pat_index to use.
745+
* @pte: The pte flags to append.
756746
*/
757-
void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node,
758-
struct xe_bo *bo, u16 pat_index)
747+
static void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node,
748+
struct xe_bo *bo, u64 pte)
759749
{
760-
761-
u64 start, pte, end;
750+
u64 start, end;
762751
struct xe_res_cursor cur;
763752

764753
if (XE_WARN_ON(!node))
@@ -767,7 +756,6 @@ void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node,
767756
start = node->base.start;
768757
end = start + xe_bo_size(bo);
769758

770-
pte = ggtt->pt_ops->pte_encode_flags(bo, pat_index);
771759
if (!xe_bo_is_vram(bo) && !xe_bo_is_stolen(bo)) {
772760
xe_assert(xe_bo_device(bo), bo->ttm.ttm);
773761

@@ -797,10 +785,63 @@ void xe_ggtt_map_bo_unlocked(struct xe_ggtt *ggtt, struct xe_bo *bo)
797785
{
798786
u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : XE_CACHE_WB;
799787
u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode];
788+
u64 pte;
800789

801790
mutex_lock(&ggtt->lock);
802-
xe_ggtt_map_bo(ggtt, bo->ggtt_node[ggtt->tile->id], bo, pat_index);
791+
pte = ggtt->pt_ops->pte_encode_flags(bo, pat_index);
792+
xe_ggtt_map_bo(ggtt, bo->ggtt_node[ggtt->tile->id], bo, pte);
793+
mutex_unlock(&ggtt->lock);
794+
}
795+
796+
/**
797+
* xe_ggtt_node_insert_transform - Insert a newly allocated &xe_ggtt_node into the GGTT
798+
* @ggtt: the &xe_ggtt where the node will inserted/reserved.
799+
* @bo: The bo to be transformed
800+
* @pte_flags: The extra GGTT flags to add to mapping.
801+
* @size: size of the node
802+
* @align: required alignment for node
803+
* @transform: transformation function that will populate the GGTT node, or NULL for linear mapping.
804+
* @arg: Extra argument to pass to the transformation function.
805+
*
806+
* This function allows inserting a GGTT node with a custom transformation function.
807+
* This is useful for display to allow inserting rotated framebuffers to GGTT.
808+
*
809+
* Return: A pointer to %xe_ggtt_node struct on success. An ERR_PTR otherwise.
810+
*/
811+
struct xe_ggtt_node *xe_ggtt_node_insert_transform(struct xe_ggtt *ggtt,
812+
struct xe_bo *bo, u64 pte_flags,
813+
u64 size, u32 align,
814+
xe_ggtt_transform_cb transform, void *arg)
815+
{
816+
struct xe_ggtt_node *node;
817+
int ret;
818+
819+
node = xe_ggtt_node_init(ggtt);
820+
if (IS_ERR(node))
821+
return ERR_CAST(node);
822+
823+
if (mutex_lock_interruptible(&ggtt->lock) < 0) {
824+
ret = -ERESTARTSYS;
825+
goto err;
826+
}
827+
828+
ret = xe_ggtt_node_insert_locked(node, size, align, 0);
829+
if (ret)
830+
goto err_unlock;
831+
832+
if (transform)
833+
transform(ggtt, node, pte_flags, ggtt->pt_ops->ggtt_set_pte, arg);
834+
else
835+
xe_ggtt_map_bo(ggtt, node, bo, pte_flags);
836+
803837
mutex_unlock(&ggtt->lock);
838+
return node;
839+
840+
err_unlock:
841+
mutex_unlock(&ggtt->lock);
842+
err:
843+
xe_ggtt_node_fini(node);
844+
return ERR_PTR(ret);
804845
}
805846

806847
static int __xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo,
@@ -841,8 +882,9 @@ static int __xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo,
841882
} else {
842883
u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : XE_CACHE_WB;
843884
u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode];
885+
u64 pte = ggtt->pt_ops->pte_encode_flags(bo, pat_index);
844886

845-
xe_ggtt_map_bo(ggtt, bo->ggtt_node[tile_id], bo, pat_index);
887+
xe_ggtt_map_bo(ggtt, bo->ggtt_node[tile_id], bo, pte);
846888
}
847889
mutex_unlock(&ggtt->lock);
848890

drivers/gpu/drm/xe/xe_ggtt.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,14 @@ u64 xe_ggtt_start(struct xe_ggtt *ggtt);
2727
u64 xe_ggtt_size(struct xe_ggtt *ggtt);
2828

2929
int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align);
30-
int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node,
31-
u32 size, u32 align, u32 mm_flags);
30+
struct xe_ggtt_node *
31+
xe_ggtt_node_insert_transform(struct xe_ggtt *ggtt,
32+
struct xe_bo *bo, u64 pte,
33+
u64 size, u32 align,
34+
xe_ggtt_transform_cb transform, void *arg);
3235
void xe_ggtt_node_remove(struct xe_ggtt_node *node, bool invalidate);
3336
bool xe_ggtt_node_allocated(const struct xe_ggtt_node *node);
3437
size_t xe_ggtt_node_pt_size(const struct xe_ggtt_node *node);
35-
void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node,
36-
struct xe_bo *bo, u16 pat_index);
3738
void xe_ggtt_map_bo_unlocked(struct xe_ggtt *ggtt, struct xe_bo *bo);
3839
int xe_ggtt_insert_bo(struct xe_ggtt *ggtt, struct xe_bo *bo, struct drm_exec *exec);
3940
int xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo,

drivers/gpu/drm/xe/xe_ggtt_types.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,22 @@ struct xe_ggtt_node {
7171
bool invalidate_on_remove;
7272
};
7373

74+
typedef void (*xe_ggtt_set_pte_fn)(struct xe_ggtt *ggtt, u64 addr, u64 pte);
75+
typedef void (*xe_ggtt_transform_cb)(struct xe_ggtt *ggtt,
76+
struct xe_ggtt_node *node,
77+
u64 pte_flags,
78+
xe_ggtt_set_pte_fn set_pte, void *arg);
7479
/**
7580
* struct xe_ggtt_pt_ops - GGTT Page table operations
7681
* Which can vary from platform to platform.
7782
*/
7883
struct xe_ggtt_pt_ops {
7984
/** @pte_encode_flags: Encode PTE flags for a given BO */
8085
u64 (*pte_encode_flags)(struct xe_bo *bo, u16 pat_index);
86+
8187
/** @ggtt_set_pte: Directly write into GGTT's PTE */
82-
void (*ggtt_set_pte)(struct xe_ggtt *ggtt, u64 addr, u64 pte);
88+
xe_ggtt_set_pte_fn ggtt_set_pte;
89+
8390
/** @ggtt_get_pte: Directly read from GGTT's PTE */
8491
u64 (*ggtt_get_pte)(struct xe_ggtt *ggtt, u64 addr);
8592
};

0 commit comments

Comments
 (0)