drivers/staging/media/atomisp/pci/mmu/isp_mmu.c

Source file repositories/reference/linux-study-clean/drivers/staging/media/atomisp/pci/mmu/isp_mmu.c

File Facts

System
Linux kernel
Corpus path
drivers/staging/media/atomisp/pci/mmu/isp_mmu.c
Extension
.c
Size
12873 bytes
Lines
557
Domain
Driver Families
Bucket
drivers/staging
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 (ISP_PTE_VALID(mmu, pte)) {
			mmu_remap_error(mmu, l1_pt, l1_idx,
					l2_pt, idx, ptr, pte, phys);

			/* free all mapped pages */
			free_mmu_map(mmu, start, ptr);

			return -EINVAL;
		}

		pte = isp_pgaddr_to_pte_valid(mmu, phys);

		atomisp_set_pte(l2_pt, idx, pte);
		mmu->l2_pgt_refcount[l1_idx]++;
		ptr += (1U << ISP_L2PT_OFFSET);
		phys += (1U << ISP_L2PT_OFFSET);
	} while (ptr < end && idx < ISP_L2PT_PTES - 1);

	return 0;
}

/*
 * Update L1 page table according to isp virtual address and page physical
 * address
 */
static int mmu_l1_map(struct isp_mmu *mmu, phys_addr_t l1_pt,
		      unsigned int start, unsigned int end,
		      phys_addr_t phys)
{
	phys_addr_t l2_pt;
	unsigned int ptr, l1_aligned;
	unsigned int idx;
	unsigned int l2_pte;
	int ret;

	l1_pt &= ISP_PAGE_MASK;

	start = start & ISP_PAGE_MASK;
	end = ISP_PAGE_ALIGN(end);
	phys &= ISP_PAGE_MASK;

	ptr = start;
	do {
		idx = ISP_PTR_TO_L1_IDX(ptr);

		l2_pte = atomisp_get_pte(l1_pt, idx);

		if (!ISP_PTE_VALID(mmu, l2_pte)) {
			l2_pt = alloc_page_table(mmu);
			if (l2_pt == NULL_PAGE) {
				dev_err(atomisp_dev,
					"alloc page table fail.\n");

				/* free all mapped pages */
				free_mmu_map(mmu, start, ptr);

				return -ENOMEM;
			}

			l2_pte = isp_pgaddr_to_pte_valid(mmu, l2_pt);

			atomisp_set_pte(l1_pt, idx, l2_pte);
			mmu->l2_pgt_refcount[idx] = 0;
		}

		l2_pt = isp_pte_to_pgaddr(mmu, l2_pte);

		l1_aligned = (ptr & ISP_PAGE_MASK) + (1U << ISP_L1PT_OFFSET);

		if (l1_aligned < end) {
			ret = mmu_l2_map(mmu, l1_pt, idx,
					 l2_pt, ptr, l1_aligned, phys);
			phys += (l1_aligned - ptr);
			ptr = l1_aligned;
		} else {
			ret = mmu_l2_map(mmu, l1_pt, idx,
					 l2_pt, ptr, end, phys);
			phys += (end - ptr);
			ptr = end;
		}

		if (ret) {
			dev_err(atomisp_dev, "setup mapping in L2PT fail.\n");

			/* free all mapped pages */
			free_mmu_map(mmu, start, ptr);

			return -EINVAL;
		}
	} while (ptr < end && idx < ISP_L1PT_PTES);

Annotation

Implementation Notes