From: Greg Kroah-Hartman Date: Tue, 5 Apr 2022 05:28:05 +0000 (+0200) Subject: 5.15-stable patches X-Git-Tag: v5.17.2~36 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=466a9087fe3027919ffbbafe2defd47339dd9e5c;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: iommu-dma-account-for-min_align_mask-w-swiotlb.patch iommu-dma-check-config_swiotlb-more-broadly.patch iommu-dma-fold-_swiotlb-helpers-into-callers.patch iommu-dma-skip-extra-sync-during-unmap-w-swiotlb.patch swiotlb-support-aligned-swiotlb-buffers.patch --- diff --git a/queue-5.15/iommu-dma-account-for-min_align_mask-w-swiotlb.patch b/queue-5.15/iommu-dma-account-for-min_align_mask-w-swiotlb.patch new file mode 100644 index 00000000000..bdf38722996 --- /dev/null +++ b/queue-5.15/iommu-dma-account-for-min_align_mask-w-swiotlb.patch @@ -0,0 +1,61 @@ +From 2cbc61a1b1665c84282dbf2b1747ffa0b6248639 Mon Sep 17 00:00:00 2001 +From: David Stevens +Date: Wed, 29 Sep 2021 11:33:00 +0900 +Subject: iommu/dma: Account for min_align_mask w/swiotlb + +From: David Stevens + +commit 2cbc61a1b1665c84282dbf2b1747ffa0b6248639 upstream. + +Pass the non-aligned size to __iommu_dma_map when using swiotlb bounce +buffers in iommu_dma_map_page, to account for min_align_mask. + +To deal with granule alignment, __iommu_dma_map maps iova_align(size + +iova_off) bytes starting at phys - iova_off. If iommu_dma_map_page +passes aligned size when using swiotlb, then this becomes +iova_align(iova_align(orig_size) + iova_off). Normally iova_off will be +zero when using swiotlb. However, this is not the case for devices that +set min_align_mask. When iova_off is non-zero, __iommu_dma_map ends up +mapping an extra page at the end of the buffer. Beyond just being a +security issue, the extra page is not cleaned up by __iommu_dma_unmap. +This causes problems when the IOVA is reused, due to collisions in the +iommu driver. Just passing the original size is sufficient, since +__iommu_dma_map will take care of granule alignment. + +Fixes: 1f221a0d0dbf ("swiotlb: respect min_align_mask") +Signed-off-by: David Stevens +Link: https://lore.kernel.org/r/20210929023300.335969-8-stevensd@google.com +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/dma-iommu.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/iommu/dma-iommu.c ++++ b/drivers/iommu/dma-iommu.c +@@ -806,7 +806,6 @@ static dma_addr_t iommu_dma_map_page(str + struct iommu_domain *domain = iommu_get_dma_domain(dev); + struct iommu_dma_cookie *cookie = domain->iova_cookie; + struct iova_domain *iovad = &cookie->iovad; +- size_t aligned_size = size; + dma_addr_t iova, dma_mask = dma_get_mask(dev); + + /* +@@ -815,7 +814,7 @@ static dma_addr_t iommu_dma_map_page(str + */ + if (dev_use_swiotlb(dev) && iova_offset(iovad, phys | size)) { + void *padding_start; +- size_t padding_size; ++ size_t padding_size, aligned_size; + + aligned_size = iova_align(iovad, size); + phys = swiotlb_tbl_map_single(dev, phys, size, aligned_size, +@@ -840,7 +839,7 @@ static dma_addr_t iommu_dma_map_page(str + if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) + arch_sync_dma_for_device(phys, size, dir); + +- iova = __iommu_dma_map(dev, phys, aligned_size, prot, dma_mask); ++ iova = __iommu_dma_map(dev, phys, size, prot, dma_mask); + if (iova == DMA_MAPPING_ERROR && is_swiotlb_buffer(dev, phys)) + swiotlb_tbl_unmap_single(dev, phys, size, dir, attrs); + return iova; diff --git a/queue-5.15/iommu-dma-check-config_swiotlb-more-broadly.patch b/queue-5.15/iommu-dma-check-config_swiotlb-more-broadly.patch new file mode 100644 index 00000000000..e51a8dd31ad --- /dev/null +++ b/queue-5.15/iommu-dma-check-config_swiotlb-more-broadly.patch @@ -0,0 +1,103 @@ +From 2e727bffbe93750a13d2414f3ce43de2f21600d2 Mon Sep 17 00:00:00 2001 +From: David Stevens +Date: Wed, 29 Sep 2021 11:32:58 +0900 +Subject: iommu/dma: Check CONFIG_SWIOTLB more broadly + +From: David Stevens + +commit 2e727bffbe93750a13d2414f3ce43de2f21600d2 upstream. + +Introduce a new dev_use_swiotlb function to guard swiotlb code, instead +of overloading dev_is_untrusted. This allows CONFIG_SWIOTLB to be +checked more broadly, so the swiotlb related code can be removed more +aggressively. + +Signed-off-by: David Stevens +Reviewed-by: Robin Murphy +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20210929023300.335969-6-stevensd@google.com +Signed-off-by: Joerg Roedel +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/dma-iommu.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +--- a/drivers/iommu/dma-iommu.c ++++ b/drivers/iommu/dma-iommu.c +@@ -317,6 +317,11 @@ static bool dev_is_untrusted(struct devi + return dev_is_pci(dev) && to_pci_dev(dev)->untrusted; + } + ++static bool dev_use_swiotlb(struct device *dev) ++{ ++ return IS_ENABLED(CONFIG_SWIOTLB) && dev_is_untrusted(dev); ++} ++ + /* sysfs updates are serialised by the mutex of the group owning @domain */ + int iommu_dma_init_fq(struct iommu_domain *domain) + { +@@ -731,7 +736,7 @@ static void iommu_dma_sync_single_for_cp + { + phys_addr_t phys; + +- if (dev_is_dma_coherent(dev) && !dev_is_untrusted(dev)) ++ if (dev_is_dma_coherent(dev) && !dev_use_swiotlb(dev)) + return; + + phys = iommu_iova_to_phys(iommu_get_dma_domain(dev), dma_handle); +@@ -747,7 +752,7 @@ static void iommu_dma_sync_single_for_de + { + phys_addr_t phys; + +- if (dev_is_dma_coherent(dev) && !dev_is_untrusted(dev)) ++ if (dev_is_dma_coherent(dev) && !dev_use_swiotlb(dev)) + return; + + phys = iommu_iova_to_phys(iommu_get_dma_domain(dev), dma_handle); +@@ -765,7 +770,7 @@ static void iommu_dma_sync_sg_for_cpu(st + struct scatterlist *sg; + int i; + +- if (dev_is_untrusted(dev)) ++ if (dev_use_swiotlb(dev)) + for_each_sg(sgl, sg, nelems, i) + iommu_dma_sync_single_for_cpu(dev, sg_dma_address(sg), + sg->length, dir); +@@ -781,7 +786,7 @@ static void iommu_dma_sync_sg_for_device + struct scatterlist *sg; + int i; + +- if (dev_is_untrusted(dev)) ++ if (dev_use_swiotlb(dev)) + for_each_sg(sgl, sg, nelems, i) + iommu_dma_sync_single_for_device(dev, + sg_dma_address(sg), +@@ -808,8 +813,7 @@ static dma_addr_t iommu_dma_map_page(str + * If both the physical buffer start address and size are + * page aligned, we don't need to use a bounce page. + */ +- if (IS_ENABLED(CONFIG_SWIOTLB) && dev_is_untrusted(dev) && +- iova_offset(iovad, phys | size)) { ++ if (dev_use_swiotlb(dev) && iova_offset(iovad, phys | size)) { + void *padding_start; + size_t padding_size; + +@@ -995,7 +999,7 @@ static int iommu_dma_map_sg(struct devic + goto out; + } + +- if (dev_is_untrusted(dev)) ++ if (dev_use_swiotlb(dev)) + return iommu_dma_map_sg_swiotlb(dev, sg, nents, dir, attrs); + + if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) +@@ -1073,7 +1077,7 @@ static void iommu_dma_unmap_sg(struct de + struct scatterlist *tmp; + int i; + +- if (dev_is_untrusted(dev)) { ++ if (dev_use_swiotlb(dev)) { + iommu_dma_unmap_sg_swiotlb(dev, sg, nents, dir, attrs); + return; + } diff --git a/queue-5.15/iommu-dma-fold-_swiotlb-helpers-into-callers.patch b/queue-5.15/iommu-dma-fold-_swiotlb-helpers-into-callers.patch new file mode 100644 index 00000000000..95775952e36 --- /dev/null +++ b/queue-5.15/iommu-dma-fold-_swiotlb-helpers-into-callers.patch @@ -0,0 +1,202 @@ +From 9b49bbc2c4dfd0431bf7ff4e862171189cf94b7e Mon Sep 17 00:00:00 2001 +From: David Stevens +Date: Wed, 29 Sep 2021 11:32:57 +0900 +Subject: iommu/dma: Fold _swiotlb helpers into callers + +From: David Stevens + +commit 9b49bbc2c4dfd0431bf7ff4e862171189cf94b7e upstream. + +Fold the _swiotlb helper functions into the respective _page functions, +since recent fixes have moved all logic from the _page functions to the +_swiotlb functions. + +Signed-off-by: David Stevens +Reviewed-by: Christoph Hellwig +Reviewed-by: Robin Murphy +Link: https://lore.kernel.org/r/20210929023300.335969-5-stevensd@google.com +Signed-off-by: Joerg Roedel +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/dma-iommu.c | 135 ++++++++++++++++++++-------------------------- + 1 file changed, 59 insertions(+), 76 deletions(-) + +--- a/drivers/iommu/dma-iommu.c ++++ b/drivers/iommu/dma-iommu.c +@@ -510,26 +510,6 @@ static void __iommu_dma_unmap(struct dev + iommu_dma_free_iova(cookie, dma_addr, size, &iotlb_gather); + } + +-static void __iommu_dma_unmap_swiotlb(struct device *dev, dma_addr_t dma_addr, +- size_t size, enum dma_data_direction dir, +- unsigned long attrs) +-{ +- struct iommu_domain *domain = iommu_get_dma_domain(dev); +- phys_addr_t phys; +- +- phys = iommu_iova_to_phys(domain, dma_addr); +- if (WARN_ON(!phys)) +- return; +- +- if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) && !dev_is_dma_coherent(dev)) +- arch_sync_dma_for_cpu(phys, size, dir); +- +- __iommu_dma_unmap(dev, dma_addr, size); +- +- if (unlikely(is_swiotlb_buffer(dev, phys))) +- swiotlb_tbl_unmap_single(dev, phys, size, dir, attrs); +-} +- + static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys, + size_t size, int prot, u64 dma_mask) + { +@@ -556,55 +536,6 @@ static dma_addr_t __iommu_dma_map(struct + return iova + iova_off; + } + +-static dma_addr_t __iommu_dma_map_swiotlb(struct device *dev, phys_addr_t phys, +- size_t org_size, dma_addr_t dma_mask, bool coherent, +- enum dma_data_direction dir, unsigned long attrs) +-{ +- int prot = dma_info_to_prot(dir, coherent, attrs); +- struct iommu_domain *domain = iommu_get_dma_domain(dev); +- struct iommu_dma_cookie *cookie = domain->iova_cookie; +- struct iova_domain *iovad = &cookie->iovad; +- size_t aligned_size = org_size; +- void *padding_start; +- size_t padding_size; +- dma_addr_t iova; +- +- /* +- * If both the physical buffer start address and size are +- * page aligned, we don't need to use a bounce page. +- */ +- if (IS_ENABLED(CONFIG_SWIOTLB) && dev_is_untrusted(dev) && +- iova_offset(iovad, phys | org_size)) { +- aligned_size = iova_align(iovad, org_size); +- phys = swiotlb_tbl_map_single(dev, phys, org_size, +- aligned_size, dir, attrs); +- +- if (phys == DMA_MAPPING_ERROR) +- return DMA_MAPPING_ERROR; +- +- /* Cleanup the padding area. */ +- padding_start = phys_to_virt(phys); +- padding_size = aligned_size; +- +- if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) && +- (dir == DMA_TO_DEVICE || +- dir == DMA_BIDIRECTIONAL)) { +- padding_start += org_size; +- padding_size -= org_size; +- } +- +- memset(padding_start, 0, padding_size); +- } +- +- if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) +- arch_sync_dma_for_device(phys, org_size, dir); +- +- iova = __iommu_dma_map(dev, phys, aligned_size, prot, dma_mask); +- if (iova == DMA_MAPPING_ERROR && is_swiotlb_buffer(dev, phys)) +- swiotlb_tbl_unmap_single(dev, phys, org_size, dir, attrs); +- return iova; +-} +- + static void __iommu_dma_free_pages(struct page **pages, int count) + { + while (count--) +@@ -866,15 +797,68 @@ static dma_addr_t iommu_dma_map_page(str + { + phys_addr_t phys = page_to_phys(page) + offset; + bool coherent = dev_is_dma_coherent(dev); ++ int prot = dma_info_to_prot(dir, coherent, attrs); ++ struct iommu_domain *domain = iommu_get_dma_domain(dev); ++ struct iommu_dma_cookie *cookie = domain->iova_cookie; ++ struct iova_domain *iovad = &cookie->iovad; ++ size_t aligned_size = size; ++ dma_addr_t iova, dma_mask = dma_get_mask(dev); ++ ++ /* ++ * If both the physical buffer start address and size are ++ * page aligned, we don't need to use a bounce page. ++ */ ++ if (IS_ENABLED(CONFIG_SWIOTLB) && dev_is_untrusted(dev) && ++ iova_offset(iovad, phys | size)) { ++ void *padding_start; ++ size_t padding_size; ++ ++ aligned_size = iova_align(iovad, size); ++ phys = swiotlb_tbl_map_single(dev, phys, size, ++ aligned_size, dir, attrs); ++ ++ if (phys == DMA_MAPPING_ERROR) ++ return DMA_MAPPING_ERROR; + +- return __iommu_dma_map_swiotlb(dev, phys, size, dma_get_mask(dev), +- coherent, dir, attrs); ++ /* Cleanup the padding area. */ ++ padding_start = phys_to_virt(phys); ++ padding_size = aligned_size; ++ ++ if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) && ++ (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)) { ++ padding_start += size; ++ padding_size -= size; ++ } ++ ++ memset(padding_start, 0, padding_size); ++ } ++ ++ if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) ++ arch_sync_dma_for_device(phys, size, dir); ++ ++ iova = __iommu_dma_map(dev, phys, aligned_size, prot, dma_mask); ++ if (iova == DMA_MAPPING_ERROR && is_swiotlb_buffer(dev, phys)) ++ swiotlb_tbl_unmap_single(dev, phys, size, dir, attrs); ++ return iova; + } + + static void iommu_dma_unmap_page(struct device *dev, dma_addr_t dma_handle, + size_t size, enum dma_data_direction dir, unsigned long attrs) + { +- __iommu_dma_unmap_swiotlb(dev, dma_handle, size, dir, attrs); ++ struct iommu_domain *domain = iommu_get_dma_domain(dev); ++ phys_addr_t phys; ++ ++ phys = iommu_iova_to_phys(domain, dma_handle); ++ if (WARN_ON(!phys)) ++ return; ++ ++ if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) && !dev_is_dma_coherent(dev)) ++ arch_sync_dma_for_cpu(phys, size, dir); ++ ++ __iommu_dma_unmap(dev, dma_handle, size); ++ ++ if (unlikely(is_swiotlb_buffer(dev, phys))) ++ swiotlb_tbl_unmap_single(dev, phys, size, dir, attrs); + } + + /* +@@ -959,7 +943,7 @@ static void iommu_dma_unmap_sg_swiotlb(s + int i; + + for_each_sg(sg, s, nents, i) +- __iommu_dma_unmap_swiotlb(dev, sg_dma_address(s), ++ iommu_dma_unmap_page(dev, sg_dma_address(s), + sg_dma_len(s), dir, attrs); + } + +@@ -970,9 +954,8 @@ static int iommu_dma_map_sg_swiotlb(stru + int i; + + for_each_sg(sg, s, nents, i) { +- sg_dma_address(s) = __iommu_dma_map_swiotlb(dev, sg_phys(s), +- s->length, dma_get_mask(dev), +- dev_is_dma_coherent(dev), dir, attrs); ++ sg_dma_address(s) = iommu_dma_map_page(dev, sg_page(s), ++ s->offset, s->length, dir, attrs); + if (sg_dma_address(s) == DMA_MAPPING_ERROR) + goto out_unmap; + sg_dma_len(s) = s->length; diff --git a/queue-5.15/iommu-dma-skip-extra-sync-during-unmap-w-swiotlb.patch b/queue-5.15/iommu-dma-skip-extra-sync-during-unmap-w-swiotlb.patch new file mode 100644 index 00000000000..f8f1e986d0c --- /dev/null +++ b/queue-5.15/iommu-dma-skip-extra-sync-during-unmap-w-swiotlb.patch @@ -0,0 +1,65 @@ +From ee9d4097cc145dcaebedf6b113d17c91c21333a0 Mon Sep 17 00:00:00 2001 +From: David Stevens +Date: Wed, 29 Sep 2021 11:32:56 +0900 +Subject: iommu/dma: Skip extra sync during unmap w/swiotlb + +From: David Stevens + +commit ee9d4097cc145dcaebedf6b113d17c91c21333a0 upstream. + +Calling the iommu_dma_sync_*_for_cpu functions during unmap can cause +two copies out of the swiotlb buffer. Do the arch sync directly in +__iommu_dma_unmap_swiotlb instead to avoid this. This makes the call to +iommu_dma_sync_sg_for_cpu for untrusted devices in iommu_dma_unmap_sg no +longer necessary, so move that invocation later in the function. + +Signed-off-by: David Stevens +Reviewed-by: Christoph Hellwig +Reviewed-by: Robin Murphy +Link: https://lore.kernel.org/r/20210929023300.335969-4-stevensd@google.com +Signed-off-by: Joerg Roedel +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/dma-iommu.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/drivers/iommu/dma-iommu.c ++++ b/drivers/iommu/dma-iommu.c +@@ -521,6 +521,9 @@ static void __iommu_dma_unmap_swiotlb(st + if (WARN_ON(!phys)) + return; + ++ if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) && !dev_is_dma_coherent(dev)) ++ arch_sync_dma_for_cpu(phys, size, dir); ++ + __iommu_dma_unmap(dev, dma_addr, size); + + if (unlikely(is_swiotlb_buffer(dev, phys))) +@@ -871,8 +874,6 @@ static dma_addr_t iommu_dma_map_page(str + static void iommu_dma_unmap_page(struct device *dev, dma_addr_t dma_handle, + size_t size, enum dma_data_direction dir, unsigned long attrs) + { +- if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) +- iommu_dma_sync_single_for_cpu(dev, dma_handle, size, dir); + __iommu_dma_unmap_swiotlb(dev, dma_handle, size, dir, attrs); + } + +@@ -1089,14 +1090,14 @@ static void iommu_dma_unmap_sg(struct de + struct scatterlist *tmp; + int i; + +- if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) +- iommu_dma_sync_sg_for_cpu(dev, sg, nents, dir); +- + if (dev_is_untrusted(dev)) { + iommu_dma_unmap_sg_swiotlb(dev, sg, nents, dir, attrs); + return; + } + ++ if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) ++ iommu_dma_sync_sg_for_cpu(dev, sg, nents, dir); ++ + /* + * The scatterlist segments are mapped into a single + * contiguous IOVA allocation, so this is incredibly easy. diff --git a/queue-5.15/series b/queue-5.15/series index 8ed0ec614da..761dbb74d8f 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -902,3 +902,8 @@ n64cart-convert-bi_disk-to-bi_bdev-bd_disk-fix-build.patch mmc-rtsx-let-mmc-core-handle-runtime-pm.patch mmc-rtsx-fix-build-errors-warnings-for-unused-variable.patch kvm-x86-mmu-do-compare-and-exchange-of-gpte-via-the-user-address.patch +iommu-dma-skip-extra-sync-during-unmap-w-swiotlb.patch +iommu-dma-fold-_swiotlb-helpers-into-callers.patch +iommu-dma-check-config_swiotlb-more-broadly.patch +swiotlb-support-aligned-swiotlb-buffers.patch +iommu-dma-account-for-min_align_mask-w-swiotlb.patch diff --git a/queue-5.15/swiotlb-support-aligned-swiotlb-buffers.patch b/queue-5.15/swiotlb-support-aligned-swiotlb-buffers.patch new file mode 100644 index 00000000000..073a0d29491 --- /dev/null +++ b/queue-5.15/swiotlb-support-aligned-swiotlb-buffers.patch @@ -0,0 +1,122 @@ +From e81e99bacc9f9347bda7808a949c1ce9fcc2bbf4 Mon Sep 17 00:00:00 2001 +From: David Stevens +Date: Wed, 29 Sep 2021 11:32:59 +0900 +Subject: swiotlb: Support aligned swiotlb buffers + +From: David Stevens + +commit e81e99bacc9f9347bda7808a949c1ce9fcc2bbf4 upstream. + +Add an argument to swiotlb_tbl_map_single that specifies the desired +alignment of the allocated buffer. This is used by dma-iommu to ensure +the buffer is aligned to the iova granule size when using swiotlb with +untrusted sub-granule mappings. This addresses an issue where adjacent +slots could be exposed to the untrusted device if IO_TLB_SIZE < iova +granule < PAGE_SIZE. + +Signed-off-by: David Stevens +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20210929023300.335969-7-stevensd@google.com +Signed-off-by: Joerg Roedel +Cc: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/dma-iommu.c | 4 ++-- + drivers/xen/swiotlb-xen.c | 2 +- + include/linux/swiotlb.h | 3 ++- + kernel/dma/swiotlb.c | 13 ++++++++----- + 4 files changed, 13 insertions(+), 9 deletions(-) + +--- a/drivers/iommu/dma-iommu.c ++++ b/drivers/iommu/dma-iommu.c +@@ -818,8 +818,8 @@ static dma_addr_t iommu_dma_map_page(str + size_t padding_size; + + aligned_size = iova_align(iovad, size); +- phys = swiotlb_tbl_map_single(dev, phys, size, +- aligned_size, dir, attrs); ++ phys = swiotlb_tbl_map_single(dev, phys, size, aligned_size, ++ iova_mask(iovad), dir, attrs); + + if (phys == DMA_MAPPING_ERROR) + return DMA_MAPPING_ERROR; +--- a/drivers/xen/swiotlb-xen.c ++++ b/drivers/xen/swiotlb-xen.c +@@ -380,7 +380,7 @@ static dma_addr_t xen_swiotlb_map_page(s + */ + trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force); + +- map = swiotlb_tbl_map_single(dev, phys, size, size, dir, attrs); ++ map = swiotlb_tbl_map_single(dev, phys, size, size, 0, dir, attrs); + if (map == (phys_addr_t)DMA_MAPPING_ERROR) + return DMA_MAPPING_ERROR; + +--- a/include/linux/swiotlb.h ++++ b/include/linux/swiotlb.h +@@ -45,7 +45,8 @@ extern void __init swiotlb_update_mem_at + + phys_addr_t swiotlb_tbl_map_single(struct device *hwdev, phys_addr_t phys, + size_t mapping_size, size_t alloc_size, +- enum dma_data_direction dir, unsigned long attrs); ++ unsigned int alloc_aligned_mask, enum dma_data_direction dir, ++ unsigned long attrs); + + extern void swiotlb_tbl_unmap_single(struct device *hwdev, + phys_addr_t tlb_addr, +--- a/kernel/dma/swiotlb.c ++++ b/kernel/dma/swiotlb.c +@@ -459,7 +459,7 @@ static unsigned int wrap_index(struct io + * allocate a buffer from that IO TLB pool. + */ + static int swiotlb_find_slots(struct device *dev, phys_addr_t orig_addr, +- size_t alloc_size) ++ size_t alloc_size, unsigned int alloc_align_mask) + { + struct io_tlb_mem *mem = dev->dma_io_tlb_mem; + unsigned long boundary_mask = dma_get_seg_boundary(dev); +@@ -483,6 +483,7 @@ static int swiotlb_find_slots(struct dev + stride = (iotlb_align_mask >> IO_TLB_SHIFT) + 1; + if (alloc_size >= PAGE_SIZE) + stride = max(stride, stride << (PAGE_SHIFT - IO_TLB_SHIFT)); ++ stride = max(stride, (alloc_align_mask >> IO_TLB_SHIFT) + 1); + + spin_lock_irqsave(&mem->lock, flags); + if (unlikely(nslots > mem->nslabs - mem->used)) +@@ -541,7 +542,8 @@ found: + + phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr, + size_t mapping_size, size_t alloc_size, +- enum dma_data_direction dir, unsigned long attrs) ++ unsigned int alloc_align_mask, enum dma_data_direction dir, ++ unsigned long attrs) + { + struct io_tlb_mem *mem = dev->dma_io_tlb_mem; + unsigned int offset = swiotlb_align_offset(dev, orig_addr); +@@ -561,7 +563,8 @@ phys_addr_t swiotlb_tbl_map_single(struc + return (phys_addr_t)DMA_MAPPING_ERROR; + } + +- index = swiotlb_find_slots(dev, orig_addr, alloc_size + offset); ++ index = swiotlb_find_slots(dev, orig_addr, ++ alloc_size + offset, alloc_align_mask); + if (index == -1) { + if (!(attrs & DMA_ATTR_NO_WARN)) + dev_warn_ratelimited(dev, +@@ -680,7 +683,7 @@ dma_addr_t swiotlb_map(struct device *de + trace_swiotlb_bounced(dev, phys_to_dma(dev, paddr), size, + swiotlb_force); + +- swiotlb_addr = swiotlb_tbl_map_single(dev, paddr, size, size, dir, ++ swiotlb_addr = swiotlb_tbl_map_single(dev, paddr, size, size, 0, dir, + attrs); + if (swiotlb_addr == (phys_addr_t)DMA_MAPPING_ERROR) + return DMA_MAPPING_ERROR; +@@ -764,7 +767,7 @@ struct page *swiotlb_alloc(struct device + if (!mem) + return NULL; + +- index = swiotlb_find_slots(dev, 0, size); ++ index = swiotlb_find_slots(dev, 0, size, 0); + if (index == -1) + return NULL; +