drivers/gpu/drm/imagination/pvr_mmu.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/imagination/pvr_mmu.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/imagination/pvr_mmu.c
Extension
.c
Size
82508 bytes
Lines
2644
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 pvr_mmu_backing_page {
	dma_addr_t dma_addr;
	void *host_ptr;
/* private: internal use only */
	struct page *raw_page;
	struct pvr_device *pvr_dev;
};

/**
 * pvr_mmu_backing_page_init() - Initialize a MMU backing page.
 * @page: Target backing page.
 * @pvr_dev: Target PowerVR device.
 *
 * This function performs three distinct operations:
 *
 * 1. Allocate a single page,
 * 2. Map the page to the CPU, and
 * 3. Map the page to DMA-space.
 *
 * It is expected that @page be zeroed (e.g. from kzalloc()) before calling
 * this function.
 *
 * Return:
 *  * 0 on success, or
 *  * -%ENOMEM if allocation of the backing page or mapping of the backing
 *    page to DMA fails.
 */
static int
pvr_mmu_backing_page_init(struct pvr_mmu_backing_page *page,
			  struct pvr_device *pvr_dev)
{
	struct device *dev = from_pvr_device(pvr_dev)->dev;

	struct page *raw_page;
	pgprot_t prot;
	int err;

	dma_addr_t dma_addr;
	void *host_ptr;

	raw_page = alloc_page(__GFP_ZERO | GFP_KERNEL);
	if (!raw_page)
		return -ENOMEM;

	prot = PAGE_KERNEL;
	if (device_get_dma_attr(dev) != DEV_DMA_COHERENT)
		prot = pgprot_writecombine(prot);

	host_ptr = vmap(&raw_page, 1, VM_MAP, prot);
	if (!host_ptr) {
		err = -ENOMEM;
		goto err_free_page;
	}

	dma_addr = dma_map_page(dev, raw_page, 0, PVR_MMU_BACKING_PAGE_SIZE,
				DMA_TO_DEVICE);
	if (dma_mapping_error(dev, dma_addr)) {
		err = -ENOMEM;
		goto err_unmap_page;
	}

	page->dma_addr = dma_addr;
	page->host_ptr = host_ptr;
	page->pvr_dev = pvr_dev;
	page->raw_page = raw_page;
	kmemleak_alloc(page->host_ptr, PAGE_SIZE, 1, GFP_KERNEL);

	return 0;

err_unmap_page:
	vunmap(host_ptr);

err_free_page:
	__free_page(raw_page);

	return err;
}

/**
 * pvr_mmu_backing_page_fini() - Teardown a MMU backing page.
 * @page: Target backing page.
 *
 * This function performs the mirror operations to pvr_mmu_backing_page_init(),
 * in reverse order:
 *
 * 1. Unmap the page from DMA-space,
 * 2. Unmap the page from the CPU, and
 * 3. Free the page.
 *
 * It also zeros @page.

Annotation

Implementation Notes