Skip to content

Commit 5c87cff

Browse files
Christoph Hellwigmszyprow
authored andcommitted
iommu: generalize the batched sync after map interface
For the upcoming IOVA-based DMA API we want to batch the ops->iotlb_sync_map() call after mapping multiple IOVAs from dma-iommu without having a scatterlist. Improve the API. Add a wrapper for the map_sync as iommu_sync_map() so that callers don't need to poke into the methods directly. Formalize __iommu_map() into iommu_map_nosync() which requires the caller to call iommu_sync_map() after all maps are completed. Refactor the existing sanity checks from all the different layers into iommu_map_nosync(). Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Will Deacon <will@kernel.org> Tested-by: Jens Axboe <axboe@kernel.dk> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Luis Chamberlain <mcgrof@kernel.org> Signed-off-by: Leon Romanovsky <leonro@nvidia.com> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
1 parent ca2c2e4 commit 5c87cff

File tree

2 files changed

+33
-36
lines changed

2 files changed

+33
-36
lines changed

drivers/iommu/iommu.c

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2440,8 +2440,8 @@ static size_t iommu_pgsize(struct iommu_domain *domain, unsigned long iova,
24402440
return pgsize;
24412441
}
24422442

2443-
static int __iommu_map(struct iommu_domain *domain, unsigned long iova,
2444-
phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
2443+
int iommu_map_nosync(struct iommu_domain *domain, unsigned long iova,
2444+
phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
24452445
{
24462446
const struct iommu_domain_ops *ops = domain->ops;
24472447
unsigned long orig_iova = iova;
@@ -2450,12 +2450,19 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova,
24502450
phys_addr_t orig_paddr = paddr;
24512451
int ret = 0;
24522452

2453+
might_sleep_if(gfpflags_allow_blocking(gfp));
2454+
24532455
if (unlikely(!(domain->type & __IOMMU_DOMAIN_PAGING)))
24542456
return -EINVAL;
24552457

24562458
if (WARN_ON(!ops->map_pages || domain->pgsize_bitmap == 0UL))
24572459
return -ENODEV;
24582460

2461+
/* Discourage passing strange GFP flags */
2462+
if (WARN_ON_ONCE(gfp & (__GFP_COMP | __GFP_DMA | __GFP_DMA32 |
2463+
__GFP_HIGHMEM)))
2464+
return -EINVAL;
2465+
24592466
/* find out the minimum page size supported */
24602467
min_pagesz = 1 << __ffs(domain->pgsize_bitmap);
24612468

@@ -2503,31 +2510,27 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova,
25032510
return ret;
25042511
}
25052512

2506-
int iommu_map(struct iommu_domain *domain, unsigned long iova,
2507-
phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
2513+
int iommu_sync_map(struct iommu_domain *domain, unsigned long iova, size_t size)
25082514
{
25092515
const struct iommu_domain_ops *ops = domain->ops;
2510-
int ret;
2511-
2512-
might_sleep_if(gfpflags_allow_blocking(gfp));
25132516

2514-
/* Discourage passing strange GFP flags */
2515-
if (WARN_ON_ONCE(gfp & (__GFP_COMP | __GFP_DMA | __GFP_DMA32 |
2516-
__GFP_HIGHMEM)))
2517-
return -EINVAL;
2517+
if (!ops->iotlb_sync_map)
2518+
return 0;
2519+
return ops->iotlb_sync_map(domain, iova, size);
2520+
}
25182521

2519-
ret = __iommu_map(domain, iova, paddr, size, prot, gfp);
2520-
if (ret == 0 && ops->iotlb_sync_map) {
2521-
ret = ops->iotlb_sync_map(domain, iova, size);
2522-
if (ret)
2523-
goto out_err;
2524-
}
2522+
int iommu_map(struct iommu_domain *domain, unsigned long iova,
2523+
phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
2524+
{
2525+
int ret;
25252526

2526-
return ret;
2527+
ret = iommu_map_nosync(domain, iova, paddr, size, prot, gfp);
2528+
if (ret)
2529+
return ret;
25272530

2528-
out_err:
2529-
/* undo mappings already done */
2530-
iommu_unmap(domain, iova, size);
2531+
ret = iommu_sync_map(domain, iova, size);
2532+
if (ret)
2533+
iommu_unmap(domain, iova, size);
25312534

25322535
return ret;
25332536
}
@@ -2627,26 +2630,17 @@ ssize_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
26272630
struct scatterlist *sg, unsigned int nents, int prot,
26282631
gfp_t gfp)
26292632
{
2630-
const struct iommu_domain_ops *ops = domain->ops;
26312633
size_t len = 0, mapped = 0;
26322634
phys_addr_t start;
26332635
unsigned int i = 0;
26342636
int ret;
26352637

2636-
might_sleep_if(gfpflags_allow_blocking(gfp));
2637-
2638-
/* Discourage passing strange GFP flags */
2639-
if (WARN_ON_ONCE(gfp & (__GFP_COMP | __GFP_DMA | __GFP_DMA32 |
2640-
__GFP_HIGHMEM)))
2641-
return -EINVAL;
2642-
26432638
while (i <= nents) {
26442639
phys_addr_t s_phys = sg_phys(sg);
26452640

26462641
if (len && s_phys != start + len) {
2647-
ret = __iommu_map(domain, iova + mapped, start,
2642+
ret = iommu_map_nosync(domain, iova + mapped, start,
26482643
len, prot, gfp);
2649-
26502644
if (ret)
26512645
goto out_err;
26522646

@@ -2669,11 +2663,10 @@ ssize_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
26692663
sg = sg_next(sg);
26702664
}
26712665

2672-
if (ops->iotlb_sync_map) {
2673-
ret = ops->iotlb_sync_map(domain, iova, mapped);
2674-
if (ret)
2675-
goto out_err;
2676-
}
2666+
ret = iommu_sync_map(domain, iova, mapped);
2667+
if (ret)
2668+
goto out_err;
2669+
26772670
return mapped;
26782671

26792672
out_err:

include/linux/iommu.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,10 @@ extern struct iommu_domain *iommu_get_domain_for_dev(struct device *dev);
872872
extern struct iommu_domain *iommu_get_dma_domain(struct device *dev);
873873
extern int iommu_map(struct iommu_domain *domain, unsigned long iova,
874874
phys_addr_t paddr, size_t size, int prot, gfp_t gfp);
875+
int iommu_map_nosync(struct iommu_domain *domain, unsigned long iova,
876+
phys_addr_t paddr, size_t size, int prot, gfp_t gfp);
877+
int iommu_sync_map(struct iommu_domain *domain, unsigned long iova,
878+
size_t size);
875879
extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova,
876880
size_t size);
877881
extern size_t iommu_unmap_fast(struct iommu_domain *domain,

0 commit comments

Comments
 (0)