We're going to re-use these in the next commit. No functional changes, just some ugly callbacks.
Signed-off-by: Rob Clark <[email protected]> --- drivers/gpu/drm/msm/msm_iommu.c | 150 ++++++++++++++++++++------------ 1 file changed, 93 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index da6782fca6bd..a658493f8007 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -52,9 +52,8 @@ static struct msm_iommu_pagetable *to_pagetable(struct msm_mmu *mmu) } /* 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) +static size_t calc_pgsize(unsigned long pgsize_bitmap, unsigned long iova, + phys_addr_t paddr, size_t size, size_t *count) { unsigned int pgsize_idx, pgsize_idx_next; unsigned long pgsizes; @@ -62,7 +61,7 @@ static size_t calc_pgsize(struct msm_iommu_pagetable *pagetable, 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); + pgsizes = pgsize_bitmap & GENMASK(__fls(size), 0); /* Constrain the page sizes further based on the maximum alignment */ if (likely(addr_merge)) @@ -78,7 +77,7 @@ static size_t calc_pgsize(struct msm_iommu_pagetable *pagetable, return pgsize; /* Find the next biggest support page size, if it exists */ - pgsizes = pagetable->pgsize_bitmap & ~GENMASK(pgsize_idx, 0); + pgsizes = pgsize_bitmap & ~GENMASK(pgsize_idx, 0); if (!pgsizes) goto out_set_count; @@ -107,24 +106,27 @@ static size_t calc_pgsize(struct msm_iommu_pagetable *pagetable, return pgsize; } -static int msm_iommu_pagetable_unmap(struct msm_mmu *mmu, u64 iova, - size_t size) +typedef size_t (*unmap_fn)(void *arg, u64 iova, size_t pgsize, size_t count); +typedef int (*map_fn)(void *arg, phys_addr_t paddr, u64 iova, size_t pgsize, + size_t pgcount, int prot, size_t *mapped); + +static inline int +__do_unmap(unsigned long pgsize_bitmap, u64 iova, size_t size, + void *arg, unmap_fn unmap) { - struct msm_iommu_pagetable *pagetable = to_pagetable(mmu); - struct io_pgtable_ops *ops = pagetable->pgtbl_ops; int ret = 0; while (size) { size_t pgsize, count; ssize_t unmapped; - pgsize = calc_pgsize(pagetable, iova, iova, size, &count); + pgsize = calc_pgsize(pgsize_bitmap, iova, iova, size, &count); - unmapped = ops->unmap_pages(ops, iova, pgsize, count, NULL); + unmapped = unmap(arg, iova, pgsize, count); if (unmapped <= 0) { ret = -EINVAL; /* - * Continue attempting to unamp the remained of the + * Continue attempting to unmap the remained of the * range, so we don't end up with some dangling * mapped pages */ @@ -135,55 +137,18 @@ static int msm_iommu_pagetable_unmap(struct msm_mmu *mmu, u64 iova, size -= unmapped; } - iommu_flush_iotlb_all(to_msm_iommu(pagetable->parent)->domain); - return ret; } -static int msm_iommu_pagetable_map_prr(struct msm_mmu *mmu, u64 iova, size_t len, int prot) -{ - struct msm_iommu_pagetable *pagetable = to_pagetable(mmu); - struct io_pgtable_ops *ops = pagetable->pgtbl_ops; - struct msm_iommu *iommu = to_msm_iommu(pagetable->parent); - phys_addr_t phys = page_to_phys(iommu->prr_page); - u64 addr = iova; - - while (len) { - size_t mapped = 0; - size_t size = PAGE_SIZE; - int ret; - - ret = ops->map_pages(ops, addr, phys, size, 1, prot, GFP_KERNEL, &mapped); - - /* map_pages could fail after mapping some of the pages, - * so update the counters before error handling. - */ - addr += mapped; - len -= mapped; - - if (ret) { - msm_iommu_pagetable_unmap(mmu, iova, addr - iova); - return -EINVAL; - } - } - - return 0; -} - -static int msm_iommu_pagetable_map(struct msm_mmu *mmu, u64 iova, - struct sg_table *sgt, size_t off, size_t len, - int prot) +static inline int +__do_map(unsigned long pgsize_bitmap, u64 iova, struct sg_table *sgt, size_t off, + size_t len, int prot, void *arg, map_fn map, unmap_fn unmap) { - struct msm_iommu_pagetable *pagetable = to_pagetable(mmu); - struct io_pgtable_ops *ops = pagetable->pgtbl_ops; struct scatterlist *sg; u64 addr = iova; unsigned int i; - if (!sgt) - return msm_iommu_pagetable_map_prr(mmu, iova, len, prot); - - for_each_sgtable_sg(sgt, sg, i) { + for_each_sgtable_sg (sgt, sg, i) { size_t size = sg->length; phys_addr_t phys = sg_phys(sg); @@ -204,10 +169,9 @@ static int msm_iommu_pagetable_map(struct msm_mmu *mmu, u64 iova, size_t pgsize, count, mapped = 0; int ret; - pgsize = calc_pgsize(pagetable, addr, phys, size, &count); + pgsize = calc_pgsize(pgsize_bitmap, addr, phys, size, &count); - ret = ops->map_pages(ops, addr, phys, pgsize, count, - prot, GFP_KERNEL, &mapped); + ret = map(arg, phys, addr, pgsize, count, prot, &mapped); /* map_pages could fail after mapping some of the pages, * so update the counters before error handling. @@ -218,7 +182,7 @@ static int msm_iommu_pagetable_map(struct msm_mmu *mmu, u64 iova, len -= mapped; if (ret) { - msm_iommu_pagetable_unmap(mmu, iova, addr - iova); + __do_unmap(pgsize_bitmap, iova, addr - iova, arg, unmap); return -EINVAL; } } @@ -227,6 +191,78 @@ static int msm_iommu_pagetable_map(struct msm_mmu *mmu, u64 iova, return 0; } +static size_t +__unmap_pgtable(void *arg, u64 iova, size_t pgsize, size_t pgcount) +{ + struct io_pgtable_ops *ops = arg; + return ops->unmap_pages(ops, iova, pgsize, pgcount, NULL); +} + +static int +__map_pgtable(void *arg, phys_addr_t paddr, u64 iova, size_t pgsize, + size_t pgcount, int prot, size_t *mapped) +{ + struct io_pgtable_ops *ops = arg; + return ops->map_pages(ops, iova, paddr, pgsize, pgcount, prot, GFP_KERNEL, mapped); +} + +static int msm_iommu_pagetable_unmap(struct msm_mmu *mmu, u64 iova, size_t size) +{ + struct msm_iommu_pagetable *pagetable = to_pagetable(mmu); + struct io_pgtable_ops *ops = pagetable->pgtbl_ops; + int ret = 0; + + ret = __do_unmap(pagetable->pgsize_bitmap, iova, size, ops, __unmap_pgtable); + + iommu_flush_iotlb_all(to_msm_iommu(pagetable->parent)->domain); + + return ret; +} + +static int msm_iommu_pagetable_map_prr(struct msm_mmu *mmu, u64 iova, size_t len, int prot) +{ + struct msm_iommu_pagetable *pagetable = to_pagetable(mmu); + struct io_pgtable_ops *ops = pagetable->pgtbl_ops; + struct msm_iommu *iommu = to_msm_iommu(pagetable->parent); + phys_addr_t phys = page_to_phys(iommu->prr_page); + u64 addr = iova; + + while (len) { + size_t mapped = 0; + size_t size = PAGE_SIZE; + int ret; + + ret = ops->map_pages(ops, addr, phys, size, 1, prot, GFP_KERNEL, &mapped); + + /* map_pages could fail after mapping some of the pages, + * so update the counters before error handling. + */ + addr += mapped; + len -= mapped; + + if (ret) { + msm_iommu_pagetable_unmap(mmu, iova, addr - iova); + return -EINVAL; + } + } + + return 0; +} + +static int msm_iommu_pagetable_map(struct msm_mmu *mmu, u64 iova, + struct sg_table *sgt, size_t off, size_t len, + int prot) +{ + struct msm_iommu_pagetable *pagetable = to_pagetable(mmu); + struct io_pgtable_ops *ops = pagetable->pgtbl_ops; + + if (!sgt) + return msm_iommu_pagetable_map_prr(mmu, iova, len, prot); + + return __do_map(pagetable->pgsize_bitmap, iova, sgt, off, len, prot, + ops, __map_pgtable, __unmap_pgtable); +} + static void msm_iommu_pagetable_destroy(struct msm_mmu *mmu) { struct msm_iommu_pagetable *pagetable = to_pagetable(mmu); -- 2.55.0
