aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/iommu/iommu.c20
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);