drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv44.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv44.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv44.c
Extension
.c
Size
6122 bytes
Lines
231
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

switch (ptei++ & 0x3) {
		case 0:
			tmp[0] &= ~0x07ffffff;
			tmp[0] |= addr;
			break;
		case 1:
			tmp[0] &= ~0xf8000000;
			tmp[0] |= addr << 27;
			tmp[1] &= ~0x003fffff;
			tmp[1] |= addr >> 5;
			break;
		case 2:
			tmp[1] &= ~0xffc00000;
			tmp[1] |= addr << 22;
			tmp[2] &= ~0x0001ffff;
			tmp[2] |= addr >> 10;
			break;
		case 3:
			tmp[2] &= ~0xfffe0000;
			tmp[2] |= addr << 17;
			tmp[3] &= ~0x00000fff;
			tmp[3] |= addr >> 15;
			break;
		}
	}

	VMM_WO032(pt, vmm, pteo + 0x0, tmp[0]);
	VMM_WO032(pt, vmm, pteo + 0x4, tmp[1]);
	VMM_WO032(pt, vmm, pteo + 0x8, tmp[2]);
	VMM_WO032(pt, vmm, pteo + 0xc, tmp[3] | 0x40000000);
}

static void
nv44_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
		 u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr)
{
	dma_addr_t tmp[4], i;

	if (ptei & 3) {
		const u32 pten = min(ptes, 4 - (ptei & 3));
		for (i = 0; i < pten; i++, addr += 0x1000)
			tmp[i] = addr;
		nv44_vmm_pgt_fill(vmm, pt, tmp, ptei, pten);
		ptei += pten;
		ptes -= pten;
	}

	while (ptes >= 4) {
		for (i = 0; i < 4; i++, addr += 0x1000)
			tmp[i] = addr >> 12;
		VMM_WO032(pt, vmm, ptei++ * 4, tmp[0] >>  0 | tmp[1] << 27);
		VMM_WO032(pt, vmm, ptei++ * 4, tmp[1] >>  5 | tmp[2] << 22);
		VMM_WO032(pt, vmm, ptei++ * 4, tmp[2] >> 10 | tmp[3] << 17);
		VMM_WO032(pt, vmm, ptei++ * 4, tmp[3] >> 15 | 0x40000000);
		ptes -= 4;
	}

	if (ptes) {
		for (i = 0; i < ptes; i++, addr += 0x1000)
			tmp[i] = addr;
		nv44_vmm_pgt_fill(vmm, pt, tmp, ptei, ptes);
	}
}

static void
nv44_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
		 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
{
	VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, nv44_vmm_pgt_pte);
}

static void
nv44_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
		 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
{
#if PAGE_SHIFT == 12
	nvkm_kmap(pt->memory);
	if (ptei & 3) {
		const u32 pten = min(ptes, 4 - (ptei & 3));
		nv44_vmm_pgt_fill(vmm, pt, map->dma, ptei, pten);
		ptei += pten;
		ptes -= pten;
		map->dma += pten;
	}

	while (ptes >= 4) {
		u32 tmp[4], i;
		for (i = 0; i < 4; i++)
			tmp[i] = *map->dma++ >> 12;
		VMM_WO032(pt, vmm, ptei++ * 4, tmp[0] >>  0 | tmp[1] << 27);

Annotation

Implementation Notes