diff options
-rw-r--r-- | drivers/iommu/iommu.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 02e4313e937c..1bd63352ab17 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c | |||
@@ -1143,14 +1143,24 @@ size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long iova, | |||
1143 | { | 1143 | { |
1144 | struct scatterlist *s; | 1144 | struct scatterlist *s; |
1145 | size_t mapped = 0; | 1145 | size_t mapped = 0; |
1146 | unsigned int i; | 1146 | unsigned int i, min_pagesz; |
1147 | int ret; | 1147 | int ret; |
1148 | 1148 | ||
1149 | for_each_sg(sg, s, nents, i) { | 1149 | if (unlikely(domain->ops->pgsize_bitmap == 0UL)) |
1150 | phys_addr_t phys = page_to_phys(sg_page(s)); | 1150 | return 0; |
1151 | 1151 | ||
1152 | /* We are mapping on page boundarys, so offset must be 0 */ | 1152 | min_pagesz = 1 << __ffs(domain->ops->pgsize_bitmap); |
1153 | if (s->offset) | 1153 | |
1154 | for_each_sg(sg, s, nents, i) { | ||
1155 | phys_addr_t phys = page_to_phys(sg_page(s)) + s->offset; | ||
1156 | |||
1157 | /* | ||
1158 | * We are mapping on IOMMU page boundaries, so offset within | ||
1159 | * the page must be 0. However, the IOMMU may support pages | ||
1160 | * smaller than PAGE_SIZE, so s->offset may still represent | ||
1161 | * an offset of that boundary within the CPU page. | ||
1162 | */ | ||
1163 | if (!IS_ALIGNED(s->offset, min_pagesz)) | ||
1154 | goto out_err; | 1164 | goto out_err; |
1155 | 1165 | ||
1156 | ret = iommu_map(domain, iova + mapped, phys, s->length, prot); | 1166 | ret = iommu_map(domain, iova + mapped, phys, s->length, prot); |