Implement iova_to_phys_length for Exynos IOMMU driver, returning the actual PTE mapping size. Signed-off-by: Guanghui Feng --- drivers/iommu/exynos-iommu.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 874d05f4b396..17d77b9114c4 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -1372,13 +1372,14 @@ static size_t exynos_iommu_unmap(struct iommu_domain *iommu_domain, return 0; } -static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *iommu_domain, - dma_addr_t iova) +static phys_addr_t exynos_iommu_iova_to_phys_length(struct iommu_domain *iommu_domain, + dma_addr_t iova, + size_t *mapped_length) { struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain); sysmmu_pte_t *entry; unsigned long flags; - phys_addr_t phys = 0; + phys_addr_t phys = PHYS_ADDR_MAX; spin_lock_irqsave(&domain->pgtablelock, flags); @@ -1386,13 +1387,20 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *iommu_domain, if (lv1ent_section(entry)) { phys = section_phys(entry) + section_offs(iova); + if (mapped_length) + *mapped_length = SECT_SIZE; } else if (lv1ent_page(entry)) { entry = page_entry(entry, iova); - if (lv2ent_large(entry)) + if (lv2ent_large(entry)) { phys = lpage_phys(entry) + lpage_offs(iova); - else if (lv2ent_small(entry)) + if (mapped_length) + *mapped_length = LPAGE_SIZE; + } else if (lv2ent_small(entry)) { phys = spage_phys(entry) + spage_offs(iova); + if (mapped_length) + *mapped_length = SPAGE_SIZE; + } } spin_unlock_irqrestore(&domain->pgtablelock, flags); @@ -1484,7 +1492,7 @@ static const struct iommu_ops exynos_iommu_ops = { .attach_dev = exynos_iommu_attach_device, .map_pages = exynos_iommu_map, .unmap_pages = exynos_iommu_unmap, - .iova_to_phys = exynos_iommu_iova_to_phys, + .iova_to_phys_length = exynos_iommu_iova_to_phys_length, .free = exynos_iommu_domain_free, } }; -- 2.43.7