Files
linux/drivers/gpu/drm/drm_buddy.c
Francois Dugast 25d912475e gpu/buddy: Track per-order used blocks with a scoreboard
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().

v3:
- Assert scoreboard is empty at fini(), as sanity check (Matthew Auld)

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

Assisted-by: GitHub Copilot:claude-sonnet-4.6
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Link: https://lore.kernel.org/r/20260522092600.32818-6-francois.dugast@intel.com
Signed-off-by: Francois Dugast <francois.dugast@intel.com>
2026-05-29 13:44:01 +02:00

73 lines
1.9 KiB
C

// SPDX-License-Identifier: MIT
/*
* Copyright © 2021 Intel Corporation
*/
#include <kunit/test-bug.h>
#include <linux/export.h>
#include <linux/kmemleak.h>
#include <linux/module.h>
#include <linux/sizes.h>
#include <linux/gpu_buddy.h>
#include <drm/drm_buddy.h>
#include <drm/drm_print.h>
/**
* drm_buddy_block_print - print block information
*
* @mm: DRM buddy manager
* @block: DRM buddy block
* @p: DRM printer to use
*/
void drm_buddy_block_print(struct gpu_buddy *mm,
struct gpu_buddy_block *block,
struct drm_printer *p)
{
u64 start = gpu_buddy_block_offset(block);
u64 size = gpu_buddy_block_size(mm, block);
drm_printf(p, "%#018llx-%#018llx: %llu\n", start, start + size, size);
}
EXPORT_SYMBOL(drm_buddy_block_print);
/**
* drm_buddy_print - print allocator state
*
* @mm: DRM buddy manager
* @p: DRM printer to use
*/
void drm_buddy_print(struct gpu_buddy *mm, struct drm_printer *p)
{
int order;
gpu_buddy_driver_lock_held(mm);
drm_printf(p, "chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB, clear_free: %lluMiB\n",
mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20, mm->clear_avail >> 20);
for (order = mm->max_order; order >= 0; 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 (block_size < SZ_1M)
drm_printf(p, "free: %8llu KiB, used: %8llu KiB",
free >> 10, used >> 10);
else
drm_printf(p, "free: %8llu MiB, used: %8llu MiB",
free >> 20, used >> 20);
drm_printf(p, ", free_blocks: %llu, used_blocks: %llu\n",
free_count, used_count);
}
}
EXPORT_SYMBOL(drm_buddy_print);
MODULE_DESCRIPTION("DRM-specific GPU Buddy Allocator Print Helpers");
MODULE_LICENSE("Dual MIT/GPL");