drivers/gpu/drm/msm/msm_iommu.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/msm/msm_iommu.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/msm/msm_iommu.c- Extension
.c- Size
- 21200 bytes
- Lines
- 804
- 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.
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/adreno-smmu-priv.hlinux/io-pgtable.hlinux/kmemleak.hmsm_drv.hmsm_gpu_trace.hmsm_mmu.h
Detected Declarations
struct msm_iommustruct msm_iommu_pagetablefunction calc_pgsizefunction msm_iommu_pagetable_unmapfunction msm_iommu_pagetable_map_prrfunction msm_iommu_pagetable_mapfunction for_each_sgtable_sgfunction msm_iommu_pagetable_destroyfunction msm_iommu_pagetable_paramsfunction msm_iommu_pagetable_walkfunction msm_iommu_pagetable_prealloc_countfunction get_pt_cachefunction msm_iommu_pagetable_prealloc_allocatefunction msm_iommu_pagetable_prealloc_cleanupfunction msm_iommu_pagetable_alloc_ptfunction msm_iommu_pagetable_free_ptfunction msm_iommu_tlb_flush_allfunction msm_iommu_tlb_flush_walkfunction msm_iommu_tlb_add_pagefunction get_tblszfunction msm_gpu_fault_handlerfunction msm_disp_fault_handlerfunction msm_iommu_set_stallfunction msm_iommu_detachfunction msm_iommu_mapfunction msm_iommu_unmapfunction msm_iommu_destroy
Annotated Snippet
struct msm_iommu {
struct msm_mmu base;
struct iommu_domain *domain;
struct mutex init_lock; /* protects pagetables counter and prr_page */
int pagetables;
struct page *prr_page;
struct kmem_cache *pt_cache;
};
#define to_msm_iommu(x) container_of(x, struct msm_iommu, base)
struct msm_iommu_pagetable {
struct msm_mmu base;
struct msm_mmu *parent;
struct io_pgtable_ops *pgtbl_ops;
const struct iommu_flush_ops *tlb;
struct device *iommu_dev;
unsigned long pgsize_bitmap; /* Bitmap of page sizes in use */
phys_addr_t ttbr;
u32 asid;
/** @root_page_table: Stores the root page table pointer. */
void *root_page_table;
};
static struct msm_iommu_pagetable *to_pagetable(struct msm_mmu *mmu)
{
return container_of(mmu, struct msm_iommu_pagetable, base);
}
/* based on iommu_pgsize() in iommu.c: */
static size_t calc_pgsize(struct msm_iommu_pagetable *pagetable,
unsigned long iova, phys_addr_t paddr,
size_t size, size_t *count)
{
unsigned int pgsize_idx, pgsize_idx_next;
unsigned long pgsizes;
size_t offset, pgsize, pgsize_next;
unsigned long addr_merge = paddr | iova;
/* Page sizes supported by the hardware and small enough for @size */
pgsizes = pagetable->pgsize_bitmap & GENMASK(__fls(size), 0);
/* Constrain the page sizes further based on the maximum alignment */
if (likely(addr_merge))
pgsizes &= GENMASK(__ffs(addr_merge), 0);
/* Make sure we have at least one suitable page size */
BUG_ON(!pgsizes);
/* Pick the biggest page size remaining */
pgsize_idx = __fls(pgsizes);
pgsize = BIT(pgsize_idx);
if (!count)
return pgsize;
/* Find the next biggest support page size, if it exists */
pgsizes = pagetable->pgsize_bitmap & ~GENMASK(pgsize_idx, 0);
if (!pgsizes)
goto out_set_count;
pgsize_idx_next = __ffs(pgsizes);
pgsize_next = BIT(pgsize_idx_next);
/*
* There's no point trying a bigger page size unless the virtual
* and physical addresses are similarly offset within the larger page.
*/
if ((iova ^ paddr) & (pgsize_next - 1))
goto out_set_count;
/* Calculate the offset to the next page size alignment boundary */
offset = pgsize_next - (addr_merge & (pgsize_next - 1));
/*
* If size is big enough to accommodate the larger page, reduce
* the number of smaller pages.
*/
if (offset + pgsize_next <= size)
size = offset;
out_set_count:
*count = size >> pgsize_idx;
return pgsize;
}
static int msm_iommu_pagetable_unmap(struct msm_mmu *mmu, u64 iova,
size_t size)
{
Annotation
- Immediate include surface: `linux/adreno-smmu-priv.h`, `linux/io-pgtable.h`, `linux/kmemleak.h`, `msm_drv.h`, `msm_gpu_trace.h`, `msm_mmu.h`.
- Detected declarations: `struct msm_iommu`, `struct msm_iommu_pagetable`, `function calc_pgsize`, `function msm_iommu_pagetable_unmap`, `function msm_iommu_pagetable_map_prr`, `function msm_iommu_pagetable_map`, `function for_each_sgtable_sg`, `function msm_iommu_pagetable_destroy`, `function msm_iommu_pagetable_params`, `function msm_iommu_pagetable_walk`.
- Atlas domain: Driver Families / drivers/gpu.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.