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

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c
Extension
.c
Size
17080 bytes
Lines
650
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 ((data & (3ULL << 1)) != 0) {
			addr = (data >> 8) << 12;
			dma_unmap_page(dev, addr, PAGE_SIZE, DMA_BIDIRECTIONAL);
		}
		ptei++;
	}
	nvkm_done(pt->memory);
}

static bool
gp100_vmm_pfn_clear(struct nvkm_vmm *vmm,
		    struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes)
{
	bool dma = false;
	nvkm_kmap(pt->memory);
	while (ptes--) {
		u32 datalo = nvkm_ro32(pt->memory, pt->base + ptei * 8 + 0);
		u32 datahi = nvkm_ro32(pt->memory, pt->base + ptei * 8 + 4);
		u64 data   = (u64)datahi << 32 | datalo;
		if ((data & BIT_ULL(0)) && (data & (3ULL << 1)) != 0) {
			VMM_WO064(pt, vmm, ptei * 8, data & ~BIT_ULL(0));
			dma = true;
		}
		ptei++;
	}
	nvkm_done(pt->memory);
	return dma;
}

static void
gp100_vmm_pgt_pfn(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
		  u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
{
	struct device *dev = vmm->mmu->subdev.device->dev;
	dma_addr_t addr;

	nvkm_kmap(pt->memory);
	for (; ptes; ptes--, map->pfn++) {
		u64 data = 0;

		if (!(*map->pfn & NVKM_VMM_PFN_V))
			continue;

		if (!(*map->pfn & NVKM_VMM_PFN_W))
			data |= BIT_ULL(6); /* RO. */

		if (!(*map->pfn & NVKM_VMM_PFN_A))
			data |= BIT_ULL(7); /* Atomic disable. */

		if (!(*map->pfn & NVKM_VMM_PFN_VRAM)) {
			addr = *map->pfn >> NVKM_VMM_PFN_ADDR_SHIFT;
			addr = dma_map_page(dev, pfn_to_page(addr), 0,
					    PAGE_SIZE, DMA_BIDIRECTIONAL);
			if (!WARN_ON(dma_mapping_error(dev, addr))) {
				data |= addr >> 4;
				data |= 2ULL << 1; /* SYSTEM_COHERENT_MEMORY. */
				data |= BIT_ULL(3); /* VOL. */
				data |= BIT_ULL(0); /* VALID. */
			}
		} else {
			data |= (*map->pfn & NVKM_VMM_PFN_ADDR) >> 4;
			data |= BIT_ULL(0); /* VALID. */
		}

		VMM_WO064(pt, vmm, ptei++ * 8, data);
	}
	nvkm_done(pt->memory);
}

static inline u64
gp100_vmm_comptag_nr(u64 size)
{
	return size >> 16; /* One comptag per 64KiB VRAM. */
}

static inline u64
gp100_vmm_pte_comptagline_base(u64 addr)
{
	/* RM allocates enough comptags for all of VRAM, so use a 1:1 mapping. */
	return (1 + gp100_vmm_comptag_nr(addr)) << 36; /* NV_MMU_VER2_PTE_COMPTAGLINE */
}

static inline u64
gp100_vmm_pte_comptagline_incr(u32 page_size)
{
	return gp100_vmm_comptag_nr(page_size) << 36; /* NV_MMU_VER2_PTE_COMPTAGLINE */
}

static inline void
gp100_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,

Annotation

Implementation Notes