The balloon nodes used to fill areas of GGTT inaccessible for
a specific VF, were allocaten and inserted into GGTT within
one function. This disallowed re-using the insertion part
during VF migration recovery.

This patch separates allocation (init/fini functs) from the insertion
of balloons (balloon/deballoon functs). Locks are also moved to ensure
calls from post-migration recovery worker will not cause a deadlock.

Signed-off-by: Tomasz Lis <tomasz....@intel.com>
---
 drivers/gpu/drm/xe/xe_ggtt.c        |  9 +---
 drivers/gpu/drm/xe/xe_ggtt.h        |  2 +
 drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 64 ++++++++++++++++++++++-------
 3 files changed, 52 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c
index 5fcb2b4c2c13..2d7456e37ef4 100644
--- a/drivers/gpu/drm/xe/xe_ggtt.c
+++ b/drivers/gpu/drm/xe/xe_ggtt.c
@@ -452,9 +452,7 @@ int xe_ggtt_node_insert_balloon(struct xe_ggtt_node *node, 
u64 start, u64 end)
        node->base.start = start;
        node->base.size = end - start;
 
-       mutex_lock(&ggtt->lock);
        err = drm_mm_reserve_node(&ggtt->mm, &node->base);
-       mutex_unlock(&ggtt->lock);
 
        if (xe_gt_WARN(ggtt->tile->primary_gt, err,
                       "Failed to balloon GGTT %#llx-%#llx (%pe)\n",
@@ -477,16 +475,11 @@ void xe_ggtt_node_remove_balloon(struct xe_ggtt_node 
*node)
                return;
 
        if (!drm_mm_node_allocated(&node->base))
-               goto free_node;
+               return;
 
        xe_ggtt_dump_node(node->ggtt, &node->base, "remove-balloon");
 
-       mutex_lock(&node->ggtt->lock);
        drm_mm_remove_node(&node->base);
-       mutex_unlock(&node->ggtt->lock);
-
-free_node:
-       xe_ggtt_node_fini(node);
 }
 
 /**
diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h
index 27e7d67de004..fddb68f309d9 100644
--- a/drivers/gpu/drm/xe/xe_ggtt.h
+++ b/drivers/gpu/drm/xe/xe_ggtt.h
@@ -18,6 +18,8 @@ void xe_ggtt_node_fini(struct xe_ggtt_node *node);
 int xe_ggtt_node_insert_balloon(struct xe_ggtt_node *node,
                                u64 start, u64 size);
 void xe_ggtt_node_remove_balloon(struct xe_ggtt_node *node);
+int xe_gt_sriov_vf_balloon_ggtt(struct xe_gt *gt);
+void xe_gt_sriov_vf_deballoon_ggtt(struct xe_gt *gt);
 
 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,
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c 
b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
index a439261bf4d7..9edbe34f45f4 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
@@ -560,26 +560,33 @@ u64 xe_gt_sriov_vf_lmem(struct xe_gt *gt)
        return gt->sriov.vf.self_config.lmem_size;
 }
 
-static struct xe_ggtt_node *
-vf_balloon_ggtt_node(struct xe_ggtt *ggtt, u64 start, u64 end)
+static int
+vf_balloon_ggtt_node(struct xe_ggtt *ggtt, struct xe_ggtt_node *node,
+                    u64 start, u64 end)
 {
-       struct xe_ggtt_node *node;
        int err;
 
-       node = xe_ggtt_node_init(ggtt);
        if (IS_ERR(node))
-               return node;
+               return PTR_ERR(node);
 
        err = xe_ggtt_node_insert_balloon(node, start, end);
        if (err) {
-               xe_ggtt_node_fini(node);
-               return ERR_PTR(err);
+               return err;
        }
 
-       return node;
+       return 0;
 }
 
-static int vf_balloon_ggtt(struct xe_gt *gt)
+static void xe_gt_sriov_vf_balloon_init(struct xe_gt *gt)
+{
+       struct xe_tile *tile = gt_to_tile(gt);
+       struct xe_ggtt *ggtt = tile->mem.ggtt;
+
+       tile->sriov.vf.ggtt_balloon[0] = xe_ggtt_node_init(ggtt);
+       tile->sriov.vf.ggtt_balloon[1] = xe_ggtt_node_init(ggtt);
+}
+
+int xe_gt_sriov_vf_balloon_ggtt(struct xe_gt *gt)
 {
        struct xe_gt_sriov_vf_selfconfig *config = &gt->sriov.vf.self_config;
        struct xe_tile *tile = gt_to_tile(gt);
@@ -589,6 +596,7 @@ static int vf_balloon_ggtt(struct xe_gt *gt)
 
        xe_gt_assert(gt, IS_SRIOV_VF(xe));
        xe_gt_assert(gt, !xe_gt_is_media_type(gt));
+       lockdep_assert_held(&tile->mem.ggtt->lock);
 
        if (!config->ggtt_size)
                return -ENODATA;
@@ -611,7 +619,7 @@ static int vf_balloon_ggtt(struct xe_gt *gt)
        start = xe_wopcm_size(xe);
        end = config->ggtt_base;
        if (end != start) {
-               tile->sriov.vf.ggtt_balloon[0] = vf_balloon_ggtt_node(ggtt, 
start, end);
+               vf_balloon_ggtt_node(ggtt, tile->sriov.vf.ggtt_balloon[0], 
start, end);
                if (IS_ERR(tile->sriov.vf.ggtt_balloon[0]))
                        return PTR_ERR(tile->sriov.vf.ggtt_balloon[0]);
        }
@@ -619,7 +627,7 @@ static int vf_balloon_ggtt(struct xe_gt *gt)
        start = config->ggtt_base + config->ggtt_size;
        end = GUC_GGTT_TOP;
        if (end != start) {
-               tile->sriov.vf.ggtt_balloon[1] = vf_balloon_ggtt_node(ggtt, 
start, end);
+               vf_balloon_ggtt_node(ggtt, tile->sriov.vf.ggtt_balloon[1], 
start, end);
                if (IS_ERR(tile->sriov.vf.ggtt_balloon[1])) {
                        
xe_ggtt_node_remove_balloon(tile->sriov.vf.ggtt_balloon[0]);
                        return PTR_ERR(tile->sriov.vf.ggtt_balloon[1]);
@@ -629,15 +637,34 @@ static int vf_balloon_ggtt(struct xe_gt *gt)
        return 0;
 }
 
-static void deballoon_ggtt(struct drm_device *drm, void *arg)
+void xe_gt_sriov_vf_deballoon_ggtt(struct xe_gt *gt)
 {
-       struct xe_tile *tile = arg;
+       struct xe_tile *tile = gt_to_tile(gt);
 
        xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile)));
+       lockdep_assert_held(&tile->mem.ggtt->lock);
        xe_ggtt_node_remove_balloon(tile->sriov.vf.ggtt_balloon[1]);
        xe_ggtt_node_remove_balloon(tile->sriov.vf.ggtt_balloon[0]);
 }
 
+static void xe_gt_sriov_vf_balloon_fini(struct xe_gt *gt)
+{
+       struct xe_tile *tile = gt_to_tile(gt);
+
+       xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[1]);
+       xe_ggtt_node_fini(tile->sriov.vf.ggtt_balloon[0]);
+}
+
+static void deballoon_ggtt(struct drm_device *drm, void *arg)
+{
+       struct xe_tile *tile = arg;
+
+       mutex_lock(&tile->mem.ggtt->lock);
+       xe_gt_sriov_vf_deballoon_ggtt(tile->primary_gt);
+       mutex_unlock(&tile->mem.ggtt->lock);
+       xe_gt_sriov_vf_balloon_fini(tile->primary_gt);
+}
+
 /**
  * xe_gt_sriov_vf_prepare_ggtt - Prepare a VF's GGTT configuration.
  * @gt: the &xe_gt
@@ -650,14 +677,21 @@ int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt)
 {
        struct xe_tile *tile = gt_to_tile(gt);
        struct xe_device *xe = tile_to_xe(tile);
+       struct xe_ggtt *ggtt = tile->mem.ggtt;
        int err;
 
        if (xe_gt_is_media_type(gt))
                return 0;
 
-       err = vf_balloon_ggtt(gt);
-       if (err)
+       xe_gt_sriov_vf_balloon_init(gt);
+
+       mutex_lock(&ggtt->lock);
+       err = xe_gt_sriov_vf_balloon_ggtt(gt);
+       mutex_unlock(&ggtt->lock);
+       if (err) {
+               xe_gt_sriov_vf_balloon_fini(gt);
                return err;
+       }
 
        return drmm_add_action_or_reset(&xe->drm, deballoon_ggtt, tile);
 }
-- 
2.25.1

Reply via email to