All of lore.kernel.org
 help / color / mirror / Atom feed
From: Matthew Auld <matthew.auld@intel.com>
To: Francois Dugast <francois.dugast@intel.com>,
	intel-xe@lists.freedesktop.org
Cc: dri-devel@lists.freedesktop.org
Subject: Re: [PATCH v3 5/5] gpu/buddy: Track per-order used blocks with a scoreboard
Date: Mon, 18 May 2026 17:02:32 +0100	[thread overview]
Message-ID: <ddfb5ef7-e01a-4a9d-aa16-bcd475338135@intel.com> (raw)
In-Reply-To: <20260518141446.124508-6-francois.dugast@intel.com>

On 18/05/2026 15:14, Francois Dugast wrote:
> Extend the scoreboard approach from the previous commit to used blocks,
> so drm_buddy_print() can report per-order allocation pressure in O(1).
> 
> Unlike free blocks, an allocated block can leave the allocated state
> through mark_free() (normal free and gpu_buddy_block_trim()) or be
> consumed directly by gpu_block_free() during coalescing. Both sites are
> guarded by gpu_buddy_block_is_allocated() and paired with the increment
> in mark_allocated().
> 
> v2:
> - Update after fix for use-after-free in split_block() call sites
> - Change goto label to out_free_used_scoreboard for clarity
> - Make drm_buddy_print() and gpu_buddy_print() symmetric for used and
>    free
> 
> Signed-off-by: Francois Dugast <francois.dugast@intel.com>
> Assisted-by: GitHub Copilot:claude-sonnet-4.6

Could potentially also assert that used_scoreboard is empty at fini(), 
as a quick sanity check that nothing got leaked/missed with the 
accounting. Would also then be checked across the selftests.

Reviewed-by: Matthew Auld <matthew.auld@intel.com>

> ---
>   drivers/gpu/buddy.c         | 39 +++++++++++++++++++++++++++----------
>   drivers/gpu/drm/drm_buddy.c | 18 +++++++++++------
>   include/linux/gpu_buddy.h   |  8 ++++++++
>   3 files changed, 49 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/buddy.c b/drivers/gpu/buddy.c
> index de18b63fef0a..f81d0d8fde15 100644
> --- a/drivers/gpu/buddy.c
> +++ b/drivers/gpu/buddy.c
> @@ -194,6 +194,7 @@ static void mark_allocated(struct gpu_buddy *mm,
>   	block->header |= GPU_BUDDY_ALLOCATED;
>   
>   	mm->free_scoreboard[gpu_buddy_block_order(block)]--;
> +	mm->used_scoreboard[gpu_buddy_block_order(block)]++;
>   
>   	rbtree_remove(mm, block);
>   }
> @@ -203,6 +204,9 @@ static void mark_free(struct gpu_buddy *mm,
>   {
>   	enum gpu_buddy_free_tree tree;
>   
> +	if (gpu_buddy_block_is_allocated(block))
> +		mm->used_scoreboard[gpu_buddy_block_order(block)]--;
> +
>   	block->header &= ~GPU_BUDDY_HEADER_STATE;
>   	block->header |= GPU_BUDDY_FREE;
>   
> @@ -281,6 +285,9 @@ static unsigned int __gpu_buddy_free(struct gpu_buddy *mm,
>   		if (force_merge && gpu_buddy_block_is_clear(buddy))
>   			mm->clear_avail -= gpu_buddy_block_size(mm, buddy);
>   
> +		if (gpu_buddy_block_is_allocated(block))
> +			mm->used_scoreboard[gpu_buddy_block_order(block)]--;
> +
>   		gpu_block_free(mm, block);
>   		gpu_block_free(mm, buddy);
>   
> @@ -398,11 +405,17 @@ int gpu_buddy_init(struct gpu_buddy *mm, u64 size, u64 chunk_size)
>   	if (!mm->free_scoreboard)
>   		return -ENOMEM;
>   
> +	mm->used_scoreboard = kcalloc(mm->max_order + 1,
> +				      sizeof(*mm->used_scoreboard),
> +				      GFP_KERNEL);
> +	if (!mm->used_scoreboard)
> +		goto out_free_free_scoreboard;
> +
>   	mm->free_trees = kmalloc_array(GPU_BUDDY_MAX_FREE_TREES,
>   				       sizeof(*mm->free_trees),
>   				       GFP_KERNEL);
>   	if (!mm->free_trees)
> -		goto out_free_scoreboard;
> +		goto out_free_used_scoreboard;
>   
>   	for_each_free_tree(i) {
>   		mm->free_trees[i] = kmalloc_array(mm->max_order + 1,
> @@ -464,7 +477,9 @@ int gpu_buddy_init(struct gpu_buddy *mm, u64 size, u64 chunk_size)
>   	while (i--)
>   		kfree(mm->free_trees[i]);
>   	kfree(mm->free_trees);
> -out_free_scoreboard:
> +out_free_used_scoreboard:
> +	kfree(mm->used_scoreboard);
> +out_free_free_scoreboard:
>   	kfree(mm->free_scoreboard);
>   	return -ENOMEM;
>   }
> @@ -505,6 +520,7 @@ void gpu_buddy_fini(struct gpu_buddy *mm)
>   	kfree(mm->free_trees);
>   	kfree(mm->roots);
>   	kfree(mm->free_scoreboard);
> +	kfree(mm->used_scoreboard);
>   }
>   EXPORT_SYMBOL(gpu_buddy_fini);
>   
> @@ -1505,15 +1521,18 @@ void gpu_buddy_print(struct gpu_buddy *mm)
>   		mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20, mm->clear_avail >> 20);
>   
>   	for (order = mm->max_order; order >= 0; order--) {
> -		u64 count = mm->free_scoreboard[order];
> -		u64 free = count * (mm->chunk_size << order);
> -
> -		if (free < SZ_1M)
> -			pr_info("order-%2d free: %8llu KiB, blocks: %llu\n",
> -				order, free >> 10, count);
> +		u64 free_count = mm->free_scoreboard[order];
> +		u64 used_count = mm->used_scoreboard[order];
> +		u64 block_size = mm->chunk_size << order;
> +		u64 free = free_count * block_size;
> +		u64 used = used_count * block_size;
> +
> +		if (block_size < SZ_1M)
> +			pr_info("order-%2d free: %8llu KiB, used: %8llu KiB, free_blocks: %llu, used_blocks: %llu\n",
> +				order, free >> 10, used >> 10, free_count, used_count);
>   		else
> -			pr_info("order-%2d free: %8llu MiB, blocks: %llu\n",
> -				order, free >> 20, count);
> +			pr_info("order-%2d free: %8llu MiB, used: %8llu MiB, free_blocks: %llu, used_blocks: %llu\n",
> +				order, free >> 20, used >> 20, free_count, used_count);
>   	}
>   }
>   EXPORT_SYMBOL(gpu_buddy_print);
> diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
> index eef995e08a37..1536e59c6fe7 100644
> --- a/drivers/gpu/drm/drm_buddy.c
> +++ b/drivers/gpu/drm/drm_buddy.c
> @@ -47,17 +47,23 @@ void drm_buddy_print(struct gpu_buddy *mm, struct drm_printer *p)
>   		   mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20, mm->clear_avail >> 20);
>   
>   	for (order = mm->max_order; order >= 0; order--) {
> -		u64 count = mm->free_scoreboard[order];
> -		u64 free = count * (mm->chunk_size << order);
> +		u64 free_count = mm->free_scoreboard[order];
> +		u64 used_count = mm->used_scoreboard[order];
> +		u64 block_size = mm->chunk_size << order;
> +		u64 free = free_count * block_size;
> +		u64 used = used_count * block_size;
>   
>   		drm_printf(p, "order-%2d ", order);
>   
> -		if (free < SZ_1M)
> -			drm_printf(p, "free: %8llu KiB", free >> 10);
> +		if (block_size < SZ_1M)
> +			drm_printf(p, "free: %8llu KiB, used: %8llu KiB",
> +				   free >> 10, used >> 10);
>   		else
> -			drm_printf(p, "free: %8llu MiB", free >> 20);
> +			drm_printf(p, "free: %8llu MiB, used: %8llu MiB",
> +				   free >> 20, used >> 20);
>   
> -		drm_printf(p, ", blocks: %llu\n", count);
> +		drm_printf(p, ", free_blocks: %llu, used_blocks: %llu\n",
> +			   free_count, used_count);
>   	}
>   }
>   EXPORT_SYMBOL(drm_buddy_print);
> diff --git a/include/linux/gpu_buddy.h b/include/linux/gpu_buddy.h
> index a28f7d7637ca..e037714563d8 100644
> --- a/include/linux/gpu_buddy.h
> +++ b/include/linux/gpu_buddy.h
> @@ -180,6 +180,14 @@ struct gpu_buddy {
>   	 * called on a free block.
>   	 */
>   	u64 *free_scoreboard;
> +	/*
> +	 * Per-order used block scoreboard: used_scoreboard[order] holds the
> +	 * number of blocks of that order currently in the allocated state.
> +	 * Incremented in mark_allocated(), decremented in mark_free() (guarded
> +	 * by gpu_buddy_block_is_allocated()) and in __gpu_buddy_free() when an
> +	 * allocated block is consumed directly during buddy coalescing.
> +	 */
> +	u64 *used_scoreboard;
>   /* public: */
>   	unsigned int n_roots;
>   	unsigned int max_order;


  reply	other threads:[~2026-05-18 16:02 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-18 14:14 [PATCH v3 0/5] gpu/buddy: Per-order free and used block scoreboards Francois Dugast
2026-05-18 14:14 ` [PATCH v3 1/5] gpu/buddy: Fix use-after-free in split_block() call sites Francois Dugast
2026-05-18 15:38   ` Matthew Auld
2026-05-18 15:55   ` Matthew Auld
2026-05-20 10:58     ` Francois Dugast
2026-05-21 16:18       ` Matthew Auld
2026-05-18 14:14 ` [PATCH v3 2/5] gpu/buddy: Remove redundant condition in alloc_from_freetree() error path Francois Dugast
2026-05-18 14:14 ` [PATCH v3 3/5] gpu/buddy: Introduce __gpu_buddy_undo_splits() helper Francois Dugast
2026-05-18 15:57   ` Matthew Auld
2026-05-18 14:14 ` [PATCH v3 4/5] gpu/buddy: Track per-order free blocks with a scoreboard Francois Dugast
2026-05-18 15:58   ` Matthew Auld
2026-05-18 14:14 ` [PATCH v3 5/5] gpu/buddy: Track per-order used " Francois Dugast
2026-05-18 16:02   ` Matthew Auld [this message]
2026-05-19 15:40     ` Francois Dugast
2026-05-18 14:40 ` ✗ CI.checkpatch: warning for gpu/buddy: Per-order free and used block scoreboards (rev4) Patchwork
2026-05-18 14:41 ` ✓ CI.KUnit: success " Patchwork
2026-05-18 15:33 ` ✓ Xe.CI.BAT: " Patchwork
2026-05-18 19:50 ` ✗ Xe.CI.FULL: failure " 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=ddfb5ef7-e01a-4a9d-aa16-bcd475338135@intel.com \
    --to=matthew.auld@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=francois.dugast@intel.com \
    --cc=intel-xe@lists.freedesktop.org \
    /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.