drivers/gpu/drm/lima/lima_vm.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/lima/lima_vm.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/lima/lima_vm.c
Extension
.c
Size
6430 bytes
Lines
323
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 lima_bo_va {
	struct list_head list;
	unsigned int ref_count;

	struct drm_mm_node node;

	struct lima_vm *vm;
};

#define LIMA_VM_PD_SHIFT 22
#define LIMA_VM_PT_SHIFT 12
#define LIMA_VM_PB_SHIFT (LIMA_VM_PD_SHIFT + LIMA_VM_NUM_PT_PER_BT_SHIFT)
#define LIMA_VM_BT_SHIFT LIMA_VM_PT_SHIFT

#define LIMA_VM_PT_MASK ((1 << LIMA_VM_PD_SHIFT) - 1)
#define LIMA_VM_BT_MASK ((1 << LIMA_VM_PB_SHIFT) - 1)

#define LIMA_PDE(va) (va >> LIMA_VM_PD_SHIFT)
#define LIMA_PTE(va) ((va & LIMA_VM_PT_MASK) >> LIMA_VM_PT_SHIFT)
#define LIMA_PBE(va) (va >> LIMA_VM_PB_SHIFT)
#define LIMA_BTE(va) ((va & LIMA_VM_BT_MASK) >> LIMA_VM_BT_SHIFT)


static void lima_vm_unmap_range(struct lima_vm *vm, u32 start, u32 end)
{
	u32 addr;

	for (addr = start; addr <= end; addr += LIMA_PAGE_SIZE) {
		u32 pbe = LIMA_PBE(addr);
		u32 bte = LIMA_BTE(addr);

		vm->bts[pbe].cpu[bte] = 0;
	}
}

static int lima_vm_map_page(struct lima_vm *vm, dma_addr_t pa, u32 va)
{
	u32 pbe = LIMA_PBE(va);
	u32 bte = LIMA_BTE(va);

	if (!vm->bts[pbe].cpu) {
		dma_addr_t pts;
		u32 *pd;
		int j;

		vm->bts[pbe].cpu = dma_alloc_wc(
			vm->dev->dev, LIMA_PAGE_SIZE << LIMA_VM_NUM_PT_PER_BT_SHIFT,
			&vm->bts[pbe].dma, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO);
		if (!vm->bts[pbe].cpu)
			return -ENOMEM;

		pts = vm->bts[pbe].dma;
		pd = vm->pd.cpu + (pbe << LIMA_VM_NUM_PT_PER_BT_SHIFT);
		for (j = 0; j < LIMA_VM_NUM_PT_PER_BT; j++) {
			pd[j] = pts | LIMA_VM_FLAG_PRESENT;
			pts += LIMA_PAGE_SIZE;
		}
	}

	vm->bts[pbe].cpu[bte] = pa | LIMA_VM_FLAGS_CACHE;

	return 0;
}

static struct lima_bo_va *
lima_vm_bo_find(struct lima_vm *vm, struct lima_bo *bo)
{
	struct lima_bo_va *bo_va, *ret = NULL;

	list_for_each_entry(bo_va, &bo->va, list) {
		if (bo_va->vm == vm) {
			ret = bo_va;
			break;
		}
	}

	return ret;
}

int lima_vm_bo_add(struct lima_vm *vm, struct lima_bo *bo, bool create)
{
	struct lima_bo_va *bo_va;
	struct sg_dma_page_iter sg_iter;
	int offset = 0, err;

	mutex_lock(&bo->lock);

	bo_va = lima_vm_bo_find(vm, bo);
	if (bo_va) {
		bo_va->ref_count++;

Annotation

Implementation Notes