Skip to content

Commit 647c577

Browse files
Isaac J. Manjarresjoergroedel
authored andcommitted
iommu: Add support for the map_pages() callback
Since iommu_pgsize can calculate how many pages of the same size can be mapped/unmapped before the next largest page size boundary, add support for invoking an IOMMU driver's map_pages() callback, if it provides one. Signed-off-by: Isaac J. Manjarres <[email protected]> Suggested-by: Will Deacon <[email protected]> Signed-off-by: Georgi Djakov <[email protected]> Reviewed-by: Lu Baolu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent b1d99dc commit 647c577

File tree

1 file changed

+35
-8
lines changed

1 file changed

+35
-8
lines changed

drivers/iommu/iommu.c

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2429,6 +2429,30 @@ static size_t iommu_pgsize(struct iommu_domain *domain, unsigned long iova,
24292429
return pgsize;
24302430
}
24312431

2432+
static int __iommu_map_pages(struct iommu_domain *domain, unsigned long iova,
2433+
phys_addr_t paddr, size_t size, int prot,
2434+
gfp_t gfp, size_t *mapped)
2435+
{
2436+
const struct iommu_ops *ops = domain->ops;
2437+
size_t pgsize, count;
2438+
int ret;
2439+
2440+
pgsize = iommu_pgsize(domain, iova, paddr, size, &count);
2441+
2442+
pr_debug("mapping: iova 0x%lx pa %pa pgsize 0x%zx count %zu\n",
2443+
iova, &paddr, pgsize, count);
2444+
2445+
if (ops->map_pages) {
2446+
ret = ops->map_pages(domain, iova, paddr, pgsize, count, prot,
2447+
gfp, mapped);
2448+
} else {
2449+
ret = ops->map(domain, iova, paddr, pgsize, prot, gfp);
2450+
*mapped = ret ? 0 : pgsize;
2451+
}
2452+
2453+
return ret;
2454+
}
2455+
24322456
static int __iommu_map(struct iommu_domain *domain, unsigned long iova,
24332457
phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
24342458
{
@@ -2439,7 +2463,7 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova,
24392463
phys_addr_t orig_paddr = paddr;
24402464
int ret = 0;
24412465

2442-
if (unlikely(ops->map == NULL ||
2466+
if (unlikely(!(ops->map || ops->map_pages) ||
24432467
domain->pgsize_bitmap == 0UL))
24442468
return -ENODEV;
24452469

@@ -2463,18 +2487,21 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova,
24632487
pr_debug("map: iova 0x%lx pa %pa size 0x%zx\n", iova, &paddr, size);
24642488

24652489
while (size) {
2466-
size_t pgsize = iommu_pgsize(domain, iova, paddr, size, NULL);
2490+
size_t mapped = 0;
24672491

2468-
pr_debug("mapping: iova 0x%lx pa %pa pgsize 0x%zx\n",
2469-
iova, &paddr, pgsize);
2470-
ret = ops->map(domain, iova, paddr, pgsize, prot, gfp);
2492+
ret = __iommu_map_pages(domain, iova, paddr, size, prot, gfp,
2493+
&mapped);
2494+
/*
2495+
* Some pages may have been mapped, even if an error occurred,
2496+
* so we should account for those so they can be unmapped.
2497+
*/
2498+
size -= mapped;
24712499

24722500
if (ret)
24732501
break;
24742502

2475-
iova += pgsize;
2476-
paddr += pgsize;
2477-
size -= pgsize;
2503+
iova += mapped;
2504+
paddr += mapped;
24782505
}
24792506

24802507
/* unroll mapping in case something went wrong */

0 commit comments

Comments
 (0)