Message ID | 20201119061836.15238-2-yong.wu@mediatek.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | MediaTek IOMMU improve tlb flush performance in map/unmap | expand |
On 2020-11-19 06:18, Yong Wu wrote: > In the end of __iommu_map, It alway call iotlb_sync_map. > This patch moves iotlb_sync_map out from __iommu_map since it is > unnecessary to call this for each sg segment especially iotlb_sync_map > is flush tlb all currently. I don't see a way to avoid the boilerplate that wouldn't end up making things even more ugly and complicated, so: Reviewed-by: Robin Murphy <robin.murphy@arm.com> > Signed-off-by: Yong Wu <yong.wu@mediatek.com> > --- > drivers/iommu/iommu.c | 24 +++++++++++++++++++----- > 1 file changed, 19 insertions(+), 5 deletions(-) > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > index 8c470f451a32..decef851fa3a 100644 > --- a/drivers/iommu/iommu.c > +++ b/drivers/iommu/iommu.c > @@ -2407,9 +2407,6 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova, > size -= pgsize; > } > > - if (ops->iotlb_sync_map) > - ops->iotlb_sync_map(domain); > - > /* unroll mapping in case something went wrong */ > if (ret) > iommu_unmap(domain, orig_iova, orig_size - size); > @@ -2422,15 +2419,29 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova, > int iommu_map(struct iommu_domain *domain, unsigned long iova, > phys_addr_t paddr, size_t size, int prot) > { > + const struct iommu_ops *ops = domain->ops; > + int ret; > + > might_sleep(); > - return __iommu_map(domain, iova, paddr, size, prot, GFP_KERNEL); > + ret = __iommu_map(domain, iova, paddr, size, prot, GFP_KERNEL); > + if (ret == 0 && ops->iotlb_sync_map) > + ops->iotlb_sync_map(domain); > + > + return ret; > } > EXPORT_SYMBOL_GPL(iommu_map); > > int iommu_map_atomic(struct iommu_domain *domain, unsigned long iova, > phys_addr_t paddr, size_t size, int prot) > { > - return __iommu_map(domain, iova, paddr, size, prot, GFP_ATOMIC); > + const struct iommu_ops *ops = domain->ops; > + int ret; > + > + ret = __iommu_map(domain, iova, paddr, size, prot, GFP_ATOMIC); > + if (ret == 0 && ops->iotlb_sync_map) > + ops->iotlb_sync_map(domain); > + > + return ret; > } > EXPORT_SYMBOL_GPL(iommu_map_atomic); > > @@ -2514,6 +2525,7 @@ static size_t __iommu_map_sg(struct iommu_domain *domain, unsigned long iova, > struct scatterlist *sg, unsigned int nents, int prot, > gfp_t gfp) > { > + const struct iommu_ops *ops = domain->ops; > size_t len = 0, mapped = 0; > phys_addr_t start; > unsigned int i = 0; > @@ -2544,6 +2556,8 @@ static size_t __iommu_map_sg(struct iommu_domain *domain, unsigned long iova, > sg = sg_next(sg); > } > > + if (ops->iotlb_sync_map) > + ops->iotlb_sync_map(domain); > return mapped; > > out_err: >
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 8c470f451a32..decef851fa3a 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -2407,9 +2407,6 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova, size -= pgsize; } - if (ops->iotlb_sync_map) - ops->iotlb_sync_map(domain); - /* unroll mapping in case something went wrong */ if (ret) iommu_unmap(domain, orig_iova, orig_size - size); @@ -2422,15 +2419,29 @@ static int __iommu_map(struct iommu_domain *domain, unsigned long iova, int iommu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot) { + const struct iommu_ops *ops = domain->ops; + int ret; + might_sleep(); - return __iommu_map(domain, iova, paddr, size, prot, GFP_KERNEL); + ret = __iommu_map(domain, iova, paddr, size, prot, GFP_KERNEL); + if (ret == 0 && ops->iotlb_sync_map) + ops->iotlb_sync_map(domain); + + return ret; } EXPORT_SYMBOL_GPL(iommu_map); int iommu_map_atomic(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot) { - return __iommu_map(domain, iova, paddr, size, prot, GFP_ATOMIC); + const struct iommu_ops *ops = domain->ops; + int ret; + + ret = __iommu_map(domain, iova, paddr, size, prot, GFP_ATOMIC); + if (ret == 0 && ops->iotlb_sync_map) + ops->iotlb_sync_map(domain); + + return ret; } EXPORT_SYMBOL_GPL(iommu_map_atomic); @@ -2514,6 +2525,7 @@ static size_t __iommu_map_sg(struct iommu_domain *domain, unsigned long iova, struct scatterlist *sg, unsigned int nents, int prot, gfp_t gfp) { + const struct iommu_ops *ops = domain->ops; size_t len = 0, mapped = 0; phys_addr_t start; unsigned int i = 0; @@ -2544,6 +2556,8 @@ static size_t __iommu_map_sg(struct iommu_domain *domain, unsigned long iova, sg = sg_next(sg); } + if (ops->iotlb_sync_map) + ops->iotlb_sync_map(domain); return mapped; out_err:
In the end of __iommu_map, It alway call iotlb_sync_map. This patch moves iotlb_sync_map out from __iommu_map since it is unnecessary to call this for each sg segment especially iotlb_sync_map is flush tlb all currently. Signed-off-by: Yong Wu <yong.wu@mediatek.com> --- drivers/iommu/iommu.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)