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]>
---
 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 514dc9edd19e2..7aa075edf9d28 100644
--- a/drivers/gpu/drm/xe/xe_ggtt.c
+++ b/drivers/gpu/drm/xe/xe_ggtt.c
@@ -467,24 +467,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),
@@ -492,7 +508,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);
 }
 
 /**
@@ -514,7 +530,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

Reply via email to