--- /dev/null
+From 2cbc61a1b1665c84282dbf2b1747ffa0b6248639 Mon Sep 17 00:00:00 2001
+From: David Stevens <stevensd@chromium.org>
+Date: Wed, 29 Sep 2021 11:33:00 +0900
+Subject: iommu/dma: Account for min_align_mask w/swiotlb
+
+From: David Stevens <stevensd@chromium.org>
+
+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 <stevensd@chromium.org>
+Link: https://lore.kernel.org/r/20210929023300.335969-8-stevensd@google.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
--- /dev/null
+From 2e727bffbe93750a13d2414f3ce43de2f21600d2 Mon Sep 17 00:00:00 2001
+From: David Stevens <stevensd@chromium.org>
+Date: Wed, 29 Sep 2021 11:32:58 +0900
+Subject: iommu/dma: Check CONFIG_SWIOTLB more broadly
+
+From: David Stevens <stevensd@chromium.org>
+
+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 <stevensd@chromium.org>
+Reviewed-by: Robin Murphy <robin.murphy@arm.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/r/20210929023300.335969-6-stevensd@google.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
+ }
--- /dev/null
+From 9b49bbc2c4dfd0431bf7ff4e862171189cf94b7e Mon Sep 17 00:00:00 2001
+From: David Stevens <stevensd@chromium.org>
+Date: Wed, 29 Sep 2021 11:32:57 +0900
+Subject: iommu/dma: Fold _swiotlb helpers into callers
+
+From: David Stevens <stevensd@chromium.org>
+
+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 <stevensd@chromium.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/20210929023300.335969-5-stevensd@google.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
--- /dev/null
+From ee9d4097cc145dcaebedf6b113d17c91c21333a0 Mon Sep 17 00:00:00 2001
+From: David Stevens <stevensd@chromium.org>
+Date: Wed, 29 Sep 2021 11:32:56 +0900
+Subject: iommu/dma: Skip extra sync during unmap w/swiotlb
+
+From: David Stevens <stevensd@chromium.org>
+
+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 <stevensd@chromium.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/20210929023300.335969-4-stevensd@google.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.
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
--- /dev/null
+From e81e99bacc9f9347bda7808a949c1ce9fcc2bbf4 Mon Sep 17 00:00:00 2001
+From: David Stevens <stevensd@chromium.org>
+Date: Wed, 29 Sep 2021 11:32:59 +0900
+Subject: swiotlb: Support aligned swiotlb buffers
+
+From: David Stevens <stevensd@chromium.org>
+
+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 <stevensd@chromium.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/r/20210929023300.335969-7-stevensd@google.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Cc: Mario Limonciello <Mario.Limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
+