<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<font face="monospace">Hey,<br>
<br>
I'm trying for a different direction for this path series. I want
to move all ggtt handling to xe_ggtt.c again,<br>
so I had to remove all the code that pokes around into xe_ggtt
internals.</font><br>
<br>
Can you test the patch I attached below instead?<br>
It might require the rest of my GGTT cleanup series, I will resubmit
those if they don't apply.<br>
<br>
<div class="moz-cite-prefix">On 2025-06-02 12:33, Michal Wajdeczko
wrote:<br>
</div>
<blockquote type="cite"
cite="mid:20250602103325.549-2-michal.wajdeczko@intel.com">
<pre wrap="" class="moz-quote-pre">In upcoming patch we want to separate tile-oriented VF functions
from GT-oriented functions and to allow the former access a GGTT
configuration stored at GT level we need to provide some helpers.
Signed-off-by: Michal Wajdeczko <a class="moz-txt-link-rfc2396E" href="mailto:michal.wajdeczko@intel.com"><michal.wajdeczko@intel.com></a>
Cc: Tomasz Lis <a class="moz-txt-link-rfc2396E" href="mailto:tomasz.lis@intel.com"><tomasz.lis@intel.com></a>
---
drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 34 +++++++++++++++++++++++++++++
drivers/gpu/drm/xe/xe_gt_sriov_vf.h | 5 ++++-
2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
index 4ff7ae1a5f16..acfb3b1b0832 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
@@ -561,6 +561,40 @@ u64 xe_gt_sriov_vf_lmem(struct xe_gt *gt)
return gt->sriov.vf.self_config.lmem_size;
}
+/**
+ * xe_gt_sriov_vf_ggtt - VF GGTT configuration.
+ * @gt: the &xe_gt
+ *
+ * This function is for VF use only.
+ *
+ * Return: size of the GGTT assigned to VF.
+ */
+u64 xe_gt_sriov_vf_ggtt(struct xe_gt *gt)
+{
+ xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt)));
+ xe_gt_assert(gt, gt->sriov.vf.guc_version.major);
+ xe_gt_assert(gt, gt->sriov.vf.self_config.ggtt_size);
+
+ return gt->sriov.vf.self_config.ggtt_size;
+}
+
+/**
+ * xe_gt_sriov_vf_ggtt_base - VF GGTT base offset.
+ * @gt: the &xe_gt
+ *
+ * This function is for VF use only.
+ *
+ * Return: base offset of the GGTT assigned to VF.
+ */
+u64 xe_gt_sriov_vf_ggtt_base(struct xe_gt *gt)
+{
+ xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt)));
+ xe_gt_assert(gt, gt->sriov.vf.guc_version.major);
+ xe_gt_assert(gt, gt->sriov.vf.self_config.ggtt_size);
+
+ return gt->sriov.vf.self_config.ggtt_base;
+}
+
/**
* xe_gt_sriov_vf_ggtt_shift - Return shift in GGTT range due to VF migration
* @gt: the &xe_gt struct instance
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h
index 9db41afddd5a..2f96ac0c5dca 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h
@@ -20,7 +20,6 @@ int xe_gt_sriov_vf_query_runtime(struct xe_gt *gt);
int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt);
int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt);
void xe_gt_sriov_vf_deballoon_ggtt_locked(struct xe_gt *gt);
-s64 xe_gt_sriov_vf_ggtt_shift(struct xe_gt *gt);
void xe_gt_sriov_vf_fixup_ggtt_nodes(struct xe_gt *gt, s64 shift);
int xe_gt_sriov_vf_notify_resfix_done(struct xe_gt *gt);
void xe_gt_sriov_vf_migrated_event_handler(struct xe_gt *gt);
@@ -28,6 +27,10 @@ void xe_gt_sriov_vf_migrated_event_handler(struct xe_gt *gt);
u32 xe_gt_sriov_vf_gmdid(struct xe_gt *gt);
u16 xe_gt_sriov_vf_guc_ids(struct xe_gt *gt);
u64 xe_gt_sriov_vf_lmem(struct xe_gt *gt);
+u64 xe_gt_sriov_vf_ggtt(struct xe_gt *gt);
+u64 xe_gt_sriov_vf_ggtt_base(struct xe_gt *gt);
+s64 xe_gt_sriov_vf_ggtt_shift(struct xe_gt *gt);
+
u32 xe_gt_sriov_vf_read32(struct xe_gt *gt, struct xe_reg reg);
void xe_gt_sriov_vf_write32(struct xe_gt *gt, struct xe_reg reg, u32 val);
</pre>
</blockquote>
----8<----<br>
<pre>commit 40985bb758b283beba80d92e71e360aa2cc80783
Author: Maarten Lankhorst <a class="moz-txt-link-rfc2396E" href="mailto:dev@lankhorst.se"><dev@lankhorst.se></a>
Date: Mon May 26 14:52:21 2025 +0200
drm/xe: Make xe_ggtt_shift_nodes shift balloons as well
Do not manipulate xe_ggtt from xe_gt_sriov_vf, instead give
xe_ggtt_shift_nodes() the ability to resize and move the balloon
nodes as well.
Empty balloons do not get re-added. I'm not sure if this corner
case happens in practice though.
This removes the need for ggtt->lock from xe_gt_sriov_vf, and
leaves the GGTT modification logic entirely in xe_ggtt.c
Signed-off-by: Maarten Lankhorst <a class="moz-txt-link-rfc2396E" href="mailto:dev@lankhorst.se"><dev@lankhorst.se></a>
Cc: Tomasz Lis <a class="moz-txt-link-rfc2396E" href="mailto:tomasz.lis@intel.com"><tomasz.lis@intel.com></a>
Cc: Michal Wajdeczko <a class="moz-txt-link-rfc2396E" href="mailto:michal.wajdeczko@intel.com"><michal.wajdeczko@intel.com></a>
diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c
index c32803b31bada..1e5f8901bf513 100644
--- a/drivers/gpu/drm/xe/xe_ggtt.c
+++ b/drivers/gpu/drm/xe/xe_ggtt.c
@@ -462,22 +462,21 @@ static void xe_ggtt_dump_node(struct xe_ggtt *ggtt,
}
/**
- * xe_ggtt_node_insert_balloon_locked - prevent allocation of specified GGTT addresses
+ * xe_ggtt_node_insert_balloon - prevent allocation of specified GGTT addresses
* @node: the &xe_ggtt_node to hold reserved GGTT node
* @start: the starting GGTT address of the reserved region
* @end: then end GGTT address of the reserved region
*
- * To be used in cases where ggtt->lock is already taken.
- * Use xe_ggtt_node_remove_balloon_locked() to release a reserved GGTT node.
+ * Use xe_ggtt_node_remove_balloon() to release a reserved GGTT node.
*
* Return: 0 on success or a negative error code on failure.
*/
-int xe_ggtt_node_insert_balloon_locked(struct xe_ggtt_node *node, u64 start, u64 end)
+int xe_ggtt_node_insert_balloon(struct xe_ggtt_node *node, u64 start, u64 end)
{
struct xe_ggtt *ggtt = node->ggtt;
int err;
- xe_tile_assert(ggtt->tile, start < end);
+ xe_tile_assert(ggtt->tile, start <= end);
xe_tile_assert(ggtt->tile, IS_ALIGNED(start, XE_PAGE_SIZE));
xe_tile_assert(ggtt->tile, IS_ALIGNED(end, XE_PAGE_SIZE));
xe_tile_assert(ggtt->tile, !drm_mm_node_allocated(&node->base));
@@ -487,26 +486,41 @@ int xe_ggtt_node_insert_balloon_locked(struct xe_ggtt_node *node, u64 start, u64
node->base.start = start;
node->base.size = end - start;
- err = drm_mm_reserve_node(&ggtt->mm, &node->base);
+ if (node->base.size)
+ err = drm_mm_reserve_node(&ggtt->mm, &node->base);
+ else
+ err = 0;
if (xe_gt_WARN(ggtt->tile->primary_gt, err,
"Failed to balloon GGTT %#llx-%#llx (%pe)\n",
node->base.start, node->base.start + node->base.size, ERR_PTR(err)))
return err;
+ if (start == xe_wopcm_size(tile_to_xe(ggtt->tile)))
+ ggtt->balloon_start = &node->base;
+ else if (end == ggtt->size)
+ ggtt->balloon_end = &node->base;
+
xe_ggtt_dump_node(ggtt, &node->base, "balloon");
return 0;
}
/**
- * xe_ggtt_node_remove_balloon_locked - release a reserved GGTT region
+ * xe_ggtt_node_remove_balloon - release a reserved GGTT region
* @node: the &xe_ggtt_node with reserved GGTT region
*
- * To be used in cases where ggtt->lock is already taken.
- * See xe_ggtt_node_insert_balloon_locked() for details.
+ * See xe_ggtt_node_insert_balloon() for details.
*/
-void xe_ggtt_node_remove_balloon_locked(struct xe_ggtt_node *node)
+void xe_ggtt_node_remove_balloon(struct xe_ggtt_node *node)
{
+ struct xe_ggtt *ggtt = node->ggtt;
+
+ if (ggtt && &node->base == ggtt->balloon_start)
+ ggtt->balloon_start = NULL;
+
+ if (ggtt && &node->base == ggtt->balloon_end)
+ ggtt->balloon_end = NULL;
+
if (!xe_ggtt_node_allocated(node))
return;
@@ -517,18 +531,8 @@ void xe_ggtt_node_remove_balloon_locked(struct xe_ggtt_node *node)
drm_mm_remove_node(&node->base);
}
-static void xe_ggtt_assert_fit(struct xe_ggtt *ggtt, u64 start, u64 size)
-{
- struct xe_tile *tile = ggtt->tile;
- struct xe_device *xe = tile_to_xe(tile);
- u64 __maybe_unused wopcm = xe_wopcm_size(xe);
-
- xe_tile_assert(tile, start >= wopcm);
- xe_tile_assert(tile, start + size < ggtt->size - wopcm);
-}
-
/**
- * xe_ggtt_shift_nodes_locked - Shift GGTT nodes to adjust for a change in usable address range.
+ * xe_ggtt_shift_nodes - Shift GGTT nodes to adjust for a change in usable address range.
* @ggtt: the &xe_ggtt struct instance
* @shift: change to the location of area provisioned for current VF
*
@@ -542,29 +546,73 @@ static void xe_ggtt_assert_fit(struct xe_ggtt *ggtt, u64 start, u64 size)
* the list of nodes was either already damaged, or that the shift brings the address range
* outside of valid bounds. Both cases justify an assert rather than error code.
*/
-void xe_ggtt_shift_nodes_locked(struct xe_ggtt *ggtt, s64 shift)
+void xe_ggtt_shift_nodes(struct xe_ggtt *ggtt, s64 shift)
{
struct xe_tile *tile __maybe_unused = ggtt->tile;
struct drm_mm_node *node, *tmpn;
+ u64 ggtt_start __maybe_unused = xe_wopcm_size(tile_to_xe(ggtt->tile));
LIST_HEAD(temp_list_head);
- lockdep_assert_held(&ggtt->lock);
+ mutex_lock(&ggtt->lock);
+ if (ggtt->balloon_start) {
+ /*
+ * Balloon at the beginning, only end is adjusted,
+ * ensure it's possible with size >= 0)
+ */
+ node = ggtt->balloon_start;
+ xe_tile_assert(tile, node->start + shift + node->size < ggtt->size);
+ xe_tile_assert(tile, node->start + shift + node->size > ggtt_start);
+
+ if (drm_mm_node_allocated(node))
+ drm_mm_remove_node(node);
+
+ node->size += shift;
+ if (node->size)
+ list_add_tail(&node->node_list, &temp_list_head);
+ }
+
+ if (ggtt->balloon_end) {
+ /*
+ * Balloon at the end, only start is adjusted,
+ * ensure it's possible with (size >= 0)
+ */
+ node = ggtt->balloon_end;
+ xe_tile_assert(tile, node->start + shift >= ggtt_start);
+ xe_tile_assert(tile, node->start + shift < ggtt->size);
+
+ if (drm_mm_node_allocated(node))
+ drm_mm_remove_node(node);
+
+ node->start += shift;
+ node->size -= shift;
+ if (node->size)
+ list_add_tail(&node->node_list, &temp_list_head);
+ }
+
+ /* Remaining, actual nodes */
if (IS_ENABLED(CONFIG_DRM_XE_DEBUG))
- drm_mm_for_each_node_safe(node, tmpn, &ggtt->mm)
- xe_ggtt_assert_fit(ggtt, node->start + shift, node->size);
+ drm_mm_for_each_node_safe(node, tmpn, &ggtt->mm) {
+ xe_tile_assert(tile, node->start + shift >= ggtt_start);
+ xe_tile_assert(tile, node->start + shift + node->size <= ggtt->size);
+ }
drm_mm_for_each_node_safe(node, tmpn, &ggtt->mm) {
drm_mm_remove_node(node);
- list_add(&node->node_list, &temp_list_head);
+
+ node->start += shift;
+ list_add_tail(&node->node_list, &temp_list_head);
}
+ /* Finally, insert balloons and nodes into their new locations */
list_for_each_entry_safe(node, tmpn, &temp_list_head, node_list) {
list_del(&node->node_list);
- node->start += shift;
+
drm_mm_reserve_node(&ggtt->mm, node);
xe_tile_assert(tile, drm_mm_node_allocated(node));
}
+
+ mutex_unlock(&ggtt->lock);
}
static int xe_ggtt_node_insert_locked(struct xe_ggtt_node *node,
@@ -608,7 +656,7 @@ int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align)
* or xe_ggtt_node_remove_balloon().
* Having %xe_ggtt_node struct allocated doesn't mean that the node is already allocated
* in GGTT. Only the xe_ggtt_node_insert(), xe_ggtt_node_insert_transform(),
- * xe_ggtt_node_insert_balloon_locked() will ensure the node is inserted or reserved in GGTT.
+ * xe_ggtt_node_insert_balloon() will ensure the node is inserted or reserved in GGTT.
*
* Return: A pointer to %xe_ggtt_node struct on success. An ERR_PTR otherwise.
**/
diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h
index 3951d9af97aa8..48f96267a7891 100644
--- a/drivers/gpu/drm/xe/xe_ggtt.h
+++ b/drivers/gpu/drm/xe/xe_ggtt.h
@@ -18,10 +18,10 @@ int xe_ggtt_init(struct xe_ggtt *ggtt);
struct xe_ggtt_node *xe_ggtt_node_init(struct xe_ggtt *ggtt);
void xe_ggtt_node_fini(struct xe_ggtt_node *node);
-int xe_ggtt_node_insert_balloon_locked(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_locked(struct xe_ggtt_node *node);
-void xe_ggtt_shift_nodes_locked(struct xe_ggtt *ggtt, s64 shift);
+void xe_ggtt_node_remove_balloon(struct xe_ggtt_node *node);
+void xe_ggtt_shift_nodes(struct xe_ggtt *ggtt, s64 shift);
int xe_ggtt_node_insert(struct xe_ggtt_node *node, u32 size, u32 align);
struct xe_ggtt_node *
diff --git a/drivers/gpu/drm/xe/xe_ggtt_types.h b/drivers/gpu/drm/xe/xe_ggtt_types.h
index 18b5466ae8e6f..3454a3c7686d1 100644
--- a/drivers/gpu/drm/xe/xe_ggtt_types.h
+++ b/drivers/gpu/drm/xe/xe_ggtt_types.h
@@ -12,6 +12,7 @@
struct xe_bo;
struct xe_gt;
+struct xe_ggtt_node;
/**
* struct xe_ggtt - Main GGTT struct
@@ -49,6 +50,10 @@ struct xe_ggtt {
unsigned int access_count;
/** @wq: Dedicated unordered work queue to process node removals */
struct workqueue_struct *wq;
+ /** @balloon_start: Optional balloon at the beginning of GGTT, may be zero-sized */
+ struct drm_mm_node *balloon_start;
+ /** @balloon_end: Optional balloon at the end of GGTT, may be zero-sized */
+ struct drm_mm_node *balloon_end;
};
/**
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
index 4ff7ae1a5f16c..8b8604bdedb48 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
@@ -600,12 +600,7 @@ static int vf_init_ggtt_balloons(struct xe_gt *gt)
return 0;
}
-/**
- * xe_gt_sriov_vf_balloon_ggtt_locked - Insert balloon nodes to limit used GGTT address range.
- * @gt: the &xe_gt struct instance
- * Return: 0 on success or a negative error code on failure.
- */
-int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt)
+static int 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);
@@ -615,7 +610,6 @@ int xe_gt_sriov_vf_balloon_ggtt_locked(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;
@@ -638,7 +632,7 @@ int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt)
start = xe_wopcm_size(xe);
end = config->ggtt_base;
if (end != start) {
- err = xe_ggtt_node_insert_balloon_locked(tile->sriov.vf.ggtt_balloon[0],
+ err = xe_ggtt_node_insert_balloon(tile->sriov.vf.ggtt_balloon[0],
start, end);
if (err)
return err;
@@ -647,10 +641,11 @@ int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt)
start = config->ggtt_base + config->ggtt_size;
end = GUC_GGTT_TOP;
if (end != start) {
- err = xe_ggtt_node_insert_balloon_locked(tile->sriov.vf.ggtt_balloon[1],
+ err = xe_ggtt_node_insert_balloon(tile->sriov.vf.ggtt_balloon[1],
start, end);
if (err) {
- xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[0]);
+ xe_ggtt_node_remove_balloon(tile->sriov.vf.ggtt_balloon[0]);
+ tile->sriov.vf.ggtt_balloon[0] = NULL;
return err;
}
}
@@ -658,38 +653,13 @@ int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt)
return 0;
}
-static int vf_balloon_ggtt(struct xe_gt *gt)
-{
- struct xe_ggtt *ggtt = gt_to_tile(gt)->mem.ggtt;
- int err;
-
- mutex_lock(&ggtt->lock);
- err = xe_gt_sriov_vf_balloon_ggtt_locked(gt);
- mutex_unlock(&ggtt->lock);
-
- return err;
-}
-
-/**
- * xe_gt_sriov_vf_deballoon_ggtt_locked - Remove balloon nodes.
- * @gt: the &xe_gt struct instance
- */
-void xe_gt_sriov_vf_deballoon_ggtt_locked(struct xe_gt *gt)
-{
- struct xe_tile *tile = gt_to_tile(gt);
-
- xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile)));
- xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[1]);
- xe_ggtt_node_remove_balloon_locked(tile->sriov.vf.ggtt_balloon[0]);
-}
-
static void vf_deballoon_ggtt(struct xe_gt *gt)
{
struct xe_tile *tile = gt_to_tile(gt);
- mutex_lock(&tile->mem.ggtt->lock);
- xe_gt_sriov_vf_deballoon_ggtt_locked(gt);
- mutex_unlock(&tile->mem.ggtt->lock);
+ xe_tile_assert(tile, IS_SRIOV_VF(tile_to_xe(tile)));
+ xe_ggtt_node_remove_balloon(tile->sriov.vf.ggtt_balloon[1]);
+ xe_ggtt_node_remove_balloon(tile->sriov.vf.ggtt_balloon[0]);
}
static void vf_fini_ggtt_balloons(struct xe_gt *gt)
@@ -912,11 +882,7 @@ void xe_gt_sriov_vf_fixup_ggtt_nodes(struct xe_gt *gt, s64 shift)
xe_gt_assert(gt, !xe_gt_is_media_type(gt));
- mutex_lock(&ggtt->lock);
- xe_gt_sriov_vf_deballoon_ggtt_locked(gt);
- xe_ggtt_shift_nodes_locked(ggtt, shift);
- xe_gt_sriov_vf_balloon_ggtt_locked(gt);
- mutex_unlock(&ggtt->lock);
+ xe_ggtt_shift_nodes(ggtt, shift);
}
/**
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h
index 9db41afddd5a8..8956fed594996 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.h
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.h
@@ -18,8 +18,6 @@ int xe_gt_sriov_vf_query_config(struct xe_gt *gt);
int xe_gt_sriov_vf_connect(struct xe_gt *gt);
int xe_gt_sriov_vf_query_runtime(struct xe_gt *gt);
int xe_gt_sriov_vf_prepare_ggtt(struct xe_gt *gt);
-int xe_gt_sriov_vf_balloon_ggtt_locked(struct xe_gt *gt);
-void xe_gt_sriov_vf_deballoon_ggtt_locked(struct xe_gt *gt);
s64 xe_gt_sriov_vf_ggtt_shift(struct xe_gt *gt);
void xe_gt_sriov_vf_fixup_ggtt_nodes(struct xe_gt *gt, s64 shift);
int xe_gt_sriov_vf_notify_resfix_done(struct xe_gt *gt);
</pre>
</body>
</html>