drivers/gpu/drm/i915/i915_ttm_buddy_manager.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
Extension
.c
Size
12600 bytes
Lines
442
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct i915_ttm_buddy_manager {
	struct ttm_resource_manager manager;
	struct gpu_buddy mm;
	struct list_head reserved;
	struct mutex lock;
	unsigned long visible_size;
	unsigned long visible_avail;
	unsigned long visible_reserved;
	u64 default_page_size;
};

static struct i915_ttm_buddy_manager *
to_buddy_manager(struct ttm_resource_manager *man)
{
	return container_of(man, struct i915_ttm_buddy_manager, manager);
}

static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
				    struct ttm_buffer_object *bo,
				    const struct ttm_place *place,
				    struct ttm_resource **res)
{
	struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
	struct i915_ttm_buddy_resource *bman_res;
	struct gpu_buddy *mm = &bman->mm;
	unsigned long n_pages, lpfn;
	u64 min_page_size;
	u64 size;
	int err;

	lpfn = place->lpfn;
	if (!lpfn)
		lpfn = man->size;

	bman_res = kzalloc_obj(*bman_res);
	if (!bman_res)
		return -ENOMEM;

	ttm_resource_init(bo, place, &bman_res->base);
	INIT_LIST_HEAD(&bman_res->blocks);
	bman_res->mm = mm;

	if (place->flags & TTM_PL_FLAG_TOPDOWN)
		bman_res->flags |= GPU_BUDDY_TOPDOWN_ALLOCATION;

	if (place->flags & TTM_PL_FLAG_CONTIGUOUS)
		bman_res->flags |= GPU_BUDDY_CONTIGUOUS_ALLOCATION;

	if (place->fpfn || lpfn != man->size)
		bman_res->flags |= GPU_BUDDY_RANGE_ALLOCATION;

	GEM_BUG_ON(!bman_res->base.size);
	size = bman_res->base.size;

	min_page_size = bman->default_page_size;
	if (bo->page_alignment)
		min_page_size = bo->page_alignment << PAGE_SHIFT;

	GEM_BUG_ON(min_page_size < mm->chunk_size);
	GEM_BUG_ON(!IS_ALIGNED(size, min_page_size));

	if (size > lpfn << PAGE_SHIFT) {
		err = -E2BIG;
		goto err_free_res;
	}

	n_pages = size >> ilog2(mm->chunk_size);

	mutex_lock(&bman->lock);
	if (lpfn <= bman->visible_size && n_pages > bman->visible_avail) {
		mutex_unlock(&bman->lock);
		err = -ENOSPC;
		goto err_free_res;
	}

	err = gpu_buddy_alloc_blocks(mm, (u64)place->fpfn << PAGE_SHIFT,
				     (u64)lpfn << PAGE_SHIFT,
				     (u64)n_pages << PAGE_SHIFT,
				     min_page_size,
				     &bman_res->blocks,
				     bman_res->flags);
	if (unlikely(err))
		goto err_free_blocks;

	if (lpfn <= bman->visible_size) {
		bman_res->used_visible_size = PFN_UP(bman_res->base.size);
	} else {
		struct gpu_buddy_block *block;

		list_for_each_entry(block, &bman_res->blocks, link) {

Annotation

Implementation Notes