From: "Zhaoyu Liu" <liuzhaoyu.zackary@picoheart.com>
To: <matthew.auld@intel.com>, <arunpravin.paneerselvam@amd.com>,
<joelagnelf@nvidia.com>, <airlied@gmail.com>, <simona@ffwll.ch>
Cc: <dri-devel@lists.freedesktop.org>, <linux-kernel@vger.kernel.org>
Subject: [PATCH] gpu: buddy: avoid repeated builds of root dfs when alloc range
Date: Thu, 9 Jul 2026 19:20:43 +0800 [thread overview]
Message-ID: <ak+ECwsuSljmvyKd@hostpc> (raw)
The buddy allocator previously pre-built a DFS list by inserting all
root blocks via list_add_tail() before every allocation call in
__alloc_range_bias() and __gpu_buddy_alloc_range(). This is wasteful
when the allocation can be satisfied by the first root or by sub-blocks
produced from splits, as the remaining roots are never consumed.
Introduce __get_candidate_block() which unifies the block acquisition
logic for both __alloc_range_bias() and __alloc_range(): it first
checks the DFS list (populated by splits during allocation or
pre-filled by the caller for trim), and only when the list is exhausted
does it lazily fetch the next root block through a cursor.
When the caller pre-fills the DFS list (trim scenario), the cursor is
initialized to mm->n_roots to disable root iteration entirely,
preserving the original behavior.
Signed-off-by: Zhaoyu Liu <liuzhaoyu.zackary@picoheart.com>
---
drivers/gpu/buddy.c | 61 ++++++++++++++++++++++++++++++---------------
1 file changed, 41 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/buddy.c b/drivers/gpu/buddy.c
index dc81fe0301ce..2cebb87020c7 100644
--- a/drivers/gpu/buddy.c
+++ b/drivers/gpu/buddy.c
@@ -700,6 +700,41 @@ static void __gpu_buddy_undo_splits(struct gpu_buddy *mm,
}
}
+/**
+ * __get_candidate_block - Get a candidate block for allocation.
+ * @mm: GPU buddy manager
+ * @dfs: List of candidate blocks. Populated in two ways: (1) pre-filled by
+ * the caller before allocation with blocks available for allocation,
+ * and (2) extended during allocation by block splits, which add the
+ * resulting sub-blocks for subsequent finer-grained allocation.
+ * @cursor: Pointer to current root index, advanced when iterating roots.
+ * Pass in a value >= mm->n_roots to disable root iteration entirely,
+ * restricting block acquisition to @dfs only; this is used in the
+ * trim scenario where only pre-split sub-blocks should be considered.
+ *
+ * Return: Pointer to the acquired block on success, ERR_PTR(-ENOSPC) when no
+ * more blocks are available.
+ */
+static struct gpu_buddy_block*
+__get_candidate_block(struct gpu_buddy *mm, struct list_head *dfs,
+ uint32_t *cursor)
+{
+ struct gpu_buddy_block *block;
+
+ block = list_first_entry_or_null(dfs,
+ struct gpu_buddy_block,
+ tmp_link);
+ if (block) {
+ list_del(&block->tmp_link);
+ return block;
+ }
+
+ if (*cursor >= mm->n_roots)
+ return ERR_PTR(-ENOSPC);
+
+ return mm->roots[(*cursor)++];
+}
+
static struct gpu_buddy_block *
__alloc_range_bias(struct gpu_buddy *mm,
u64 start, u64 end,
@@ -711,25 +746,18 @@ __alloc_range_bias(struct gpu_buddy *mm,
struct gpu_buddy_block *block;
LIST_HEAD(dfs);
int err;
- int i;
+ uint32_t cursor = 0;
end = end - 1;
- for (i = 0; i < mm->n_roots; ++i)
- list_add_tail(&mm->roots[i]->tmp_link, &dfs);
-
do {
u64 block_start;
u64 block_end;
- block = list_first_entry_or_null(&dfs,
- struct gpu_buddy_block,
- tmp_link);
- if (!block)
+ block = __get_candidate_block(mm, &dfs, &cursor);
+ if (IS_ERR(block))
break;
- list_del(&block->tmp_link);
-
if (gpu_buddy_block_order(block) < order)
continue;
@@ -1023,6 +1051,7 @@ static int __alloc_range(struct gpu_buddy *mm,
LIST_HEAD(allocated);
u64 end;
int err;
+ uint32_t cursor = list_empty(dfs) ? 0 : mm->n_roots;
end = start + size - 1;
@@ -1030,14 +1059,10 @@ static int __alloc_range(struct gpu_buddy *mm,
u64 block_start;
u64 block_end;
- block = list_first_entry_or_null(dfs,
- struct gpu_buddy_block,
- tmp_link);
- if (!block)
+ block = __get_candidate_block(mm, dfs, &cursor);
+ if (IS_ERR(block))
break;
- list_del(&block->tmp_link);
-
block_start = gpu_buddy_block_offset(block);
block_end = block_start + gpu_buddy_block_size(mm, block) - 1;
@@ -1109,10 +1134,6 @@ static int __gpu_buddy_alloc_range(struct gpu_buddy *mm,
struct list_head *blocks)
{
LIST_HEAD(dfs);
- int i;
-
- for (i = 0; i < mm->n_roots; ++i)
- list_add_tail(&mm->roots[i]->tmp_link, &dfs);
return __alloc_range(mm, &dfs, start, size,
blocks, total_allocated_on_err);
--
2.34.1
next reply other threads:[~2026-07-09 11:20 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-09 11:20 Zhaoyu Liu [this message]
2026-07-13 6:31 ` [PATCH] gpu: buddy: avoid repeated builds of root dfs when alloc range 刘照玉
2026-07-13 8:02 ` Arunpravin Paneer Selvam
2026-07-13 13:25 ` Zhaoyu Liu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ak+ECwsuSljmvyKd@hostpc \
--to=liuzhaoyu.zackary@picoheart.com \
--cc=airlied@gmail.com \
--cc=arunpravin.paneerselvam@amd.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=joelagnelf@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=matthew.auld@intel.com \
--cc=simona@ffwll.ch \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.