Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: "Yadav, Sanjay Kumar" <sanjay.kumar.yadav@intel.com>
To: <dri-devel@lists.freedesktop.org>
Cc: <intel-xe@lists.freedesktop.org>,
	Matthew Auld <matthew.auld@intel.com>,
	Arun Pravin <arunpravin.paneerselvam@amd.com>,
	Joel Fernandes <joelagnelf@nvidia.com>
Subject: Re: [PATCH v4 1/1] gpu/buddy: Prune exhausted subtrees in range-biased allocation
Date: Fri, 6 Nov 2026 17:50:27 +0530	[thread overview]
Message-ID: <2b70fda5-187f-4047-a742-533f11985593@intel.com> (raw)
In-Reply-To: <e87c786b-ceb5-4907-b215-ef276910392a@intel.com>


On 04-11-2026 17:42, Yadav, Sanjay Kumar wrote:
>
> On 02-11-2026 10:46, Sanjay Yadav wrote:
>> __alloc_range_bias() walks the buddy tree depth-first, higher address
>> first, and descends every SPLIT block even when nothing below it is
>> free. Range allocations are placed top-down, so they pack below the
>> range end and each new one walks every block already allocated there:
>> O(N) per allocation and O(N^2) for N allocations, under the allocator
>> lock.
>>
>> Track in each block the largest order of any FREE block in its subtree
>> (GPU_BUDDY_NO_FREE_ORDER if none), update it when a block is allocated
>> or freed, and skip subtrees that cannot satisfy the requested order.
>> Splitting needs no update of its own, as both children are marked free
>> right after and that propagates the new value up.
>> gpu_buddy_block_trim() detaches the block before freeing it, so updates
>> stop there while re-allocating inside it; recompute from the parent
>> once it is reattached.
>>
>> Skipped subtrees contain no FREE block of the requested order or
>> larger, so the old walk could neither split nor return anything there.
>> The remaining blocks are visited in the same order, so the selected
>> block and placement are unchanged.
>>
>> v4: (Matt A)
>> - Drop the update in mark_split(), the children being marked free
>>    updates the parent
>> - Detach the block before __mark_free() in gpu_buddy_block_trim(), so
>>    only the final update from the parent propagates up
>> - Drop the order, is_allocated() and is_free() checks in
>>    __alloc_range_bias() that the pruning check now covers
>>
>> Cc: Matthew Auld <matthew.auld@intel.com>
>> Cc: Arun Pravin <arunpravin.paneerselvam@amd.com>
>> Cc: Joel Fernandes <joelagnelf@nvidia.com>
>> Assisted-by: LLM
>> Signed-off-by: Sanjay Yadav <sanjay.kumar.yadav@intel.com>
> Gentle ping

Hi Arun

Could you please review?

>> ---
>>   drivers/gpu/buddy.c       | 56 +++++++++++++++++++++++++++------------
>>   include/linux/gpu_buddy.h |  7 +++++
>>   2 files changed, 46 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/gpu/buddy.c b/drivers/gpu/buddy.c
>> index 28cff97d57dc..93f70c98b235 100644
>> --- a/drivers/gpu/buddy.c
>> +++ b/drivers/gpu/buddy.c
>> @@ -602,6 +602,7 @@ static struct gpu_buddy_block 
>> *gpu_block_alloc(struct gpu_buddy *mm,
>>       block->header = offset;
>>       block->header |= order;
>>       block->parent = parent;
>> +    block->subtree_max_free_order = GPU_BUDDY_NO_FREE_ORDER;
>>         RB_CLEAR_NODE(&block->rb);
>>   @@ -717,6 +718,27 @@ static void rbtree_remove(struct gpu_buddy *mm,
>>       RB_CLEAR_NODE(&block->rb);
>>   }
>>   +static void update_subtree_max_free_order(struct gpu_buddy_block 
>> *block)
>> +{
>> +    while (block) {
>> +        s8 max_free;
>> +
>> +        if (gpu_buddy_block_is_free(block))
>> +            max_free = gpu_buddy_block_order(block);
>> +        else if (gpu_buddy_block_is_split(block))
>> +            max_free = max(block->left->subtree_max_free_order,
>> + block->right->subtree_max_free_order);
>> +        else
>> +            max_free = GPU_BUDDY_NO_FREE_ORDER;
>> +
>> +        if (block->subtree_max_free_order == max_free)
>> +            break;
>> +
>> +        block->subtree_max_free_order = max_free;
>> +        block = block->parent;
>> +    }
>> +}
>> +
>>   static void mark_allocated(struct gpu_buddy *mm,
>>                  struct gpu_buddy_block *block)
>>   {
>> @@ -729,6 +751,7 @@ static void mark_allocated(struct gpu_buddy *mm,
>>       mm->used_scoreboard[gpu_buddy_block_order(block)]++;
>>         rbtree_remove(mm, block);
>> +    update_subtree_max_free_order(block);
>>   }
>>     static void __mark_free(struct gpu_buddy *mm,
>> @@ -750,6 +773,7 @@ static void __mark_free(struct gpu_buddy *mm,
>>       mm->free_scoreboard[gpu_buddy_block_order(block)]++;
>>         rbtree_insert(mm, block);
>> +    update_subtree_max_free_order(block);
>>   }
>>     static void mark_free(struct gpu_buddy *mm,
>> @@ -869,6 +893,8 @@ int gpu_buddy_init(struct gpu_buddy *mm, u64 
>> size, u64 chunk_size)
>>         size = round_down(size, chunk_size);
>>   +    BUILD_BUG_ON(GPU_BUDDY_MAX_ORDER > S8_MAX);
>> +
>>       mm->size = size;
>>       mm->avail = size;
>>       mm->chunk_size = chunk_size;
>> @@ -1277,7 +1303,7 @@ __alloc_range_bias(struct gpu_buddy *mm,
>>             list_del(&block->tmp_link);
>>   -        if (gpu_buddy_block_order(block) < order)
>> +        if (block->subtree_max_free_order < (int)order)
>>               continue;
>>             block_start = gpu_buddy_block_offset(block);
>> @@ -1286,9 +1312,6 @@ __alloc_range_bias(struct gpu_buddy *mm,
>>           if (!overlaps(start, end, block_start, block_end))
>>               continue;
>>   -        if (gpu_buddy_block_is_allocated(block))
>> -            continue;
>> -
>>           if (block_start < start || block_end > end) {
>>               u64 adjusted_start = max(block_start, start);
>>               u64 adjusted_end = min(block_end, end);
>> @@ -1298,16 +1321,10 @@ __alloc_range_bias(struct gpu_buddy *mm,
>>                   continue;
>>           }
>>   +        /* Not pruned at @order, so this block itself is FREE */
>>           if (contains(start, end, block_start, block_end) &&
>> -            order == gpu_buddy_block_order(block)) {
>> -            /*
>> -             * Find the free block within the range.
>> -             */
>> -            if (gpu_buddy_block_is_free(block))
>> -                return block;
>> -
>> -            continue;
>> -        }
>> +            order == gpu_buddy_block_order(block))
>> +            return block;
>>             if (!gpu_buddy_block_is_split(block)) {
>>               err = split_block(mm, block);
>> @@ -1856,13 +1873,17 @@ int gpu_buddy_block_trim(struct gpu_buddy *mm,
>>                            gpu_buddy_block_offset(block),
>>                            gpu_buddy_block_size(mm, block));
>>   -    __mark_free(mm, block, was_clear ? GPU_BLOCK_CLEAR : 
>> GPU_BLOCK_DIRTY);
>> -    mm->avail += gpu_buddy_block_size(mm, block);
>> -
>> -    /* Prevent recursively freeing this node */
>> +    /*
>> +     * Detach the block to prevent recursively freeing this node, 
>> and to
>> +     * keep free-order updates from propagating above it until the trim
>> +     * is done.
>> +     */
>>       parent = block->parent;
>>       block->parent = NULL;
>>   +    __mark_free(mm, block, was_clear ? GPU_BLOCK_CLEAR : 
>> GPU_BLOCK_DIRTY);
>> +    mm->avail += gpu_buddy_block_size(mm, block);
>> +
>>       list_add(&block->tmp_link, &dfs);
>>       err =  __alloc_range(mm, &dfs, new_start, new_size,
>>                    was_clear ? GPU_BUDDY_CLEAR_ALLOCATION : 0,
>> @@ -1881,6 +1902,7 @@ int gpu_buddy_block_trim(struct gpu_buddy *mm,
>>       }
>>         block->parent = parent;
>> +    update_subtree_max_free_order(parent);
>>       return err;
>>   }
>>   EXPORT_SYMBOL(gpu_buddy_block_trim);
>> diff --git a/include/linux/gpu_buddy.h b/include/linux/gpu_buddy.h
>> index ddc4eca84175..8037f5a0feb1 100644
>> --- a/include/linux/gpu_buddy.h
>> +++ b/include/linux/gpu_buddy.h
>> @@ -141,8 +141,15 @@ struct gpu_buddy_block {
>>       unsigned int subtree_max_alignment;
>>       struct list_head tmp_link;
>>       bool has_clear;
>> +    /*
>> +     * Largest order of any FREE block in this block's buddy 
>> subtree, or
>> +     * GPU_BUDDY_NO_FREE_ORDER if none. Protected by the driver lock.
>> +     */
>> +    s8 subtree_max_free_order;
>>   };
>>   +#define GPU_BUDDY_NO_FREE_ORDER (-1)
>> +
>>   /* Order-zero must be at least SZ_4K */
>>   #define GPU_BUDDY_MAX_ORDER (63 - 12)

  reply	other threads:[~2026-11-06 12:20 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-02  5:16 [PATCH v4 0/1] gpu/buddy: Fix quadratic cost of range-biased allocation Sanjay Yadav
2026-11-02  5:16 ` [PATCH v4 1/1] gpu/buddy: Prune exhausted subtrees in " Sanjay Yadav
2026-11-04 12:12   ` Yadav, Sanjay Kumar
2026-11-06 12:20     ` Yadav, Sanjay Kumar [this message]
2026-11-06 13:45     ` Joel Fernandes
2026-11-06 15:58       ` Yadav, Sanjay Kumar
2026-11-07 14:56   ` Joel Fernandes
2026-11-09  6:40   ` Arunpravin Paneer Selvam
2026-11-09 14:07     ` Palacek, William
2026-11-12 14:45       ` Arunpravin Paneer Selvam
2026-11-15 15:53     ` Yadav, Sanjay Kumar
2026-11-02  5:30 ` ✗ CI.checkpatch: warning for gpu/buddy: Fix quadratic cost of range-biased allocation (rev5) Patchwork
2026-11-02  5:33 ` ✓ CI.KUnit: success " Patchwork
2026-11-02  6:06 ` ✗ Xe.CI.BAT: failure " Patchwork
2026-11-02  6:34 ` ✗ Xe.CI.FULL: " Patchwork

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=2b70fda5-187f-4047-a742-533f11985593@intel.com \
    --to=sanjay.kumar.yadav@intel.com \
    --cc=arunpravin.paneerselvam@amd.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=joelagnelf@nvidia.com \
    --cc=matthew.auld@intel.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox