drivers/gpu/drm/etnaviv/etnaviv_iommu.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/etnaviv/etnaviv_iommu.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/etnaviv/etnaviv_iommu.c
Extension
.c
Size
4728 bytes
Lines
177
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 etnaviv_iommuv1_context {
	struct etnaviv_iommu_context base;
	u32 *pgtable_cpu;
	dma_addr_t pgtable_dma;
};

static struct etnaviv_iommuv1_context *
to_v1_context(struct etnaviv_iommu_context *context)
{
	return container_of(context, struct etnaviv_iommuv1_context, base);
}

static void etnaviv_iommuv1_free(struct etnaviv_iommu_context *context)
{
	struct etnaviv_iommuv1_context *v1_context = to_v1_context(context);

	drm_mm_takedown(&context->mm);

	dma_free_wc(context->global->dev, PT_SIZE, v1_context->pgtable_cpu,
		    v1_context->pgtable_dma);

	context->global->v1.shared_context = NULL;

	kfree(v1_context);
}

static int etnaviv_iommuv1_map(struct etnaviv_iommu_context *context,
			       unsigned long iova, phys_addr_t paddr,
			       size_t size, int prot)
{
	struct etnaviv_iommuv1_context *v1_context = to_v1_context(context);
	unsigned int index = (iova - GPU_MEM_START) / SZ_4K;

	if (size != SZ_4K)
		return -EINVAL;

	v1_context->pgtable_cpu[index] = paddr;

	return 0;
}

static size_t etnaviv_iommuv1_unmap(struct etnaviv_iommu_context *context,
	unsigned long iova, size_t size)
{
	struct etnaviv_iommuv1_context *v1_context = to_v1_context(context);
	unsigned int index = (iova - GPU_MEM_START) / SZ_4K;

	if (size != SZ_4K)
		return -EINVAL;

	v1_context->pgtable_cpu[index] = context->global->bad_page_dma;

	return SZ_4K;
}

static size_t etnaviv_iommuv1_dump_size(struct etnaviv_iommu_context *context)
{
	return PT_SIZE;
}

static void etnaviv_iommuv1_dump(struct etnaviv_iommu_context *context,
				 void *buf)
{
	struct etnaviv_iommuv1_context *v1_context = to_v1_context(context);

	memcpy(buf, v1_context->pgtable_cpu, PT_SIZE);
}

static void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu,
			     struct etnaviv_iommu_context *context)
{
	struct etnaviv_iommuv1_context *v1_context = to_v1_context(context);
	u32 pgtable;

	if (gpu->mmu_context)
		etnaviv_iommu_context_put(gpu->mmu_context);
	gpu->mmu_context = etnaviv_iommu_context_get(context);

	/* set base addresses */
	gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_RA, context->global->memory_base);
	gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_FE, context->global->memory_base);
	gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_TX, context->global->memory_base);
	gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_PEZ, context->global->memory_base);
	gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_PE, context->global->memory_base);

	/* set page table address in MC */
	pgtable = (u32)v1_context->pgtable_dma;

	gpu_write(gpu, VIVS_MC_MMU_FE_PAGE_TABLE, pgtable);
	gpu_write(gpu, VIVS_MC_MMU_TX_PAGE_TABLE, pgtable);

Annotation

Implementation Notes