Skip to content

Commit 5a3e510

Browse files
committed
iommu: generalize the batched sync after map interface
JIRA: https://issues.redhat.com/browse/RHEL-113839 Upstream-Status: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git commit 5c87cff Author: Christoph Hellwig <hch@lst.de> Date: Mon May 5 10:01:40 2025 +0300 iommu: generalize the batched sync after map interface The IOMMU-DMA layer needs a batched sync-after-map interface that it can call after all the allocations and individual map operations are done to add a single sync point. Currently this is only exported by the IOMMU layer, but the same need will arise for DMA implementations that are not based on the IOMMU. Add a simple map of the existing is_sync_after_unmap field for this and add a helper to probe it. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org> Tested-by: Jens Axboe <axboe@kernel.dk> Reviewed-by: Luis Chamberlain <mcgrof@kernel.org> Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com> Signed-off-by: Leon Romanovsky <leonro@nvidia.com> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> (cherry picked from commit 5c87cff) Co-developed-by: Claude claude-sonnet-4 Signed-off-by: Jerry Snitselaar <jsnitsel@redhat.com>
1 parent bf31a47 commit 5a3e510

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
@@ -2409,8 +2409,8 @@ static size_t iommu_pgsize(struct iommu_domain *domain, unsigned long iova,
24092409
return pgsize;
24102410
}
24112411

2412-
static int __iommu_map(struct iommu_domain *domain, unsigned long iova,
2413-
phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
2412+
int iommu_map_nosync(struct iommu_domain *domain, unsigned long iova,
2413+
phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
24142414
{
24152415
const struct iommu_domain_ops *ops = domain->ops;
24162416
unsigned long orig_iova = iova;
@@ -2419,12 +2419,19 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova,
24192419
phys_addr_t orig_paddr = paddr;
24202420
int ret = 0;
24212421

2422+
might_sleep_if(gfpflags_allow_blocking(gfp));
2423+
24222424
if (unlikely(!(domain->type & __IOMMU_DOMAIN_PAGING)))
24232425
return -EINVAL;
24242426

24252427
if (WARN_ON(!ops->map_pages || domain->pgsize_bitmap == 0UL))
24262428
return -ENODEV;
24272429

2430+
/* Discourage passing strange GFP flags */
2431+
if (WARN_ON_ONCE(gfp & (__GFP_COMP | __GFP_DMA | __GFP_DMA32 |
2432+
__GFP_HIGHMEM)))
2433+
return -EINVAL;
2434+
24282435
/* find out the minimum page size supported */
24292436
min_pagesz = 1 << __ffs(domain->pgsize_bitmap);
24302437

@@ -2472,31 +2479,27 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova,
24722479
return ret;
24732480
}
24742481

2475-
int iommu_map(struct iommu_domain *domain, unsigned long iova,
2476-
phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
2482+
int iommu_sync_map(struct iommu_domain *domain, unsigned long iova, size_t size)
24772483
{
24782484
const struct iommu_domain_ops *ops = domain->ops;
2479-
int ret;
2480-
2481-
might_sleep_if(gfpflags_allow_blocking(gfp));
24822485

2483-
/* Discourage passing strange GFP flags */
2484-
if (WARN_ON_ONCE(gfp & (__GFP_COMP | __GFP_DMA | __GFP_DMA32 |
2485-
__GFP_HIGHMEM)))
2486-
return -EINVAL;
2486+
if (!ops->iotlb_sync_map)
2487+
return 0;
2488+
return ops->iotlb_sync_map(domain, iova, size);
2489+
}
24872490

2488-
ret = __iommu_map(domain, iova, paddr, size, prot, gfp);
2489-
if (ret == 0 && ops->iotlb_sync_map) {
2490-
ret = ops->iotlb_sync_map(domain, iova, size);
2491-
if (ret)
2492-
goto out_err;
2493-
}
2491+
int iommu_map(struct iommu_domain *domain, unsigned long iova,
2492+
phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
2493+
{
2494+
int ret;
24942495

2495-
return ret;
2496+
ret = iommu_map_nosync(domain, iova, paddr, size, prot, gfp);
2497+
if (ret)
2498+
return ret;
24962499

2497-
out_err:
2498-
/* undo mappings already done */
2499-
iommu_unmap(domain, iova, size);
2500+
ret = iommu_sync_map(domain, iova, size);
2501+
if (ret)
2502+
iommu_unmap(domain, iova, size);
25002503

25012504
return ret;
25022505
}
@@ -2596,26 +2599,17 @@ ssize_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
25962599
struct scatterlist *sg, unsigned int nents, int prot,
25972600
gfp_t gfp)
25982601
{
2599-
const struct iommu_domain_ops *ops = domain->ops;
26002602
size_t len = 0, mapped = 0;
26012603
phys_addr_t start;
26022604
unsigned int i = 0;
26032605
int ret;
26042606

2605-
might_sleep_if(gfpflags_allow_blocking(gfp));
2606-
2607-
/* Discourage passing strange GFP flags */
2608-
if (WARN_ON_ONCE(gfp & (__GFP_COMP | __GFP_DMA | __GFP_DMA32 |
2609-
__GFP_HIGHMEM)))
2610-
return -EINVAL;
2611-
26122607
while (i <= nents) {
26132608
phys_addr_t s_phys = sg_phys(sg);
26142609

26152610
if (len && s_phys != start + len) {
2616-
ret = __iommu_map(domain, iova + mapped, start,
2611+
ret = iommu_map_nosync(domain, iova + mapped, start,
26172612
len, prot, gfp);
2618-
26192613
if (ret)
26202614
goto out_err;
26212615

@@ -2638,11 +2632,10 @@ ssize_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
26382632
sg = sg_next(sg);
26392633
}
26402634

2641-
if (ops->iotlb_sync_map) {
2642-
ret = ops->iotlb_sync_map(domain, iova, mapped);
2643-
if (ret)
2644-
goto out_err;
2645-
}
2635+
ret = iommu_sync_map(domain, iova, mapped);
2636+
if (ret)
2637+
goto out_err;
2638+
26462639
return mapped;
26472640

26482641
out_err:

include/linux/iommu.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,10 @@ extern struct iommu_domain *iommu_get_domain_for_dev(struct device *dev);
857857
extern struct iommu_domain *iommu_get_dma_domain(struct device *dev);
858858
extern int iommu_map(struct iommu_domain *domain, unsigned long iova,
859859
phys_addr_t paddr, size_t size, int prot, gfp_t gfp);
860+
int iommu_map_nosync(struct iommu_domain *domain, unsigned long iova,
861+
phys_addr_t paddr, size_t size, int prot, gfp_t gfp);
862+
int iommu_sync_map(struct iommu_domain *domain, unsigned long iova,
863+
size_t size);
860864
extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova,
861865
size_t size);
862866
extern size_t iommu_unmap_fast(struct iommu_domain *domain,

0 commit comments

Comments
 (0)