Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/msm: convert to iommu_map_sg

Significantly simplifies things. Also iommu_unmap() can unmap an entire
iova range.

(If backporting to downstream kernel you might need to revert this. Or
at least double check older iommu implementation.)

Signed-off-by: Rob Clark <robdclark@gmail.com>

+5 -49
+5 -49
drivers/gpu/drm/msm/msm_iommu.c
··· 52 52 struct sg_table *sgt, unsigned len, int prot) 53 53 { 54 54 struct msm_iommu *iommu = to_msm_iommu(mmu); 55 - struct iommu_domain *domain = iommu->domain; 56 - struct scatterlist *sg; 57 - unsigned long da = iova; 58 - unsigned int i, j; 59 - int ret; 55 + size_t ret; 60 56 61 - if (!domain || !sgt) 62 - return -EINVAL; 57 + ret = iommu_map_sg(iommu->domain, iova, sgt->sgl, sgt->nents, prot); 58 + WARN_ON(ret < 0); 63 59 64 - for_each_sg(sgt->sgl, sg, sgt->nents, i) { 65 - dma_addr_t pa = sg_phys(sg) - sg->offset; 66 - size_t bytes = sg->length + sg->offset; 67 - 68 - VERB("map[%d]: %08lx %08lx(%zx)", i, da, (unsigned long)pa, bytes); 69 - 70 - ret = iommu_map(domain, da, pa, bytes, prot); 71 - if (ret) 72 - goto fail; 73 - 74 - da += bytes; 75 - } 76 - 77 - return 0; 78 - 79 - fail: 80 - da = iova; 81 - 82 - for_each_sg(sgt->sgl, sg, i, j) { 83 - size_t bytes = sg->length + sg->offset; 84 - iommu_unmap(domain, da, bytes); 85 - da += bytes; 86 - } 87 - return ret; 60 + return (ret == len) ? 0 : -EINVAL; 88 61 } 89 62 90 63 static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova, 91 64 struct sg_table *sgt, unsigned len) 92 65 { 93 66 struct msm_iommu *iommu = to_msm_iommu(mmu); 94 - struct iommu_domain *domain = iommu->domain; 95 - struct scatterlist *sg; 96 - unsigned long da = iova; 97 - int i; 98 67 99 - for_each_sg(sgt->sgl, sg, sgt->nents, i) { 100 - size_t bytes = sg->length + sg->offset; 101 - size_t unmapped; 102 - 103 - unmapped = iommu_unmap(domain, da, bytes); 104 - if (unmapped < bytes) 105 - return unmapped; 106 - 107 - VERB("unmap[%d]: %08lx(%zx)", i, da, bytes); 108 - 109 - BUG_ON(!PAGE_ALIGNED(bytes)); 110 - 111 - da += bytes; 112 - } 68 + iommu_unmap(iommu->domain, iova, len); 113 69 114 70 return 0; 115 71 }