--- /dev/null
+From fff5d99225107f5f13fe4a9805adc2a1c4b5fb00 Mon Sep 17 00:00:00 2001
+From: Geert Uytterhoeven <geert+renesas@glider.be>
+Date: Fri, 16 Dec 2016 14:28:42 +0100
+Subject: swiotlb: Add swiotlb=noforce debug option
+
+From: Geert Uytterhoeven <geert+renesas@glider.be>
+
+commit fff5d99225107f5f13fe4a9805adc2a1c4b5fb00 upstream.
+
+On architectures like arm64, swiotlb is tied intimately to the core
+architecture DMA support. In addition, ZONE_DMA cannot be disabled.
+
+To aid debugging and catch devices not supporting DMA to memory outside
+the 32-bit address space, add a kernel command line option
+"swiotlb=noforce", which disables the use of bounce buffers.
+If specified, trying to map memory that cannot be used with DMA will
+fail, and a rate-limited warning will be printed.
+
+Note that io_tlb_nslabs is set to 1, which is the minimal supported
+value.
+
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ Documentation/kernel-parameters.txt | 3 ++-
+ include/linux/swiotlb.h | 1 +
+ include/trace/events/swiotlb.h | 3 ++-
+ lib/swiotlb.c | 18 ++++++++++++++++--
+ 4 files changed, 21 insertions(+), 4 deletions(-)
+
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -3998,10 +3998,11 @@ bytes respectively. Such letter suffixes
+ it if 0 is given (See Documentation/cgroup-v1/memory.txt)
+
+ swiotlb= [ARM,IA-64,PPC,MIPS,X86]
+- Format: { <int> | force }
++ Format: { <int> | force | noforce }
+ <int> -- Number of I/O TLB slabs
+ force -- force using of bounce buffers even if they
+ wouldn't be automatically used by the kernel
++ noforce -- Never use bounce buffers (for debugging)
+
+ switches= [HW,M68k]
+
+--- a/include/linux/swiotlb.h
++++ b/include/linux/swiotlb.h
+@@ -12,6 +12,7 @@ struct scatterlist;
+ enum swiotlb_force {
+ SWIOTLB_NORMAL, /* Default - depending on HW DMA mask etc. */
+ SWIOTLB_FORCE, /* swiotlb=force */
++ SWIOTLB_NO_FORCE, /* swiotlb=noforce */
+ };
+
+ extern enum swiotlb_force swiotlb_force;
+--- a/include/trace/events/swiotlb.h
++++ b/include/trace/events/swiotlb.h
+@@ -39,7 +39,8 @@ TRACE_EVENT(swiotlb_bounced,
+ __entry->size,
+ __print_symbolic(__entry->swiotlb_force,
+ { SWIOTLB_NORMAL, "NORMAL" },
+- { SWIOTLB_FORCE, "FORCE" }))
++ { SWIOTLB_FORCE, "FORCE" },
++ { SWIOTLB_NO_FORCE, "NO_FORCE" }))
+ );
+
+ #endif /* _TRACE_SWIOTLB_H */
+--- a/lib/swiotlb.c
++++ b/lib/swiotlb.c
+@@ -106,8 +106,12 @@ setup_io_tlb_npages(char *str)
+ }
+ if (*str == ',')
+ ++str;
+- if (!strcmp(str, "force"))
++ if (!strcmp(str, "force")) {
+ swiotlb_force = SWIOTLB_FORCE;
++ } else if (!strcmp(str, "noforce")) {
++ swiotlb_force = SWIOTLB_NO_FORCE;
++ io_tlb_nslabs = 1;
++ }
+
+ return 0;
+ }
+@@ -541,8 +545,15 @@ static phys_addr_t
+ map_single(struct device *hwdev, phys_addr_t phys, size_t size,
+ enum dma_data_direction dir)
+ {
+- dma_addr_t start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
++ dma_addr_t start_dma_addr;
++
++ if (swiotlb_force == SWIOTLB_NO_FORCE) {
++ dev_warn_ratelimited(hwdev, "Cannot do DMA to address %pa\n",
++ &phys);
++ return SWIOTLB_MAP_ERROR;
++ }
+
++ start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
+ return swiotlb_tbl_map_single(hwdev, start_dma_addr, phys, size, dir);
+ }
+
+@@ -707,6 +718,9 @@ static void
+ swiotlb_full(struct device *dev, size_t size, enum dma_data_direction dir,
+ int do_panic)
+ {
++ if (swiotlb_force == SWIOTLB_NO_FORCE)
++ return;
++
+ /*
+ * Ran out of IOMMU space for this operation. This is very bad.
+ * Unfortunately the drivers cannot handle this operation properly.
--- /dev/null
+From ae7871be189cb41184f1e05742b4a99e2c59774d Mon Sep 17 00:00:00 2001
+From: Geert Uytterhoeven <geert+renesas@glider.be>
+Date: Fri, 16 Dec 2016 14:28:41 +0100
+Subject: swiotlb: Convert swiotlb_force from int to enum
+
+From: Geert Uytterhoeven <geert+renesas@glider.be>
+
+commit ae7871be189cb41184f1e05742b4a99e2c59774d upstream.
+
+Convert the flag swiotlb_force from an int to an enum, to prepare for
+the advent of more possible values.
+
+Suggested-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/mm/dma-mapping.c | 3 ++-
+ arch/arm64/mm/init.c | 3 ++-
+ arch/x86/kernel/pci-swiotlb.c | 2 +-
+ arch/x86/xen/pci-swiotlb-xen.c | 2 +-
+ drivers/xen/swiotlb-xen.c | 4 ++--
+ include/linux/swiotlb.h | 7 ++++++-
+ include/trace/events/swiotlb.h | 16 +++++++++-------
+ lib/swiotlb.c | 8 ++++----
+ 8 files changed, 27 insertions(+), 18 deletions(-)
+
+--- a/arch/arm64/mm/dma-mapping.c
++++ b/arch/arm64/mm/dma-mapping.c
+@@ -524,7 +524,8 @@ EXPORT_SYMBOL(dummy_dma_ops);
+
+ static int __init arm64_dma_init(void)
+ {
+- if (swiotlb_force || max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT))
++ if (swiotlb_force == SWIOTLB_FORCE ||
++ max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT))
+ swiotlb = 1;
+
+ return atomic_pool_init();
+--- a/arch/arm64/mm/init.c
++++ b/arch/arm64/mm/init.c
+@@ -401,7 +401,8 @@ static void __init free_unused_memmap(vo
+ */
+ void __init mem_init(void)
+ {
+- if (swiotlb_force || max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT))
++ if (swiotlb_force == SWIOTLB_FORCE ||
++ max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT))
+ swiotlb_init(1);
+ else
+ swiotlb_force = SWIOTLB_NO_FORCE;
+--- a/arch/x86/kernel/pci-swiotlb.c
++++ b/arch/x86/kernel/pci-swiotlb.c
+@@ -70,7 +70,7 @@ int __init pci_swiotlb_detect_override(v
+ {
+ int use_swiotlb = swiotlb | swiotlb_force;
+
+- if (swiotlb_force)
++ if (swiotlb_force == SWIOTLB_FORCE)
+ swiotlb = 1;
+
+ return use_swiotlb;
+--- a/arch/x86/xen/pci-swiotlb-xen.c
++++ b/arch/x86/xen/pci-swiotlb-xen.c
+@@ -49,7 +49,7 @@ int __init pci_xen_swiotlb_detect(void)
+ * activate this IOMMU. If running as PV privileged, activate it
+ * irregardless.
+ */
+- if ((xen_initial_domain() || swiotlb || swiotlb_force))
++ if (xen_initial_domain() || swiotlb || swiotlb_force == SWIOTLB_FORCE)
+ xen_swiotlb = 1;
+
+ /* If we are running under Xen, we MUST disable the native SWIOTLB.
+--- a/drivers/xen/swiotlb-xen.c
++++ b/drivers/xen/swiotlb-xen.c
+@@ -392,7 +392,7 @@ dma_addr_t xen_swiotlb_map_page(struct d
+ if (dma_capable(dev, dev_addr, size) &&
+ !range_straddles_page_boundary(phys, size) &&
+ !xen_arch_need_swiotlb(dev, phys, dev_addr) &&
+- !swiotlb_force) {
++ (swiotlb_force != SWIOTLB_FORCE)) {
+ /* we are not interested in the dma_addr returned by
+ * xen_dma_map_page, only in the potential cache flushes executed
+ * by the function. */
+@@ -549,7 +549,7 @@ xen_swiotlb_map_sg_attrs(struct device *
+ phys_addr_t paddr = sg_phys(sg);
+ dma_addr_t dev_addr = xen_phys_to_bus(paddr);
+
+- if (swiotlb_force ||
++ if (swiotlb_force == SWIOTLB_FORCE ||
+ xen_arch_need_swiotlb(hwdev, paddr, dev_addr) ||
+ !dma_capable(hwdev, dev_addr, sg->length) ||
+ range_straddles_page_boundary(paddr, sg->length)) {
+--- a/include/linux/swiotlb.h
++++ b/include/linux/swiotlb.h
+@@ -9,7 +9,12 @@ struct device;
+ struct page;
+ struct scatterlist;
+
+-extern int swiotlb_force;
++enum swiotlb_force {
++ SWIOTLB_NORMAL, /* Default - depending on HW DMA mask etc. */
++ SWIOTLB_FORCE, /* swiotlb=force */
++};
++
++extern enum swiotlb_force swiotlb_force;
+
+ /*
+ * Maximum allowable number of contiguous slabs to map,
+--- a/include/trace/events/swiotlb.h
++++ b/include/trace/events/swiotlb.h
+@@ -11,16 +11,16 @@ TRACE_EVENT(swiotlb_bounced,
+ TP_PROTO(struct device *dev,
+ dma_addr_t dev_addr,
+ size_t size,
+- int swiotlb_force),
++ enum swiotlb_force swiotlb_force),
+
+ TP_ARGS(dev, dev_addr, size, swiotlb_force),
+
+ TP_STRUCT__entry(
+- __string( dev_name, dev_name(dev) )
+- __field( u64, dma_mask )
+- __field( dma_addr_t, dev_addr )
+- __field( size_t, size )
+- __field( int, swiotlb_force )
++ __string( dev_name, dev_name(dev) )
++ __field( u64, dma_mask )
++ __field( dma_addr_t, dev_addr )
++ __field( size_t, size )
++ __field( enum swiotlb_force, swiotlb_force )
+ ),
+
+ TP_fast_assign(
+@@ -37,7 +37,9 @@ TRACE_EVENT(swiotlb_bounced,
+ __entry->dma_mask,
+ (unsigned long long)__entry->dev_addr,
+ __entry->size,
+- __entry->swiotlb_force ? "swiotlb_force" : "" )
++ __print_symbolic(__entry->swiotlb_force,
++ { SWIOTLB_NORMAL, "NORMAL" },
++ { SWIOTLB_FORCE, "FORCE" }))
+ );
+
+ #endif /* _TRACE_SWIOTLB_H */
+--- a/lib/swiotlb.c
++++ b/lib/swiotlb.c
+@@ -53,7 +53,7 @@
+ */
+ #define IO_TLB_MIN_SLABS ((1<<20) >> IO_TLB_SHIFT)
+
+-int swiotlb_force;
++enum swiotlb_force swiotlb_force;
+
+ /*
+ * Used to do a quick range check in swiotlb_tbl_unmap_single and
+@@ -107,7 +107,7 @@ setup_io_tlb_npages(char *str)
+ if (*str == ',')
+ ++str;
+ if (!strcmp(str, "force"))
+- swiotlb_force = 1;
++ swiotlb_force = SWIOTLB_FORCE;
+
+ return 0;
+ }
+@@ -749,7 +749,7 @@ dma_addr_t swiotlb_map_page(struct devic
+ * we can safely return the device addr and not worry about bounce
+ * buffering it.
+ */
+- if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
++ if (dma_capable(dev, dev_addr, size) && swiotlb_force != SWIOTLB_FORCE)
+ return dev_addr;
+
+ trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force);
+@@ -888,7 +888,7 @@ swiotlb_map_sg_attrs(struct device *hwde
+ phys_addr_t paddr = sg_phys(sg);
+ dma_addr_t dev_addr = phys_to_dma(hwdev, paddr);
+
+- if (swiotlb_force ||
++ if (swiotlb_force == SWIOTLB_FORCE ||
+ !dma_capable(hwdev, dev_addr, sg->length)) {
+ phys_addr_t map = map_single(hwdev, sg_phys(sg),
+ sg->length, dir);