@@ -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);
}
/**
@@ -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,
@@ -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 = >->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);
}
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.lis@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(-)