drivers/gpu/drm/nouveau/nvkm/core/mm.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/nouveau/nvkm/core/mm.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nvkm/core/mm.c
Extension
.c
Size
7339 bytes
Lines
308
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

if (prev && prev->type == NVKM_MM_TYPE_NONE) {
			prev->length += this->length;
			list_del(&this->nl_entry);
			kfree(this); this = prev;
		}

		if (next && next->type == NVKM_MM_TYPE_NONE) {
			next->offset  = this->offset;
			next->length += this->length;
			if (this->type == NVKM_MM_TYPE_NONE)
				list_del(&this->fl_entry);
			list_del(&this->nl_entry);
			kfree(this); this = NULL;
		}

		if (this && this->type != NVKM_MM_TYPE_NONE) {
			list_for_each_entry(prev, &mm->free, fl_entry) {
				if (this->offset < prev->offset)
					break;
			}

			list_add_tail(&this->fl_entry, &prev->fl_entry);
			this->type = NVKM_MM_TYPE_NONE;
		}
	}

	*pthis = NULL;
}

static struct nvkm_mm_node *
region_head(struct nvkm_mm *mm, struct nvkm_mm_node *a, u32 size)
{
	struct nvkm_mm_node *b;

	if (a->length == size)
		return a;

	b = kmalloc_obj(*b);
	if (unlikely(b == NULL))
		return NULL;

	b->offset = a->offset;
	b->length = size;
	b->heap   = a->heap;
	b->type   = a->type;
	a->offset += size;
	a->length -= size;
	list_add_tail(&b->nl_entry, &a->nl_entry);
	if (b->type == NVKM_MM_TYPE_NONE)
		list_add_tail(&b->fl_entry, &a->fl_entry);

	return b;
}

int
nvkm_mm_head(struct nvkm_mm *mm, u8 heap, u8 type, u32 size_max, u32 size_min,
	     u32 align, struct nvkm_mm_node **pnode)
{
	struct nvkm_mm_node *prev, *this, *next;
	u32 mask = align - 1;
	u32 splitoff;
	u32 s, e;

	BUG_ON(type == NVKM_MM_TYPE_NONE || type == NVKM_MM_TYPE_HOLE);

	list_for_each_entry(this, &mm->free, fl_entry) {
		if (unlikely(heap != NVKM_MM_HEAP_ANY)) {
			if (this->heap != heap)
				continue;
		}
		e = this->offset + this->length;
		s = this->offset;

		prev = node(this, prev);
		if (prev && prev->type != type)
			s = roundup(s, mm->block_size);

		next = node(this, next);
		if (next && next->type != type)
			e = rounddown(e, mm->block_size);

		s  = (s + mask) & ~mask;
		e &= ~mask;
		if (s > e || e - s < size_min)
			continue;

		splitoff = s - this->offset;
		if (splitoff && !region_head(mm, this, splitoff))
			return -ENOMEM;

Annotation

Implementation Notes