On Wed, Jul 15, 2026 at 01:05:53PM +0200, Maarten Lankhorst wrote: > The last bit required for handling fb takeover is > ensuring we can release the old live framebuffer > without keeping track. The display code can then > safely perform the flip. > > It's unfortunately a workaround for how display > is structured through callbacks instead of being > a midlayer. > > Signed-off-by: Maarten Lankhorst <[email protected]>
Reviewed-by: Ville Syrjälä <[email protected]> > --- > drivers/gpu/drm/xe/xe_ggtt.c | 30 +++++++++++++++++++++++------- > drivers/gpu/drm/xe/xe_ggtt.h | 1 + > 2 files changed, 24 insertions(+), 7 deletions(-) > > diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c > index c9f84db3bfecd..ff479e0a9f3b3 100644 > --- a/drivers/gpu/drm/xe/xe_ggtt.c > +++ b/drivers/gpu/drm/xe/xe_ggtt.c > @@ -470,24 +470,40 @@ static void ggtt_node_fini(struct xe_ggtt_node *node) > kfree(node); > } > > -static void ggtt_node_remove(struct xe_ggtt_node *node) > +static void ggtt_node_remove(struct xe_ggtt_node *node, bool clear) > { > struct xe_ggtt *ggtt = node->ggtt; > - bool bound; > > mutex_lock(&ggtt->lock); > - bound = ggtt->flags & XE_GGTT_FLAGS_ONLINE; > - if (bound) > + if (clear) > + clear = ggtt->flags & XE_GGTT_FLAGS_ONLINE; > + if (clear) > xe_ggtt_clear(ggtt, xe_ggtt_node_addr(node), > xe_ggtt_node_size(node)); > drm_mm_remove_node(&node->base); > node->base.size = 0; > - if (bound && node->invalidate_on_remove) > + if (clear && node->invalidate_on_remove) > xe_ggtt_invalidate(ggtt); > mutex_unlock(&ggtt->lock); > > ggtt_node_fini(node); > } > > +/** > + * xe_ggtt_node_remove_noclear - Remove a &xe_ggtt_node from the GGTT > without clearing entries > + * @node: the &xe_ggtt_node to be removed > + * > + * This function is similar to xe_ggtt_node_remove(), but doesn't clear > + * the entries. It's used to release the live FB mapping without > + * clearing it. > + * > + * This function should only be called before xe_ggtt_init() in > + * the bios FB takeover code. > + */ > +void xe_ggtt_node_remove_noclear(struct xe_ggtt_node *node) > +{ > + ggtt_node_remove(node, false); > +} > + > static void ggtt_node_remove_work_func(struct work_struct *work) > { > struct xe_ggtt_node *node = container_of(work, typeof(*node), > @@ -495,7 +511,7 @@ static void ggtt_node_remove_work_func(struct work_struct > *work) > struct xe_device *xe = tile_to_xe(node->ggtt->tile); > > guard(xe_pm_runtime)(xe); > - ggtt_node_remove(node); > + ggtt_node_remove(node, true); > } > > /** > @@ -517,7 +533,7 @@ void xe_ggtt_node_remove(struct xe_ggtt_node *node, bool > invalidate) > node->invalidate_on_remove = invalidate; > > if (xe_pm_runtime_get_if_active(xe)) { > - ggtt_node_remove(node); > + ggtt_node_remove(node, true); > xe_pm_runtime_put(xe); > } else { > queue_work(ggtt->wq, &node->delayed_removal_work); > diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h > index 69974da523f74..83654544feb6d 100644 > --- a/drivers/gpu/drm/xe/xe_ggtt.h > +++ b/drivers/gpu/drm/xe/xe_ggtt.h > @@ -32,6 +32,7 @@ xe_ggtt_insert_node_transform(struct xe_ggtt *ggtt, > u64 size, u32 align, > xe_ggtt_transform_cb transform, void *arg); > void xe_ggtt_node_remove(struct xe_ggtt_node *node, bool invalidate); > +void xe_ggtt_node_remove_noclear(struct xe_ggtt_node *node); > size_t xe_ggtt_node_pt_size(const struct xe_ggtt_node *node); > 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, struct > drm_exec *exec); > -- > 2.53.0 -- Ville Syrjälä Intel
