[PATCH v2] dma-debug: Kconfig for PREALLOC_DMA_DEBUG_ENTRIES

2018-11-30 Thread Qian Cai
The amount of DMA mappings from Hisilicon HNS ethernet devices is huge,
so it could trigger "DMA-API: debugging out of memory - disabling".

hnae_get_handle [1]
  hnae_init_queue
hnae_init_ring
  hnae_alloc_buffers [2]
debug_dma_map_page
  dma_entry_alloc

[1] for (i = 0; i < handle->q_num; i++)
[2] for (i = 0; i < ring->desc_num; i++)

Also, "#define HNS_DSAF_MAX_DESC_CNT 1024"

On this Huawei TaiShan 2280 aarch64 server, it has reached the limit
already,

4 (NICs) x 16 (queues) x 1024 (port descption numbers) = 65536

Added a Kconfig entry for PREALLOC_DMA_DEBUG_ENTRIES, so make it easier
for users to deal with special cases like this.

Signed-off-by: Qian Cai 
---

Changes since v1:
* Increased the default value if has HNS_ENET suggested by Robin.

 kernel/dma/debug.c |  9 ++---
 lib/Kconfig.debug  | 10 ++
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/kernel/dma/debug.c b/kernel/dma/debug.c
index 231ca4628062..3752fb23f72f 100644
--- a/kernel/dma/debug.c
+++ b/kernel/dma/debug.c
@@ -41,11 +41,6 @@
 #define HASH_FN_SHIFT   13
 #define HASH_FN_MASK(HASH_SIZE - 1)
 
-/* allow architectures to override this if absolutely required */
-#ifndef PREALLOC_DMA_DEBUG_ENTRIES
-#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
-#endif
-
 enum {
dma_debug_single,
dma_debug_page,
@@ -132,7 +127,7 @@ static u32 min_free_entries;
 static u32 nr_total_entries;
 
 /* number of preallocated entries requested by kernel cmdline */
-static u32 nr_prealloc_entries = PREALLOC_DMA_DEBUG_ENTRIES;
+static u32 nr_prealloc_entries = CONFIG_PREALLOC_DMA_DEBUG_ENTRIES;
 
 /* debugfs dentry's for the stuff above */
 static struct dentry *dma_debug_dent__read_mostly;
@@ -1063,7 +1058,7 @@ static __init int dma_debug_entries_cmdline(char *str)
if (!str)
return -EINVAL;
if (!get_option(&str, &nr_prealloc_entries))
-   nr_prealloc_entries = PREALLOC_DMA_DEBUG_ENTRIES;
+   nr_prealloc_entries = CONFIG_PREALLOC_DMA_DEBUG_ENTRIES;
return 0;
 }
 
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 1af29b8224fd..9f85a7a13647 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1659,6 +1659,16 @@ config DMA_API_DEBUG
 
  If unsure, say N.
 
+config PREALLOC_DMA_DEBUG_ENTRIES
+   int "Preallocated DMA-API debugging entries"
+   depends on DMA_API_DEBUG
+   default 131072 if HNS_ENET
+   default 65536
+   help
+ The number of preallocated entries for DMA-API debugging code. One
+ entry is required per DMA-API allocation. Increase this if the DMA-API
+ debugging code disables itself because the default is too low.
+
 config DMA_API_DEBUG_SG
bool "Debug DMA scatter-gather usage"
default y
-- 
2.17.2 (Apple Git-113)

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: remove the ->mapping_error method from dma_map_ops V3

2018-11-30 Thread Linus Torvalds
On Fri, Nov 30, 2018 at 5:23 AM Christoph Hellwig  wrote:
>
> Error reporting for the dma_map_single and dma_map_page operations is
> currently a mess. [..]

I don't see anything objectionable there, but it's not like I checked
any of the context of the patches. For all I know there are odd corner
cases where some zero vs DMA_MAPPING_ERROR confusion lurks, but I
guess we'll find out..

So you can add my acked-by, fwiw.

Linus
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH] dma-debug: Kconfig for PREALLOC_DMA_DEBUG_ENTRIES

2018-11-30 Thread Robin Murphy

On 30/11/2018 17:54, Qian Cai wrote:

The amount of DMA mappings from Hisilicon HNS ethernet devices is huge,
so it could trigger "DMA-API: debugging out of memory - disabling".

hnae_get_handle [1]
   hnae_init_queue
 hnae_init_ring
   hnae_alloc_buffers [2]
 debug_dma_map_page
   dma_entry_alloc

[1] for (i = 0; i < handle->q_num; i++)
[2] for (i = 0; i < ring->desc_num; i++)

On this Huawei TaiShan 2280 aarch64 server, it has reached the limit
already,

4 (ports) x 16 (handles) x 1024 (rings) = 65536

Added a Kconfig entry for PREALLOC_DMA_DEBUG_ENTRIES, so make it easier
for users to deal with special cases like this.

Signed-off-by: Qian Cai 
---
  kernel/dma/debug.c | 9 ++---
  lib/Kconfig.debug  | 9 +
  2 files changed, 11 insertions(+), 7 deletions(-)


Oh, right, the arch overrides actually got cleaned up already. I'd 
forgotten that...



diff --git a/kernel/dma/debug.c b/kernel/dma/debug.c
index 231ca4628062..3752fb23f72f 100644
--- a/kernel/dma/debug.c
+++ b/kernel/dma/debug.c
@@ -41,11 +41,6 @@
  #define HASH_FN_SHIFT   13
  #define HASH_FN_MASK(HASH_SIZE - 1)
  
-/* allow architectures to override this if absolutely required */

-#ifndef PREALLOC_DMA_DEBUG_ENTRIES
-#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
-#endif
-
  enum {
dma_debug_single,
dma_debug_page,
@@ -132,7 +127,7 @@ static u32 min_free_entries;
  static u32 nr_total_entries;
  
  /* number of preallocated entries requested by kernel cmdline */

-static u32 nr_prealloc_entries = PREALLOC_DMA_DEBUG_ENTRIES;
+static u32 nr_prealloc_entries = CONFIG_PREALLOC_DMA_DEBUG_ENTRIES;
  
  /* debugfs dentry's for the stuff above */

  static struct dentry *dma_debug_dent__read_mostly;
@@ -1063,7 +1058,7 @@ static __init int dma_debug_entries_cmdline(char *str)
if (!str)
return -EINVAL;
if (!get_option(&str, &nr_prealloc_entries))
-   nr_prealloc_entries = PREALLOC_DMA_DEBUG_ENTRIES;
+   nr_prealloc_entries = CONFIG_PREALLOC_DMA_DEBUG_ENTRIES;
return 0;
  }
  
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug

index 1af29b8224fd..2c281edcb5ad 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1659,6 +1659,15 @@ config DMA_API_DEBUG
  
  	  If unsure, say N.
  
+config PREALLOC_DMA_DEBUG_ENTRIES

+   int "Preallocated DMA-API debugging entries"
+   depends on DMA_API_DEBUG
+   default 65536


I was assuming the point was to also add something like

default 131072 if HNS_ENET

so that DMA debug doesn't require too much thought from the user. If 
they still have to notice the overflow message and empirically figure 
out a value that does work, rebuilding the kernel each time is far less 
convenient than simply adding "dma_debug_entries=..." to their kernel 
command line and rebooting, which they can do today. If they do already 
know up-front that the default will need overriding and what the 
appropriate value is, then the command line still seems seems just as 
convenient.


Robin.


+   help
+ The number of preallocated entries for DMA-API debugging code. One
+ entry is required per DMA-API allocation. Increase this if the DMA-API
+ debugging code disables itself because the default is too low.
+
  config DMA_API_DEBUG_SG
bool "Debug DMA scatter-gather usage"
default y


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 6/9] dma-remap: support DMA_ATTR_NO_KERNEL_MAPPING

2018-11-30 Thread Robin Murphy

On 05/11/2018 12:19, Christoph Hellwig wrote:

Do not waste vmalloc space on allocations that do not require a mapping
into the kernel address space.

Signed-off-by: Christoph Hellwig 
---
  kernel/dma/remap.c | 11 +--
  1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/kernel/dma/remap.c b/kernel/dma/remap.c
index 8f1fca34b894..10a545126b0b 100644
--- a/kernel/dma/remap.c
+++ b/kernel/dma/remap.c
@@ -200,7 +200,8 @@ void *arch_dma_alloc(struct device *dev, size_t size, 
dma_addr_t *dma_handle,
  
  	size = PAGE_ALIGN(size);
  
-	if (!gfpflags_allow_blocking(flags)) {

+   if (!gfpflags_allow_blocking(flags) &&
+   !(attrs & DMA_ATTR_NO_KERNEL_MAPPING)) {
ret = dma_alloc_from_pool(size, &page, flags);
if (!ret)
return NULL;
@@ -215,6 +216,9 @@ void *arch_dma_alloc(struct device *dev, size_t size, 
dma_addr_t *dma_handle,
/* remove any dirty cache lines on the kernel alias */
arch_dma_prep_coherent(page, size);
  
+	if (attrs & DMA_ATTR_NO_KERNEL_MAPPING)

+   return page; /* opaqueue cookie */


Best to preempt the inevitable patch fixing that typo in 3 months' time. 
Otherwise,


Reviewed-by: Robin Murphy 


+
/* create a coherent mapping */
ret = dma_common_contiguous_remap(page, size, VM_USERMAP,
arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs),
@@ -227,7 +231,10 @@ void *arch_dma_alloc(struct device *dev, size_t size, 
dma_addr_t *dma_handle,
  void arch_dma_free(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle, unsigned long attrs)
  {
-   if (!dma_free_from_pool(vaddr, PAGE_ALIGN(size))) {
+   if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) {
+   /* vaddr is a struct page cookie, not a kernel address */
+   __dma_direct_free_pages(dev, size, vaddr);
+   } else if (!dma_free_from_pool(vaddr, PAGE_ALIGN(size))) {
phys_addr_t phys = dma_to_phys(dev, dma_handle);
struct page *page = pfn_to_page(__phys_to_pfn(phys));
  


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 4/9] dma-mapping: move the arm64 ncoherent alloc/free support to common code

2018-11-30 Thread Robin Murphy

On 05/11/2018 12:19, Christoph Hellwig wrote:

The arm64 codebase to implement coherent dma allocation for architectures
with non-coherent DMA is a good start for a generic implementation, given
that is uses the generic remap helpers, provides the atomic pool for
allocations that can't sleep and still is realtively simple and well
tested.  Move it to kernel/dma and allow architectures to opt into it
using a config symbol.  Architectures just need to provide a new
arch_dma_prep_coherent helper to writeback an invalidate the caches
for any memory that gets remapped for uncached access.


It's a bit yuck that we now end up with arch_* hooks being a mix of arch 
code and not-actually-arch-code, but I guess there's some hope of coming 
back and streamlining things in future once all the big moves are done.


I can't really be bothered to nitpick the typos above and the slight 
inconsistencies in some of the cosmetic code changes, but one worthwhile 
thing stands out...



Signed-off-by: Christoph Hellwig 
---
  arch/arm64/Kconfig  |   2 +-
  arch/arm64/mm/dma-mapping.c | 184 ++--
  include/linux/dma-mapping.h |   5 +
  include/linux/dma-noncoherent.h |   2 +
  kernel/dma/Kconfig  |   6 ++
  kernel/dma/remap.c  | 158 ++-
  6 files changed, 181 insertions(+), 176 deletions(-)


[...]


+void *dma_alloc_from_pool(size_t size, struct page **ret_page, gfp_t flags)
+{
+   unsigned long val;
+   void *ptr = NULL;
+
+   if (!atomic_pool) {
+   WARN(1, "coherent pool not initialised!\n");
+   return NULL;
+   }
+
+   val = gen_pool_alloc(atomic_pool, size);
+   if (val) {
+   phys_addr_t phys = gen_pool_virt_to_phys(atomic_pool, val);
+
+   *ret_page = phys_to_page(phys);


Looks like phys_to_page() isn't particularly portable, so we probably 
want an explicit pfn_to_page(__phys_to_pfn(phys)) here. Otherwise, the 
fundamental refactoring looks OK.


Reviewed-by: Robin Murphy 

[ In fact, looking at phys_to_page(), microblaze, riscv, unicore and 
csky (by the end of this series if it's fixed here) don't need to define 
it at all; s390 defines it for the sake of a single call in a single 
driver; it's used in two other places in arm-related drivers but at 
least one of those is clearly wrong. All in all it's quite the sorry mess. ]



+   ptr = (void *)val;
+   memset(ptr, 0, size);
+   }
+
+   return ptr;
+}
+
+bool dma_free_from_pool(void *start, size_t size)
+{
+   if (!dma_in_atomic_pool(start, size))
+   return false;
+   gen_pool_free(atomic_pool, (unsigned long)start, size);
+   return true;
+}
+
+void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
+   gfp_t flags, unsigned long attrs)
+{
+   struct page *page = NULL;
+   void *ret, *kaddr;
+
+   size = PAGE_ALIGN(size);
+
+   if (!gfpflags_allow_blocking(flags)) {
+   ret = dma_alloc_from_pool(size, &page, flags);
+   if (!ret)
+   return NULL;
+   *dma_handle = phys_to_dma(dev, page_to_phys(page));
+   return ret;
+   }
+
+   kaddr = dma_direct_alloc_pages(dev, size, dma_handle, flags, attrs);
+   if (!kaddr)
+   return NULL;
+   page = virt_to_page(kaddr);
+
+   /* remove any dirty cache lines on the kernel alias */
+   arch_dma_prep_coherent(page, size);
+
+   /* create a coherent mapping */
+   ret = dma_common_contiguous_remap(page, size, VM_USERMAP,
+   arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs),
+   __builtin_return_address(0));
+   if (!ret)
+   dma_direct_free_pages(dev, size, kaddr, *dma_handle, attrs);
+   return ret;
+}
+
+void arch_dma_free(struct device *dev, size_t size, void *vaddr,
+   dma_addr_t dma_handle, unsigned long attrs)
+{
+   if (!dma_free_from_pool(vaddr, PAGE_ALIGN(size))) {
+   void *kaddr = phys_to_virt(dma_to_phys(dev, dma_handle));
+
+   vunmap(vaddr);
+   dma_direct_free_pages(dev, size, kaddr, dma_handle, attrs);
+   }
+}
+
+long arch_dma_coherent_to_pfn(struct device *dev, void *cpu_addr,
+   dma_addr_t dma_addr)
+{
+   return __phys_to_pfn(dma_to_phys(dev, dma_addr));
+}
+#endif /* CONFIG_DMA_DIRECT_REMAP */


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 3/9] dma-mapping: move the remap helpers to a separate file

2018-11-30 Thread Robin Murphy

On 05/11/2018 12:19, Christoph Hellwig wrote:

The dma remap code only really makes sense for not cache coherent
architectures,


And coherent ones with highmem, presumably? That can at least be the 
case on 32-bit Arm, where coherent LPAE systems do exist (e.g. Calxeda 
Midway).



and currently is only used by arm, arm64 and xtensa.
Split it out into a separate file with a separate Kconfig symbol,
which gets the right copyright notice given that this code was
written by Laura Abbott working for Code Aurora at that point.


Ignoring the further super-nitpick that the comments got subtle grammar 
fixes in some places but not others,


Reviewed-by: Robin Murphy 


Signed-off-by: Christoph Hellwig 
Acked-by: Laura Abbott 
---
  arch/arm/Kconfig |  1 +
  arch/arm64/Kconfig   |  1 +
  arch/csky/Kconfig|  1 +
  arch/xtensa/Kconfig  |  1 +
  kernel/dma/Kconfig   |  4 ++
  kernel/dma/Makefile  |  2 +-
  kernel/dma/mapping.c | 84 --
  kernel/dma/remap.c   | 88 
  8 files changed, 97 insertions(+), 85 deletions(-)
  create mode 100644 kernel/dma/remap.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 91be74d8df65..3b2852df6eb3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -30,6 +30,7 @@ config ARM
select CPU_PM if (SUSPEND || CPU_IDLE)
select DCACHE_WORD_ACCESS if HAVE_EFFICIENT_UNALIGNED_ACCESS
select DMA_DIRECT_OPS if !MMU
+   select DMA_REMAP if MMU
select EDAC_SUPPORT
select EDAC_ATOMIC_SCRUB
select GENERIC_ALLOCATOR
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 787d7850e064..5d065acb6d10 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -82,6 +82,7 @@ config ARM64
select CRC32
select DCACHE_WORD_ACCESS
select DMA_DIRECT_OPS
+   select DMA_REMAP
select EDAC_SUPPORT
select FRAME_POINTER
select GENERIC_ALLOCATOR
diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig
index cb64f8dacd08..8a30e006a845 100644
--- a/arch/csky/Kconfig
+++ b/arch/csky/Kconfig
@@ -9,6 +9,7 @@ config CSKY
select CLKSRC_OF
select DMA_DIRECT_OPS
select DMA_NONCOHERENT_OPS
+   select DMA_REMAP
select IRQ_DOMAIN
select HANDLE_DOMAIN_IRQ
select DW_APB_TIMER_OF
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index d29b7365da8d..239bfb16c58b 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -11,6 +11,7 @@ config XTENSA
select CLONE_BACKWARDS
select COMMON_CLK
select DMA_DIRECT_OPS
+   select DMA_REMAP if MMU
select GENERIC_ATOMIC64
select GENERIC_CLOCKEVENTS
select GENERIC_IRQ_SHOW
diff --git a/kernel/dma/Kconfig b/kernel/dma/Kconfig
index 645c7a2ecde8..c92e08173ed8 100644
--- a/kernel/dma/Kconfig
+++ b/kernel/dma/Kconfig
@@ -51,3 +51,7 @@ config SWIOTLB
bool
select DMA_DIRECT_OPS
select NEED_DMA_MAP_STATE
+
+config DMA_REMAP
+   depends on MMU
+   bool
diff --git a/kernel/dma/Makefile b/kernel/dma/Makefile
index 7d581e4eea4a..f4feeceb8020 100644
--- a/kernel/dma/Makefile
+++ b/kernel/dma/Makefile
@@ -7,4 +7,4 @@ obj-$(CONFIG_DMA_DIRECT_OPS)+= direct.o
  obj-$(CONFIG_DMA_VIRT_OPS)+= virt.o
  obj-$(CONFIG_DMA_API_DEBUG)   += debug.o
  obj-$(CONFIG_SWIOTLB) += swiotlb.o
-
+obj-$(CONFIG_DMA_REMAP)+= remap.o
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index 58dec7a92b7b..dfbc3deb95cd 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -262,87 +262,3 @@ int dma_common_mmap(struct device *dev, struct 
vm_area_struct *vma,
  #endif /* !CONFIG_ARCH_NO_COHERENT_DMA_MMAP */
  }
  EXPORT_SYMBOL(dma_common_mmap);
-
-#ifdef CONFIG_MMU
-static struct vm_struct *__dma_common_pages_remap(struct page **pages,
-   size_t size, unsigned long vm_flags, pgprot_t prot,
-   const void *caller)
-{
-   struct vm_struct *area;
-
-   area = get_vm_area_caller(size, vm_flags, caller);
-   if (!area)
-   return NULL;
-
-   if (map_vm_area(area, prot, pages)) {
-   vunmap(area->addr);
-   return NULL;
-   }
-
-   return area;
-}
-
-/*
- * remaps an array of PAGE_SIZE pages into another vm_area
- * Cannot be used in non-sleeping contexts
- */
-void *dma_common_pages_remap(struct page **pages, size_t size,
-   unsigned long vm_flags, pgprot_t prot,
-   const void *caller)
-{
-   struct vm_struct *area;
-
-   area = __dma_common_pages_remap(pages, size, vm_flags, prot, caller);
-   if (!area)
-   return NULL;
-
-   area->pages = pages;
-
-   return area->addr;
-}
-
-/*
- * remaps an allocated contiguous region into another vm_area.
- * Cannot be used in non-sleeping contexts
- */
-
-void *dma_common_contiguous_remap(struct page *pag

Re: [PATCH 5/9] dma-mapping: support highmem in the generic remap allocator

2018-11-30 Thread Robin Murphy

On 05/11/2018 12:19, Christoph Hellwig wrote:

By using __dma_direct_alloc_pages we can deal entirely with struct page
instead of having to derive a kernel virtual address.


Simple enough :)

Reviewed-by: Robin Murphy 


Signed-off-by: Christoph Hellwig 
---
  kernel/dma/remap.c | 14 +++---
  1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/kernel/dma/remap.c b/kernel/dma/remap.c
index bc42766f52df..8f1fca34b894 100644
--- a/kernel/dma/remap.c
+++ b/kernel/dma/remap.c
@@ -196,7 +196,7 @@ void *arch_dma_alloc(struct device *dev, size_t size, 
dma_addr_t *dma_handle,
gfp_t flags, unsigned long attrs)
  {
struct page *page = NULL;
-   void *ret, *kaddr;
+   void *ret;
  
  	size = PAGE_ALIGN(size);
  
@@ -208,10 +208,9 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,

return ret;
}
  
-	kaddr = dma_direct_alloc_pages(dev, size, dma_handle, flags, attrs);

-   if (!kaddr)
+   page = __dma_direct_alloc_pages(dev, size, dma_handle, flags, attrs);
+   if (!page)
return NULL;
-   page = virt_to_page(kaddr);
  
  	/* remove any dirty cache lines on the kernel alias */

arch_dma_prep_coherent(page, size);
@@ -221,7 +220,7 @@ void *arch_dma_alloc(struct device *dev, size_t size, 
dma_addr_t *dma_handle,
arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs),
__builtin_return_address(0));
if (!ret)
-   dma_direct_free_pages(dev, size, kaddr, *dma_handle, attrs);
+   __dma_direct_free_pages(dev, size, page);
return ret;
  }
  
@@ -229,10 +228,11 @@ void arch_dma_free(struct device *dev, size_t size, void *vaddr,

dma_addr_t dma_handle, unsigned long attrs)
  {
if (!dma_free_from_pool(vaddr, PAGE_ALIGN(size))) {
-   void *kaddr = phys_to_virt(dma_to_phys(dev, dma_handle));
+   phys_addr_t phys = dma_to_phys(dev, dma_handle);
+   struct page *page = pfn_to_page(__phys_to_pfn(phys));
  
  		vunmap(vaddr);

-   dma_direct_free_pages(dev, size, kaddr, dma_handle, attrs);
+   __dma_direct_free_pages(dev, size, page);
}
  }
  


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 2/9] dma-direct: reject highmem pages from dma_alloc_from_contiguous

2018-11-30 Thread Robin Murphy

On 05/11/2018 12:19, Christoph Hellwig wrote:

dma_alloc_from_contiguous can return highmem pages depending on the
setup, which a plain non-remapping DMA allocator can't handle.  Detect
this case and try the normal page allocator instead.


...except the actual implementation is "Detect this case and fail the 
entire allocation if so".


Again, the diff itself makes sense, so given an accurate commit message,

Reviewed-by: Robin Murphy 



Signed-off-by: Christoph Hellwig 
---
  kernel/dma/direct.c | 12 
  1 file changed, 12 insertions(+)

diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 680287779b0a..c49849bcced6 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -162,6 +162,18 @@ void *dma_direct_alloc_pages(struct device *dev, size_t 
size,
if (!page)
return NULL;
  
+	if (PageHighMem(page)) {

+   /*
+* Depending on the cma= arguments and per-arch setup
+* dma_alloc_from_contiguous could return highmem pages.
+* Without remapping there is no way to return them here,
+* so log an error and fail.
+*/
+   dev_info(dev, "Rejecting highmem page from CMA.\n");
+   __dma_direct_free_pages(dev, size, page);
+   return NULL;
+   }
+
ret = page_address(page);
if (force_dma_unencrypted()) {
set_memory_decrypted((unsigned long)ret, 1 << get_order(size));


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 1/9] dma-direct: provide page based alloc/free helpers

2018-11-30 Thread Robin Murphy

On 05/11/2018 12:19, Christoph Hellwig wrote:

Some architectures support remapping highmem into DMA coherent
allocations.  To use the common code for them we need variants of
dma_direct_{alloc,free}_pages that do not use kernel virtual addresses.


FWIW it's as much about non-cacheable remapping of lowmem as it is about 
highmem. Regardless, the diff looks OK to me.


Reviewed-by: Robin Murphy 


Signed-off-by: Christoph Hellwig 
---
  include/linux/dma-direct.h |  3 +++
  kernel/dma/direct.c| 32 ++--
  2 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h
index bd73e7a91410..5a7a3bbb912f 100644
--- a/include/linux/dma-direct.h
+++ b/include/linux/dma-direct.h
@@ -67,6 +67,9 @@ void *dma_direct_alloc_pages(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs);
  void dma_direct_free_pages(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_addr, unsigned long attrs);
+struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
+   dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs);
+void __dma_direct_free_pages(struct device *dev, size_t size, struct page 
*page);
  dma_addr_t dma_direct_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir,
unsigned long attrs);
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 22a12ab5a5e9..680287779b0a 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -103,14 +103,13 @@ static bool dma_coherent_ok(struct device *dev, 
phys_addr_t phys, size_t size)
min_not_zero(dev->coherent_dma_mask, dev->bus_dma_mask);
  }
  
-void *dma_direct_alloc_pages(struct device *dev, size_t size,

+struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
  {
unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
int page_order = get_order(size);
struct page *page = NULL;
u64 phys_mask;
-   void *ret;
  
  	if (attrs & DMA_ATTR_NO_WARN)

gfp |= __GFP_NOWARN;
@@ -150,11 +149,22 @@ void *dma_direct_alloc_pages(struct device *dev, size_t 
size,
}
}
  
+	return page;

+}
+
+void *dma_direct_alloc_pages(struct device *dev, size_t size,
+   dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
+{
+   struct page *page;
+   void *ret;
+
+   page = __dma_direct_alloc_pages(dev, size, dma_handle, gfp, attrs);
if (!page)
return NULL;
+
ret = page_address(page);
if (force_dma_unencrypted()) {
-   set_memory_decrypted((unsigned long)ret, 1 << page_order);
+   set_memory_decrypted((unsigned long)ret, 1 << get_order(size));
*dma_handle = __phys_to_dma(dev, page_to_phys(page));
} else {
*dma_handle = phys_to_dma(dev, page_to_phys(page));
@@ -163,20 +173,22 @@ void *dma_direct_alloc_pages(struct device *dev, size_t 
size,
return ret;
  }
  
-/*

- * NOTE: this function must never look at the dma_addr argument, because we 
want
- * to be able to use it as a helper for iommu implementations as well.
- */
+void __dma_direct_free_pages(struct device *dev, size_t size, struct page 
*page)
+{
+   unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+   if (!dma_release_from_contiguous(dev, page, count))
+   __free_pages(page, get_order(size));
+}
+
  void dma_direct_free_pages(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_addr, unsigned long attrs)
  {
-   unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
unsigned int page_order = get_order(size);
  
  	if (force_dma_unencrypted())

set_memory_encrypted((unsigned long)cpu_addr, 1 << page_order);
-   if (!dma_release_from_contiguous(dev, virt_to_page(cpu_addr), count))
-   free_pages((unsigned long)cpu_addr, page_order);
+   __dma_direct_free_pages(dev, size, virt_to_page(cpu_addr));
  }
  
  void *dma_direct_alloc(struct device *dev, size_t size,



___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: remove the ->mapping_error method from dma_map_ops V3

2018-11-30 Thread Russell King - ARM Linux
On Fri, Nov 30, 2018 at 02:22:08PM +0100, Christoph Hellwig wrote:
> Error reporting for the dma_map_single and dma_map_page operations is
> currently a mess.  Both APIs directly return the dma_addr_t to be used for
> the DMA, with a magic error escape that is specific to the instance and
> checked by another method provided.  This has a few downsides:
> 
>  - the error check is easily forgotten and a __must_check marker doesn't
>help as the value always is consumed anyway
>  - the error checking requires another indirect call, which have gotten
>incredibly expensive
>  - a lot of code is wasted on implementing these methods
> 
> The historical reason for this is that people thought DMA mappings would
> not fail when the API was created, which sounds like a really bad
> assumption in retrospective, and then we tried to cram error handling
> onto it later on.
> 
> There basically are two variants:  the error code is 0 because the
> implementation will never return 0 as a valid DMA address, or the error
> code is all-F as the implementation won't ever return an address that
> high.  The old AMD GART is the only one not falling into these two camps
> as it picks sort of a relative zero relative to where it is mapped.
> 
> The 0 return doesn't work for direct mappings that have ram at address
> zero and a lot of IOMMUs that start allocating bus space from address
> zero, so we can't consolidate on that, but I think we can move everyone
> to all-Fs, which the patch here does.  The reason for that is that
> there is only one way to ever get this address: by doing a 1-byte long,
> 1-byte aligned mapping, but all our mappings are not only longer but
> generally aligned, and the mappings have to keep at least the basic
> alignment.
> 
> A git tree is also available here:
> 
> git://git.infradead.org/users/hch/misc.git dma-mapping-error.3

Hi Chris,

For patches 1, 3 and 23,

Acked-by: Russell King 

Thanks.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v18 1/5] iommu/arm-smmu: Add pm_runtime/sleep ops

2018-11-30 Thread Will Deacon
On Thu, Nov 29, 2018 at 08:25:20PM +0530, Vivek Gautam wrote:
> On Wed, Nov 28, 2018 at 10:07 PM Robin Murphy  wrote:
> >
> > On 28/11/2018 16:24, Stephen Boyd wrote:
> > > Quoting Vivek Gautam (2018-11-27 02:11:41)
> > >> @@ -1966,6 +1970,23 @@ static const struct of_device_id 
> > >> arm_smmu_of_match[] = {
> > >>   };
> > >>   MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
> > >>
> > >> +static void arm_smmu_fill_clk_data(struct arm_smmu_device *smmu,
> > >> +  const char * const *clks)
> > >> +{
> > >> +   int i;
> > >> +
> > >> +   if (smmu->num_clks < 1)
> > >> +   return;
> > >> +
> > >> +   smmu->clks = devm_kcalloc(smmu->dev, smmu->num_clks,
> > >> + sizeof(*smmu->clks), GFP_KERNEL);
> > >> +   if (!smmu->clks)
> > >> +   return;
> > >> +
> > >> +   for (i = 0; i < smmu->num_clks; i++)
> > >> +   smmu->clks[i].id = clks[i];
> > >
> > > Is this clk_bulk_get_all()?
> 
> From what I remember, and now I could go back to v7 and check [1], we parked
> clk_bulk_get out of OF's sole purview as we also have
> arm_smmu_device_acpi_probe() besides arm_smmu_device_dt_probe().
> 
> arm_smmu_device_dt_probe() could get the clocks from dt and fill in
> the clock bulk data, and
> similarly, arm_smmu_device_acpi_probe() could fill the clock bulk data
> by getting it from ACPI.
> 
> clk_bulk_get_all() seems like going only the OF way.
> Is there another way here to have something common between ACPI
> and OF, and then do the clk_bulk_get?

I'd say just go with clk_bulk_get_all() and if somebody really wants to
mess with the SMMU clocks on a system booted via ACPI, then it's their
problem to solve. My understanding is that the design of IORT makes this
next to impossible to solve anyway, because a static table is used and
therefore we're unable to run whatever ASL methods need to be invoked to
mess with the clocks.

Will
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH] dma-debug: Kconfig for PREALLOC_DMA_DEBUG_ENTRIES

2018-11-30 Thread Qian Cai
The amount of DMA mappings from Hisilicon HNS ethernet devices is huge,
so it could trigger "DMA-API: debugging out of memory - disabling".

hnae_get_handle [1]
  hnae_init_queue
hnae_init_ring
  hnae_alloc_buffers [2]
debug_dma_map_page
  dma_entry_alloc

[1] for (i = 0; i < handle->q_num; i++)
[2] for (i = 0; i < ring->desc_num; i++)

On this Huawei TaiShan 2280 aarch64 server, it has reached the limit
already,

4 (ports) x 16 (handles) x 1024 (rings) = 65536

Added a Kconfig entry for PREALLOC_DMA_DEBUG_ENTRIES, so make it easier
for users to deal with special cases like this.

Signed-off-by: Qian Cai 
---
 kernel/dma/debug.c | 9 ++---
 lib/Kconfig.debug  | 9 +
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/kernel/dma/debug.c b/kernel/dma/debug.c
index 231ca4628062..3752fb23f72f 100644
--- a/kernel/dma/debug.c
+++ b/kernel/dma/debug.c
@@ -41,11 +41,6 @@
 #define HASH_FN_SHIFT   13
 #define HASH_FN_MASK(HASH_SIZE - 1)
 
-/* allow architectures to override this if absolutely required */
-#ifndef PREALLOC_DMA_DEBUG_ENTRIES
-#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
-#endif
-
 enum {
dma_debug_single,
dma_debug_page,
@@ -132,7 +127,7 @@ static u32 min_free_entries;
 static u32 nr_total_entries;
 
 /* number of preallocated entries requested by kernel cmdline */
-static u32 nr_prealloc_entries = PREALLOC_DMA_DEBUG_ENTRIES;
+static u32 nr_prealloc_entries = CONFIG_PREALLOC_DMA_DEBUG_ENTRIES;
 
 /* debugfs dentry's for the stuff above */
 static struct dentry *dma_debug_dent__read_mostly;
@@ -1063,7 +1058,7 @@ static __init int dma_debug_entries_cmdline(char *str)
if (!str)
return -EINVAL;
if (!get_option(&str, &nr_prealloc_entries))
-   nr_prealloc_entries = PREALLOC_DMA_DEBUG_ENTRIES;
+   nr_prealloc_entries = CONFIG_PREALLOC_DMA_DEBUG_ENTRIES;
return 0;
 }
 
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 1af29b8224fd..2c281edcb5ad 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1659,6 +1659,15 @@ config DMA_API_DEBUG
 
  If unsure, say N.
 
+config PREALLOC_DMA_DEBUG_ENTRIES
+   int "Preallocated DMA-API debugging entries"
+   depends on DMA_API_DEBUG
+   default 65536
+   help
+ The number of preallocated entries for DMA-API debugging code. One
+ entry is required per DMA-API allocation. Increase this if the DMA-API
+ debugging code disables itself because the default is too low.
+
 config DMA_API_DEBUG_SG
bool "Debug DMA scatter-gather usage"
default y
-- 
2.17.2 (Apple Git-113)

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: PCI passthrough with multiple devices in same iommu group

2018-11-30 Thread Alex Williamson
On Fri, 30 Nov 2018 12:04:26 +0530
gokul cg  wrote:

> Thanks for info
> 
> See inline
> On Wed, Nov 28, 2018 at 8:56 PM Alex Williamson 
> wrote:
> 
> > On Wed, 28 Nov 2018 20:21:02 +0530
> > gokul cg  wrote:
> >  
> > > Hi Folks,
> > >
> > > Please excuse me , I just writing to you as i could see you had made
> > > changes regarding iommu and I thought you could give help me here.
> > >
> > > We are testing visualization with QEMU-2.7.0 + Linux-4.8+, we are facing
> > > issue while configuring pass through PCI devices in QEMU to pass it to
> > > guest OS.
> > > We are using following QEMU argument to configure PCI device as  
> > passthrough  
> > > device to guest, which was working with Linux 3.10 distro (hypervisor:  
> > QEMU  
> > > 1.7.2, Linux:  3.10+).
> > >
> > > /usr/bin/qemu-system-x86_64 -name guest_1 -S -machine
> > > pc-i440fx-1.7,accel=kvm,usb=off -m 49152\
> > >  -device kvm-pci-assign,host=:00:1f.3 -device
> > > kvm-pci-assign,host=:09:0e.0  ..  
> >
> > Legacy KVM device assignment (aka kvm-pci-assign) has been deprecated
> > for some time now, you'll find it doesn't even exist in newer kernels
> > and QEMU.
> >
> > Understood .  
> 
> > > Here is the error message that we will get when we try to configure PCI
> > > devices as passthrough using kvm pci assignment method in Linux 4.8+
> > > (hypervisor: QEMU 2.7.0, Linux:  4.8+).
> > >
> > > which is shown below.
> > >
> > > ---log---
> > >
> > > From QEMU:
> > > qemu-system-x86_64: -device kvm-pci-assign,host=:00:1f.3: Failed to
> > > assign device "(null)": Invalid argument
> > >
> > > From dmesg:
> > > pci-stub :00:1f.3: kvm assign device failed ret -22
> > >
> > > ---end
> > >
> > > Info about devices (CPU:  Intel(R) Xeon(R) CPU E5-2608L):
> > >
> > > root@shining-node:~# lspci -k -s 00:1f.3
> > > 00:1f.3 SMBus: Intel Corporation C610/X99 series chipset SMBus Controller
> > > (rev 05)
> > > Subsystem: Intel Corporation C610/X99 series chipset SMBus
> > > Controller
> > > Kernel driver in use: pci-stub
> > > Kernel modules: i2c_i801  
> >
> > Why are you trying to assign an SMBus controller to a VM?
> >
> > We want guest of to read out eprom and sensor devices  and manage our  
> chassis .
> Our i2c devices are connected to  Intel SMbus controller

It seems fundamentally unsafe to allow a user driver (where QEMU is
just a userspace driver exposing the device into a VM) to manage the
host chassis.  Additionally since this set of multifunction devices do
not expose access control services, we must assume that untranslated
DMA between the function is possible and thus group them together.  It
would be up to the hardware vendor whether the devices are in fact DMA
isolated to provide an ACS quirk to split this grouping.  Otherwise
you'll need to provide that isolation as a downstream assumption.

> > root@shining-node:~#  
> > > root@shining-node:~# lspci -k -s  09:0e.0
> > > 09:0e.0 Network controller: Broadcom Limited Device b680 (rev 12)
> > > root@shining-node:~#
> > >
> > > From the web search i could see that it is because there are multiple
> > > devices in same iommu_group that the passthrough device belongs to.
> > > When i check iommu_group , i have multiple devices in same group but all
> > > those are intel devices under Wellsburg PCH.  
> >
> > Nope, kvm-pci-assign doesn't make use of IOMMU groups, more likely just
> > some state of disrepair as it's deprecated and replaced by vfio-pci,
> > which does use iommu groups.  So iommu groups will be a problem, but
> > not in the configuration you're attempting to use above.
> >
> >  The error i had pasted above "< pci-stub :00:1f.3: kvm assign device  
> failed ret -22 >" is comming as iommu attach device
> fails because of following check .
> 1094 int iommu_attach_device(struct iommu_domain *domain, struct device
> *dev)
> 1095 {
> 1096 struct iommu_group *group;
> 1097 int ret;
> 1098
> 1099 group = iommu_group_get(dev);
> 1100 /* FIXME: Remove this when groups a mandatory for iommu
> drivers */
> 1101 if (group == NULL)
> 1102 return __iommu_attach_device(domain, dev);
> 1103

Ah yes, I forget about this since legacy KVM device assignment has been
deprecated for so long.

> > > root@shining-node:~# ls
> > > /sys/bus/pci/devices/\:00\:1f.3/iommu_group/devices/
> > > :00:1f.0  :00:1f.2  :00:1f.3  :00:1f.6
> > > root@shining-node:~#
> > > root@shining-node:~# lspci -v -s :00:1f
> > > 00:1f.0 ISA bridge: Intel Corporation C610/X99 series chipset LPC
> > > Controller (rev 05)
> > > Subsystem: Intel Corporation C610/X99 series chipset LPC Controller
> > > Flags: bus master, medium devsel, latency 0, NUMA node 0
> > > Capabilities: [e0] Vendor Specific Information: Len=0c 
> > > Kernel driver in use: lpc_ich
> > > Kernel modules: lpc_ich
> > >
> > > 00:1f.2 SATA controller: Intel Corporation C610/X99 series chipset 6-Port
> > > SATA Controller [AHCI mode] (

Re: use generic DMA mapping code in powerpc V4

2018-11-30 Thread Christian Zigotzky

Hello Christoph,

Thanks for your reply.

On 30 November 2018 at 2:10PM, Christoph Hellwig wrote:

On Fri, Nov 30, 2018 at 01:23:20PM +0100, Christian Zigotzky wrote:

Yes, of course. I patched your Git kernel and after that I compiled it
again. U-Boot loads the kernel and the dtb file. Then the kernel starts but
it doesn't find any hard disks (partitions).

Interesting.  Does it find the storage controller (what kind of
storage does it use?).
It seems not. I don't see any infos about hard disks in the kernel ring 
buffer. The two serial ATA (SATA 2.0) controllers are integrated in the 
P5020 SoC and the hard disks are connected via SerDes lanes (PCIe) to 
the SoC. LANE 16 = SATA 0 and LANE 17 = SATA 1.

For the PASEMI board can you test the attached patch?  Also are you
using Compact Flash cards on that system?
Yes, we are using Compact Flash cards. The slot is wired to the CPU 
local bus. It works with your kernel. :-)


Where is the attached patch?

I downloaded the version 5 of your Git kernel and compiled it today. 
Unfortunately the PASEMI ethernet doesn't work.


Error message: pci :00:1a.0: dma_direct_map_page: overflow 
0x00026bcb5002+110 of device mask  bus mask 0


@All
Could you please also test Christoph's kernel on your PASEMI and NXP boards? 
Download:

'git clone git://git.infradead.org/users/hch/misc.git -b powerpc-dma.5 a'

Thanks,
Christian

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH] irq_remapping: Remove unused header files

2018-11-30 Thread Yangtao Li
seq_file.h does not need to be included,so remove it.

Signed-off-by: Yangtao Li 
---
 drivers/iommu/irq_remapping.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c
index 7d0f3074d41d..b94ebd42edd8 100644
--- a/drivers/iommu/irq_remapping.c
+++ b/drivers/iommu/irq_remapping.c
@@ -1,4 +1,3 @@
-#include 
 #include 
 #include 
 #include 
-- 
2.17.0

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 16/23] x86/calgary: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
Return DMA_MAPPING_ERROR instead of the magic bad_dma_addr on a dma
mapping failure and let the core dma-mapping code handle the rest.

Remove the magic EMERGENCY_PAGES that the bad_dma_addr gets redirected to.

Signed-off-by: Christoph Hellwig 
---
 arch/x86/kernel/pci-calgary_64.c | 29 +++--
 1 file changed, 7 insertions(+), 22 deletions(-)

diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index bbfc8b1e9104..e76ec1b8ed1f 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -51,8 +51,6 @@
 #include 
 #include 
 
-#define CALGARY_MAPPING_ERROR  0
-
 #ifdef CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT
 int use_calgary __read_mostly = 1;
 #else
@@ -157,8 +155,6 @@ static const unsigned long phb_debug_offsets[] = {
 
 #define PHB_DEBUG_STUFF_OFFSET 0x0020
 
-#define EMERGENCY_PAGES 32 /* = 128KB */
-
 unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED;
 static int translate_empty_slots __read_mostly = 0;
 static int calgary_detected __read_mostly = 0;
@@ -255,7 +251,7 @@ static unsigned long iommu_range_alloc(struct device *dev,
if (panic_on_overflow)
panic("Calgary: fix the allocator.\n");
else
-   return CALGARY_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
}
}
 
@@ -274,11 +270,10 @@ static dma_addr_t iommu_alloc(struct device *dev, struct 
iommu_table *tbl,
dma_addr_t ret;
 
entry = iommu_range_alloc(dev, tbl, npages);
-
-   if (unlikely(entry == CALGARY_MAPPING_ERROR)) {
+   if (unlikely(entry == DMA_MAPPING_ERROR)) {
pr_warn("failed to allocate %u pages in iommu %p\n",
npages, tbl);
-   return CALGARY_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
}
 
/* set the return dma address */
@@ -298,8 +293,7 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t 
dma_addr,
unsigned long flags;
 
/* were we called with bad_dma_address? */
-   badend = CALGARY_MAPPING_ERROR + (EMERGENCY_PAGES * PAGE_SIZE);
-   if (unlikely(dma_addr < badend)) {
+   if (unlikely(dma_addr == DMA_MAPPING_ERROR)) {
WARN(1, KERN_ERR "Calgary: driver tried unmapping bad DMA "
   "address 0x%Lx\n", dma_addr);
return;
@@ -383,7 +377,7 @@ static int calgary_map_sg(struct device *dev, struct 
scatterlist *sg,
npages = iommu_num_pages(vaddr, s->length, PAGE_SIZE);
 
entry = iommu_range_alloc(dev, tbl, npages);
-   if (entry == CALGARY_MAPPING_ERROR) {
+   if (entry == DMA_MAPPING_ERROR) {
/* makes sure unmap knows to stop */
s->dma_length = 0;
goto error;
@@ -401,7 +395,7 @@ static int calgary_map_sg(struct device *dev, struct 
scatterlist *sg,
 error:
calgary_unmap_sg(dev, sg, nelems, dir, 0);
for_each_sg(sg, s, nelems, i) {
-   sg->dma_address = CALGARY_MAPPING_ERROR;
+   sg->dma_address = DMA_MAPPING_ERROR;
sg->dma_length = 0;
}
return 0;
@@ -454,7 +448,7 @@ static void* calgary_alloc_coherent(struct device *dev, 
size_t size,
 
/* set up tces to cover the allocated range */
mapping = iommu_alloc(dev, tbl, ret, npages, DMA_BIDIRECTIONAL);
-   if (mapping == CALGARY_MAPPING_ERROR)
+   if (mapping == DMA_MAPPING_ERROR)
goto free;
*dma_handle = mapping;
return ret;
@@ -479,11 +473,6 @@ static void calgary_free_coherent(struct device *dev, 
size_t size,
free_pages((unsigned long)vaddr, get_order(size));
 }
 
-static int calgary_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return dma_addr == CALGARY_MAPPING_ERROR;
-}
-
 static const struct dma_map_ops calgary_dma_ops = {
.alloc = calgary_alloc_coherent,
.free = calgary_free_coherent,
@@ -491,7 +480,6 @@ static const struct dma_map_ops calgary_dma_ops = {
.unmap_sg = calgary_unmap_sg,
.map_page = calgary_map_page,
.unmap_page = calgary_unmap_page,
-   .mapping_error = calgary_mapping_error,
.dma_supported = dma_direct_supported,
 };
 
@@ -739,9 +727,6 @@ static void __init calgary_reserve_regions(struct pci_dev 
*dev)
u64 start;
struct iommu_table *tbl = pci_iommu(dev->bus);
 
-   /* reserve EMERGENCY_PAGES from bad_dma_address and up */
-   iommu_range_reserve(tbl, CALGARY_MAPPING_ERROR, EMERGENCY_PAGES);
-
/* avoid the BIOS/VGA first 640KB-1MB region */
/* for CalIOC2 - avoid the entire first MB */
if (is_calgary(dev->device)) {
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mai

[PATCH 23/23] dma-mapping: return an error code from dma_mapping_error

2018-11-30 Thread Christoph Hellwig
Currently dma_mapping_error returns a boolean as int, with 1 meaning
error.  This is rather unusual and many callers have to convert it to
errno value.  The callers are highly inconsistent with error codes
ranging from -ENOMEM over -EIO, -EINVAL and -EFAULT ranging to -EAGAIN.
Return -ENOMEM which seems to be what the largest number of callers
convert it to, and which also matches the typical error case where
we are out of resources.

Signed-off-by: Christoph Hellwig 
---
 include/linux/dma-mapping.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 2adef56c6069..b5bd25fc1f81 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -576,7 +576,7 @@ static inline int dma_mapping_error(struct device *dev, 
dma_addr_t dma_addr)
 {
debug_dma_mapping_error(dev, dma_addr);
if (dma_addr == DMA_MAPPING_ERROR)
-   return 1;
+   return -ENOMEM;
return 0;
 }
 
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 20/23] iommu/dma-iommu: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
Return DMA_MAPPING_ERROR instead of 0 on a dma mapping failure and let
the core dma-mapping code handle the rest.

Signed-off-by: Christoph Hellwig 
---
 arch/arm64/mm/dma-mapping.c |  7 +++
 drivers/iommu/dma-iommu.c   | 23 ---
 include/linux/dma-iommu.h   |  1 -
 3 files changed, 11 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index fdc26ea5036c..4cc70029cf8d 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -397,7 +397,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t 
size,
return NULL;
 
*handle = iommu_dma_map_page(dev, page, 0, iosize, ioprot);
-   if (iommu_dma_mapping_error(dev, *handle)) {
+   if (*handle == DMA_MAPPING_ERROR) {
if (coherent)
__free_pages(page, get_order(size));
else
@@ -414,7 +414,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t 
size,
return NULL;
 
*handle = iommu_dma_map_page(dev, page, 0, iosize, ioprot);
-   if (iommu_dma_mapping_error(dev, *handle)) {
+   if (*handle == DMA_MAPPING_ERROR) {
dma_release_from_contiguous(dev, page,
size >> PAGE_SHIFT);
return NULL;
@@ -574,7 +574,7 @@ static dma_addr_t __iommu_map_page(struct device *dev, 
struct page *page,
dma_addr_t dev_addr = iommu_dma_map_page(dev, page, offset, size, prot);
 
if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
-   !iommu_dma_mapping_error(dev, dev_addr))
+   dev_addr != DMA_MAPPING_ERROR)
__dma_map_area(page_address(page) + offset, size, dir);
 
return dev_addr;
@@ -657,7 +657,6 @@ static const struct dma_map_ops iommu_dma_ops = {
.sync_sg_for_device = __iommu_sync_sg_for_device,
.map_resource = iommu_dma_map_resource,
.unmap_resource = iommu_dma_unmap_resource,
-   .mapping_error = iommu_dma_mapping_error,
 };
 
 static int __init __iommu_dma_init(void)
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index d1b04753b204..60c7e9e9901e 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -32,8 +32,6 @@
 #include 
 #include 
 
-#define IOMMU_MAPPING_ERROR0
-
 struct iommu_dma_msi_page {
struct list_headlist;
dma_addr_t  iova;
@@ -523,7 +521,7 @@ void iommu_dma_free(struct device *dev, struct page 
**pages, size_t size,
 {
__iommu_dma_unmap(iommu_get_dma_domain(dev), *handle, size);
__iommu_dma_free_pages(pages, PAGE_ALIGN(size) >> PAGE_SHIFT);
-   *handle = IOMMU_MAPPING_ERROR;
+   *handle = DMA_MAPPING_ERROR;
 }
 
 /**
@@ -556,7 +554,7 @@ struct page **iommu_dma_alloc(struct device *dev, size_t 
size, gfp_t gfp,
dma_addr_t iova;
unsigned int count, min_size, alloc_sizes = domain->pgsize_bitmap;
 
-   *handle = IOMMU_MAPPING_ERROR;
+   *handle = DMA_MAPPING_ERROR;
 
min_size = alloc_sizes & -alloc_sizes;
if (min_size < PAGE_SIZE) {
@@ -649,11 +647,11 @@ static dma_addr_t __iommu_dma_map(struct device *dev, 
phys_addr_t phys,
 
iova = iommu_dma_alloc_iova(domain, size, dma_get_mask(dev), dev);
if (!iova)
-   return IOMMU_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
 
if (iommu_map(domain, iova, phys - iova_off, size, prot)) {
iommu_dma_free_iova(cookie, iova, size);
-   return IOMMU_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
}
return iova + iova_off;
 }
@@ -694,7 +692,7 @@ static int __finalise_sg(struct device *dev, struct 
scatterlist *sg, int nents,
 
s->offset += s_iova_off;
s->length = s_length;
-   sg_dma_address(s) = IOMMU_MAPPING_ERROR;
+   sg_dma_address(s) = DMA_MAPPING_ERROR;
sg_dma_len(s) = 0;
 
/*
@@ -737,11 +735,11 @@ static void __invalidate_sg(struct scatterlist *sg, int 
nents)
int i;
 
for_each_sg(sg, s, nents, i) {
-   if (sg_dma_address(s) != IOMMU_MAPPING_ERROR)
+   if (sg_dma_address(s) != DMA_MAPPING_ERROR)
s->offset += sg_dma_address(s);
if (sg_dma_len(s))
s->length = sg_dma_len(s);
-   sg_dma_address(s) = IOMMU_MAPPING_ERROR;
+   sg_dma_address(s) = DMA_MAPPING_ERROR;
sg_dma_len(s) = 0;
}
 }
@@ -858,11 +856,6 @@ void iommu_dma_unmap_resource(struct device *dev, 
dma_addr_t handle,
__iommu_dma_unmap(iommu_get_dma_domain(dev), handle, size);
 }
 
-int iommu_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return dma_addr == IOMMU_MAPPING_ERROR;
-}
-
 

[PATCH 19/23] iommu/vt-d: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
Return DMA_MAPPING_ERROR instead of 0 on a dma mapping failure and let
the core dma-mapping code handle the rest.

Signed-off-by: Christoph Hellwig 
---
 drivers/iommu/intel-iommu.c | 12 +++-
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 66b398ae..0ad67d65bbce 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -3617,7 +3617,7 @@ static dma_addr_t __intel_map_page(struct device *dev, 
struct page *page,
 
domain = get_valid_domain_for_dev(dev);
if (!domain)
-   return 0;
+   return DMA_MAPPING_ERROR;
 
iommu = domain_get_iommu(domain);
size = aligned_nrpages(paddr, size);
@@ -3655,7 +3655,7 @@ static dma_addr_t __intel_map_page(struct device *dev, 
struct page *page,
free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size));
pr_err("Device %s request: %zx@%llx dir %d --- failed\n",
dev_name(dev), size, (unsigned long long)paddr, dir);
-   return 0;
+   return DMA_MAPPING_ERROR;
 }
 
 static dma_addr_t intel_map_page(struct device *dev, struct page *page,
@@ -3756,7 +3756,7 @@ static void *intel_alloc_coherent(struct device *dev, 
size_t size,
 
*dma_handle = __intel_map_page(dev, page, 0, size, DMA_BIDIRECTIONAL,
   dev->coherent_dma_mask);
-   if (*dma_handle)
+   if (*dma_handle != DMA_MAPPING_ERROR)
return page_address(page);
if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
__free_pages(page, order);
@@ -3865,11 +3865,6 @@ static int intel_map_sg(struct device *dev, struct 
scatterlist *sglist, int nele
return nelems;
 }
 
-static int intel_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return !dma_addr;
-}
-
 static const struct dma_map_ops intel_dma_ops = {
.alloc = intel_alloc_coherent,
.free = intel_free_coherent,
@@ -3877,7 +3872,6 @@ static const struct dma_map_ops intel_dma_ops = {
.unmap_sg = intel_unmap_sg,
.map_page = intel_map_page,
.unmap_page = intel_unmap_page,
-   .mapping_error = intel_mapping_error,
.dma_supported = dma_direct_supported,
 };
 
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 17/23] iommu: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
Return DMA_MAPPING_ERROR instead of 0 on a dma mapping failure and let
the core dma-mapping code handle the rest.

Note that the existing code used AMD_IOMMU_MAPPING_ERROR to check from
a 0 return from the IOVA allocator, which is replaced with an explicit
0 as in the implementation and other users of that interface.

Signed-off-by: Christoph Hellwig 
---
 drivers/iommu/amd_iommu.c | 18 +-
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 1167ff0416cf..c5d6c7c42b0a 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -55,8 +55,6 @@
 #include "amd_iommu_types.h"
 #include "irq_remapping.h"
 
-#define AMD_IOMMU_MAPPING_ERROR0
-
 #define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28))
 
 #define LOOP_TIMEOUT   10
@@ -2339,7 +2337,7 @@ static dma_addr_t __map_single(struct device *dev,
paddr &= PAGE_MASK;
 
address = dma_ops_alloc_iova(dev, dma_dom, pages, dma_mask);
-   if (address == AMD_IOMMU_MAPPING_ERROR)
+   if (!address)
goto out;
 
prot = dir2prot(direction);
@@ -2376,7 +2374,7 @@ static dma_addr_t __map_single(struct device *dev,
 
dma_ops_free_iova(dma_dom, address, pages);
 
-   return AMD_IOMMU_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
 }
 
 /*
@@ -2427,7 +2425,7 @@ static dma_addr_t map_page(struct device *dev, struct 
page *page,
if (PTR_ERR(domain) == -EINVAL)
return (dma_addr_t)paddr;
else if (IS_ERR(domain))
-   return AMD_IOMMU_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
 
dma_mask = *dev->dma_mask;
dma_dom = to_dma_ops_domain(domain);
@@ -2504,7 +2502,7 @@ static int map_sg(struct device *dev, struct scatterlist 
*sglist,
npages = sg_num_pages(dev, sglist, nelems);
 
address = dma_ops_alloc_iova(dev, dma_dom, npages, dma_mask);
-   if (address == AMD_IOMMU_MAPPING_ERROR)
+   if (address == DMA_MAPPING_ERROR)
goto out_err;
 
prot = dir2prot(direction);
@@ -2627,7 +2625,7 @@ static void *alloc_coherent(struct device *dev, size_t 
size,
*dma_addr = __map_single(dev, dma_dom, page_to_phys(page),
 size, DMA_BIDIRECTIONAL, dma_mask);
 
-   if (*dma_addr == AMD_IOMMU_MAPPING_ERROR)
+   if (*dma_addr == DMA_MAPPING_ERROR)
goto out_free;
 
return page_address(page);
@@ -2678,11 +2676,6 @@ static int amd_iommu_dma_supported(struct device *dev, 
u64 mask)
return check_device(dev);
 }
 
-static int amd_iommu_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return dma_addr == AMD_IOMMU_MAPPING_ERROR;
-}
-
 static const struct dma_map_ops amd_iommu_dma_ops = {
.alloc  = alloc_coherent,
.free   = free_coherent,
@@ -2691,7 +2684,6 @@ static const struct dma_map_ops amd_iommu_dma_ops = {
.map_sg = map_sg,
.unmap_sg   = unmap_sg,
.dma_supported  = amd_iommu_dma_supported,
-   .mapping_error  = amd_iommu_mapping_error,
 };
 
 static int init_reserved_iova_ranges(void)
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 22/23] dma-mapping: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
No users left except for vmd which just forwards it.

Signed-off-by: Christoph Hellwig 
---
 drivers/pci/controller/vmd.c | 6 --
 include/linux/dma-mapping.h  | 7 ---
 2 files changed, 13 deletions(-)

diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
index e50b0b5815ff..98ce79eac128 100644
--- a/drivers/pci/controller/vmd.c
+++ b/drivers/pci/controller/vmd.c
@@ -394,11 +394,6 @@ static void vmd_sync_sg_for_device(struct device *dev, 
struct scatterlist *sg,
vmd_dma_ops(dev)->sync_sg_for_device(to_vmd_dev(dev), sg, nents, dir);
 }
 
-static int vmd_mapping_error(struct device *dev, dma_addr_t addr)
-{
-   return vmd_dma_ops(dev)->mapping_error(to_vmd_dev(dev), addr);
-}
-
 static int vmd_dma_supported(struct device *dev, u64 mask)
 {
return vmd_dma_ops(dev)->dma_supported(to_vmd_dev(dev), mask);
@@ -446,7 +441,6 @@ static void vmd_setup_dma_ops(struct vmd_dev *vmd)
ASSIGN_VMD_DMA_OPS(source, dest, sync_single_for_device);
ASSIGN_VMD_DMA_OPS(source, dest, sync_sg_for_cpu);
ASSIGN_VMD_DMA_OPS(source, dest, sync_sg_for_device);
-   ASSIGN_VMD_DMA_OPS(source, dest, mapping_error);
ASSIGN_VMD_DMA_OPS(source, dest, dma_supported);
ASSIGN_VMD_DMA_OPS(source, dest, get_required_mask);
add_dma_domain(domain);
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 46bd612d929e..2adef56c6069 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -128,7 +128,6 @@ struct dma_map_ops {
   enum dma_data_direction dir);
void (*cache_sync)(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction direction);
-   int (*mapping_error)(struct device *dev, dma_addr_t dma_addr);
int (*dma_supported)(struct device *dev, u64 mask);
u64 (*get_required_mask)(struct device *dev);
 };
@@ -575,15 +574,9 @@ static inline void dma_free_coherent(struct device *dev, 
size_t size,
 
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
-   const struct dma_map_ops *ops = get_dma_ops(dev);
-
debug_dma_mapping_error(dev, dma_addr);
-
if (dma_addr == DMA_MAPPING_ERROR)
return 1;
-
-   if (ops->mapping_error)
-   return ops->mapping_error(dev, dma_addr);
return 0;
 }
 
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 18/23] iommu/intel: small map_page cleanup

2018-11-30 Thread Christoph Hellwig
Pass the page + offset to the low-level __iommu_map_single helper
(which gets renamed to fit the new calling conventions) as both
callers have the page at hand.

Signed-off-by: Christoph Hellwig 
---
 drivers/iommu/intel-iommu.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 41a4b8808802..66b398ae 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -3597,9 +3597,11 @@ static int iommu_no_mapping(struct device *dev)
return 0;
 }
 
-static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
-size_t size, int dir, u64 dma_mask)
+static dma_addr_t __intel_map_page(struct device *dev, struct page *page,
+  unsigned long offset, size_t size, int dir,
+  u64 dma_mask)
 {
+   phys_addr_t paddr = page_to_phys(page) + offset;
struct dmar_domain *domain;
phys_addr_t start_paddr;
unsigned long iova_pfn;
@@ -3661,8 +3663,7 @@ static dma_addr_t intel_map_page(struct device *dev, 
struct page *page,
 enum dma_data_direction dir,
 unsigned long attrs)
 {
-   return __intel_map_single(dev, page_to_phys(page) + offset, size,
- dir, *dev->dma_mask);
+   return __intel_map_page(dev, page, offset, size, dir, *dev->dma_mask);
 }
 
 static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size)
@@ -3753,9 +3754,8 @@ static void *intel_alloc_coherent(struct device *dev, 
size_t size,
return NULL;
memset(page_address(page), 0, size);
 
-   *dma_handle = __intel_map_single(dev, page_to_phys(page), size,
-DMA_BIDIRECTIONAL,
-dev->coherent_dma_mask);
+   *dma_handle = __intel_map_page(dev, page, 0, size, DMA_BIDIRECTIONAL,
+  dev->coherent_dma_mask);
if (*dma_handle)
return page_address(page);
if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 21/23] xen-swiotlb: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
Return DMA_MAPPING_ERROR instead of 0 on a dma mapping failure and let
the core dma-mapping code handle the rest.

Signed-off-by: Christoph Hellwig 
---
 drivers/xen/swiotlb-xen.c | 12 ++--
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 2a7f545bd0b5..6dc969d5ea2f 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -53,8 +53,6 @@
  * API.
  */
 
-#define XEN_SWIOTLB_ERROR_CODE (~(dma_addr_t)0x0)
-
 static char *xen_io_tlb_start, *xen_io_tlb_end;
 static unsigned long xen_io_tlb_nslabs;
 /*
@@ -406,7 +404,7 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, 
struct page *page,
map = swiotlb_tbl_map_single(dev, start_dma_addr, phys, size, dir,
 attrs);
if (map == SWIOTLB_MAP_ERROR)
-   return XEN_SWIOTLB_ERROR_CODE;
+   return DMA_MAPPING_ERROR;
 
dev_addr = xen_phys_to_bus(map);
xen_dma_map_page(dev, pfn_to_page(map >> PAGE_SHIFT),
@@ -421,7 +419,7 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, 
struct page *page,
attrs |= DMA_ATTR_SKIP_CPU_SYNC;
swiotlb_tbl_unmap_single(dev, map, size, dir, attrs);
 
-   return XEN_SWIOTLB_ERROR_CODE;
+   return DMA_MAPPING_ERROR;
 }
 
 /*
@@ -700,11 +698,6 @@ xen_swiotlb_get_sgtable(struct device *dev, struct 
sg_table *sgt,
return dma_common_get_sgtable(dev, sgt, cpu_addr, handle, size, attrs);
 }
 
-static int xen_swiotlb_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return dma_addr == XEN_SWIOTLB_ERROR_CODE;
-}
-
 const struct dma_map_ops xen_swiotlb_dma_ops = {
.alloc = xen_swiotlb_alloc_coherent,
.free = xen_swiotlb_free_coherent,
@@ -719,5 +712,4 @@ const struct dma_map_ops xen_swiotlb_dma_ops = {
.dma_supported = xen_swiotlb_dma_supported,
.mmap = xen_swiotlb_dma_mmap,
.get_sgtable = xen_swiotlb_get_sgtable,
-   .mapping_error  = xen_swiotlb_mapping_error,
 };
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 15/23] x86/amd_gart: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
Return DMA_MAPPING_ERROR instead of the magic bad_dma_addr on a dma
mapping failure and let the core dma-mapping code handle the rest.

Remove the magic EMERGENCY_PAGES that the bad_dma_addr gets redirected to.

Signed-off-by: Christoph Hellwig 
---
 arch/x86/kernel/amd_gart_64.c | 39 ++-
 1 file changed, 6 insertions(+), 33 deletions(-)

diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c
index 3f9d1b4019bb..4e733de93f41 100644
--- a/arch/x86/kernel/amd_gart_64.c
+++ b/arch/x86/kernel/amd_gart_64.c
@@ -50,8 +50,6 @@ static unsigned long iommu_pages; /* .. and in pages */
 
 static u32 *iommu_gatt_base;   /* Remapping table */
 
-static dma_addr_t bad_dma_addr;
-
 /*
  * If this is disabled the IOMMU will use an optimized flushing strategy
  * of only flushing when an mapping is reused. With it true the GART is
@@ -74,8 +72,6 @@ static u32 gart_unmapped_entry;
(((x) & 0xf000) | (((x) >> 32) << 4) | GPTE_VALID | GPTE_COHERENT)
 #define GPTE_DECODE(x) (((x) & 0xf000) | (((u64)(x) & 0xff0) << 28))
 
-#define EMERGENCY_PAGES 32 /* = 128KB */
-
 #ifdef CONFIG_AGP
 #define AGPEXTERN extern
 #else
@@ -184,14 +180,6 @@ static void iommu_full(struct device *dev, size_t size, 
int dir)
 */
 
dev_err(dev, "PCI-DMA: Out of IOMMU space for %lu bytes\n", size);
-
-   if (size > PAGE_SIZE*EMERGENCY_PAGES) {
-   if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL)
-   panic("PCI-DMA: Memory would be corrupted\n");
-   if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL)
-   panic(KERN_ERR
-   "PCI-DMA: Random memory would be DMAed\n");
-   }
 #ifdef CONFIG_IOMMU_LEAK
dump_leak();
 #endif
@@ -220,7 +208,7 @@ static dma_addr_t dma_map_area(struct device *dev, 
dma_addr_t phys_mem,
int i;
 
if (unlikely(phys_mem + size > GART_MAX_PHYS_ADDR))
-   return bad_dma_addr;
+   return DMA_MAPPING_ERROR;
 
iommu_page = alloc_iommu(dev, npages, align_mask);
if (iommu_page == -1) {
@@ -229,7 +217,7 @@ static dma_addr_t dma_map_area(struct device *dev, 
dma_addr_t phys_mem,
if (panic_on_overflow)
panic("dma_map_area overflow %lu bytes\n", size);
iommu_full(dev, size, dir);
-   return bad_dma_addr;
+   return DMA_MAPPING_ERROR;
}
 
for (i = 0; i < npages; i++) {
@@ -271,7 +259,7 @@ static void gart_unmap_page(struct device *dev, dma_addr_t 
dma_addr,
int npages;
int i;
 
-   if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE ||
+   if (dma_addr == DMA_MAPPING_ERROR ||
dma_addr >= iommu_bus_base + iommu_size)
return;
 
@@ -315,7 +303,7 @@ static int dma_map_sg_nonforce(struct device *dev, struct 
scatterlist *sg,
 
if (nonforced_iommu(dev, addr, s->length)) {
addr = dma_map_area(dev, addr, s->length, dir, 0);
-   if (addr == bad_dma_addr) {
+   if (addr == DMA_MAPPING_ERROR) {
if (i > 0)
gart_unmap_sg(dev, sg, i, dir, 0);
nents = 0;
@@ -471,7 +459,7 @@ static int gart_map_sg(struct device *dev, struct 
scatterlist *sg, int nents,
 
iommu_full(dev, pages << PAGE_SHIFT, dir);
for_each_sg(sg, s, nents, i)
-   s->dma_address = bad_dma_addr;
+   s->dma_address = DMA_MAPPING_ERROR;
return 0;
 }
 
@@ -490,7 +478,7 @@ gart_alloc_coherent(struct device *dev, size_t size, 
dma_addr_t *dma_addr,
*dma_addr = dma_map_area(dev, virt_to_phys(vaddr), size,
DMA_BIDIRECTIONAL, (1UL << get_order(size)) - 1);
flush_gart();
-   if (unlikely(*dma_addr == bad_dma_addr))
+   if (unlikely(*dma_addr == DMA_MAPPING_ERROR))
goto out_free;
return vaddr;
 out_free:
@@ -507,11 +495,6 @@ gart_free_coherent(struct device *dev, size_t size, void 
*vaddr,
dma_direct_free_pages(dev, size, vaddr, dma_addr, attrs);
 }
 
-static int gart_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return (dma_addr == bad_dma_addr);
-}
-
 static int no_agp;
 
 static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size)
@@ -695,7 +678,6 @@ static const struct dma_map_ops gart_dma_ops = {
.unmap_page = gart_unmap_page,
.alloc  = gart_alloc_coherent,
.free   = gart_free_coherent,
-   .mapping_error  = gart_mapping_error,
.dma_supported  = dma_direct_supported,
 };
 
@@ -784,19 +766,12 @@ int __init gart_iommu_init(void)
}
 #endif
 
-   /*
-* Out of IOMMU space handling.

[PATCH 14/23] ia64/sn: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
Return DMA_MAPPING_ERROR instead of 0 on a dma mapping failure and let
the core dma-mapping code handle the rest.

Signed-off-by: Christoph Hellwig 
---
 arch/ia64/sn/pci/pci_dma.c | 8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index 4ce4ee4ef9f2..b7d42e4edc1f 100644
--- a/arch/ia64/sn/pci/pci_dma.c
+++ b/arch/ia64/sn/pci/pci_dma.c
@@ -196,7 +196,7 @@ static dma_addr_t sn_dma_map_page(struct device *dev, 
struct page *page,
 
if (!dma_addr) {
printk(KERN_ERR "%s: out of ATEs\n", __func__);
-   return 0;
+   return DMA_MAPPING_ERROR;
}
return dma_addr;
 }
@@ -314,11 +314,6 @@ static int sn_dma_map_sg(struct device *dev, struct 
scatterlist *sgl,
return nhwentries;
 }
 
-static int sn_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return 0;
-}
-
 static u64 sn_dma_get_required_mask(struct device *dev)
 {
return DMA_BIT_MASK(64);
@@ -441,7 +436,6 @@ static struct dma_map_ops sn_dma_ops = {
.unmap_page = sn_dma_unmap_page,
.map_sg = sn_dma_map_sg,
.unmap_sg   = sn_dma_unmap_sg,
-   .mapping_error  = sn_dma_mapping_error,
.dma_supported  = sn_dma_supported,
.get_required_mask  = sn_dma_get_required_mask,
 };
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 13/23] ia64/sba_iommu: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
Return DMA_MAPPING_ERROR instead of 0 on a dma mapping failure and let
the core dma-mapping code handle the rest.

Signed-off-by: Christoph Hellwig 
---
 arch/ia64/hp/common/sba_iommu.c | 8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index c56f28c98102..0d21c0b5b23d 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -974,7 +974,7 @@ static dma_addr_t sba_map_page(struct device *dev, struct 
page *page,
 
pide = sba_alloc_range(ioc, dev, size);
if (pide < 0)
-   return 0;
+   return DMA_MAPPING_ERROR;
 
iovp = (dma_addr_t) pide << iovp_shift;
 
@@ -2155,11 +2155,6 @@ static int sba_dma_supported (struct device *dev, u64 
mask)
return ((mask & 0xUL) == 0xUL);
 }
 
-static int sba_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return 0;
-}
-
 __setup("nosbagart", nosbagart);
 
 static int __init
@@ -2193,7 +2188,6 @@ const struct dma_map_ops sba_dma_ops = {
.map_sg = sba_map_sg_attrs,
.unmap_sg   = sba_unmap_sg_attrs,
.dma_supported  = sba_dma_supported,
-   .mapping_error  = sba_dma_mapping_error,
 };
 
 void sba_dma_init(void)
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 12/23] ia64/sba_iommu: improve internal map_page users

2018-11-30 Thread Christoph Hellwig
Remove the odd sba_{un,}map_single_attrs wrappers, check errors
everywhere.

Signed-off-by: Christoph Hellwig 
---
 arch/ia64/hp/common/sba_iommu.c | 73 +
 1 file changed, 29 insertions(+), 44 deletions(-)

diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index e8a93b07283e..c56f28c98102 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -907,11 +907,12 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t 
byte_cnt)
 }
 
 /**
- * sba_map_single_attrs - map one buffer and return IOVA for DMA
+ * sba_map_page - map one buffer and return IOVA for DMA
  * @dev: instance of PCI owned by the driver that's asking.
- * @addr:  driver buffer to map.
- * @size:  number of bytes to map in driver buffer.
- * @dir:  R/W or both.
+ * @page: page to map
+ * @poff: offset into page
+ * @size: number of bytes to map
+ * @dir: dma direction
  * @attrs: optional dma attributes
  *
  * See Documentation/DMA-API-HOWTO.txt
@@ -944,7 +945,7 @@ static dma_addr_t sba_map_page(struct device *dev, struct 
page *page,
** Device is bit capable of DMA'ing to the buffer...
** just return the PCI address of ptr
*/
-   DBG_BYPASS("sba_map_single_attrs() bypass mask/addr: "
+   DBG_BYPASS("sba_map_page() bypass mask/addr: "
   "0x%lx/0x%lx\n",
   to_pci_dev(dev)->dma_mask, pci_addr);
return pci_addr;
@@ -966,7 +967,7 @@ static dma_addr_t sba_map_page(struct device *dev, struct 
page *page,
 
 #ifdef ASSERT_PDIR_SANITY
spin_lock_irqsave(&ioc->res_lock, flags);
-   if (sba_check_pdir(ioc,"Check before sba_map_single_attrs()"))
+   if (sba_check_pdir(ioc,"Check before sba_map_page()"))
panic("Sanity check failed");
spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif
@@ -997,20 +998,12 @@ static dma_addr_t sba_map_page(struct device *dev, struct 
page *page,
/* form complete address */
 #ifdef ASSERT_PDIR_SANITY
spin_lock_irqsave(&ioc->res_lock, flags);
-   sba_check_pdir(ioc,"Check after sba_map_single_attrs()");
+   sba_check_pdir(ioc,"Check after sba_map_page()");
spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif
return SBA_IOVA(ioc, iovp, offset);
 }
 
-static dma_addr_t sba_map_single_attrs(struct device *dev, void *addr,
-  size_t size, enum dma_data_direction dir,
-  unsigned long attrs)
-{
-   return sba_map_page(dev, virt_to_page(addr),
-   (unsigned long)addr & ~PAGE_MASK, size, dir, attrs);
-}
-
 #ifdef ENABLE_MARK_CLEAN
 static SBA_INLINE void
 sba_mark_clean(struct ioc *ioc, dma_addr_t iova, size_t size)
@@ -1036,7 +1029,7 @@ sba_mark_clean(struct ioc *ioc, dma_addr_t iova, size_t 
size)
 #endif
 
 /**
- * sba_unmap_single_attrs - unmap one IOVA and free resources
+ * sba_unmap_page - unmap one IOVA and free resources
  * @dev: instance of PCI owned by the driver that's asking.
  * @iova:  IOVA of driver buffer previously mapped.
  * @size:  number of bytes mapped in driver buffer.
@@ -1063,7 +1056,7 @@ static void sba_unmap_page(struct device *dev, dma_addr_t 
iova, size_t size,
/*
** Address does not fall w/in IOVA, must be bypassing
*/
-   DBG_BYPASS("sba_unmap_single_attrs() bypass addr: 0x%lx\n",
+   DBG_BYPASS("sba_unmap_page() bypass addr: 0x%lx\n",
   iova);
 
 #ifdef ENABLE_MARK_CLEAN
@@ -1114,12 +1107,6 @@ static void sba_unmap_page(struct device *dev, 
dma_addr_t iova, size_t size,
 #endif /* DELAYED_RESOURCE_CNT == 0 */
 }
 
-void sba_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size,
-   enum dma_data_direction dir, unsigned long attrs)
-{
-   sba_unmap_page(dev, iova, size, dir, attrs);
-}
-
 /**
  * sba_alloc_coherent - allocate/map shared mem for DMA
  * @dev: instance of PCI owned by the driver that's asking.
@@ -1132,30 +1119,24 @@ static void *
 sba_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
   gfp_t flags, unsigned long attrs)
 {
+   struct page *page;
struct ioc *ioc;
+   int node = -1;
void *addr;
 
ioc = GET_IOC(dev);
ASSERT(ioc);
-
 #ifdef CONFIG_NUMA
-   {
-   struct page *page;
-
-   page = alloc_pages_node(ioc->node, flags, get_order(size));
-   if (unlikely(!page))
-   return NULL;
-
-   addr = page_address(page);
-   }
-#else
-   addr = (void *) __get_free_pages(flags, get_order(size));
+   node = ioc->node;
 #endif
-   if (unlikely(!addr))
+
+   page = alloc_pages_node(node, flags, get_order(size));
+   if (unlikely(!page))
return NULL;
 
+   a

[PATCH 09/23] parisc/sba_iommu: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
The SBA iommu code already returns (~(dma_addr_t)0x0) on mapping
failures, so we can switch over to returning DMA_MAPPING_ERROR and let
the core dma-mapping code handle the rest.

Signed-off-by: Christoph Hellwig 
---
 drivers/parisc/sba_iommu.c | 10 +-
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index c1e599a429af..452d306ce5cb 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -93,8 +93,6 @@
 
 #define DEFAULT_DMA_HINT_REG   0
 
-#define SBA_MAPPING_ERROR(~(dma_addr_t)0)
-
 struct sba_device *sba_list;
 EXPORT_SYMBOL_GPL(sba_list);
 
@@ -725,7 +723,7 @@ sba_map_single(struct device *dev, void *addr, size_t size,
 
ioc = GET_IOC(dev);
if (!ioc)
-   return SBA_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
 
/* save offset bits */
offset = ((dma_addr_t) (long) addr) & ~IOVP_MASK;
@@ -1080,11 +1078,6 @@ sba_unmap_sg(struct device *dev, struct scatterlist 
*sglist, int nents,
 
 }
 
-static int sba_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return dma_addr == SBA_MAPPING_ERROR;
-}
-
 static const struct dma_map_ops sba_ops = {
.dma_supported =sba_dma_supported,
.alloc =sba_alloc,
@@ -1093,7 +1086,6 @@ static const struct dma_map_ops sba_ops = {
.unmap_page =   sba_unmap_page,
.map_sg =   sba_map_sg,
.unmap_sg = sba_unmap_sg,
-   .mapping_error =sba_mapping_error,
 };
 
 
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 11/23] alpha: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
Return DMA_MAPPING_ERROR instead of 0 on a dma mapping failure and let
the core dma-mapping code handle the rest.

Signed-off-by: Christoph Hellwig 
---
 arch/alpha/kernel/pci_iommu.c | 14 --
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 46e08e0d9181..e1716e0d92fd 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -291,7 +291,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, 
size_t size,
   use direct_map above, it now must be considered an error. */
if (! alpha_mv.mv_pci_tbi) {
printk_once(KERN_WARNING "pci_map_single: no HW sg\n");
-   return 0;
+   return DMA_MAPPING_ERROR;
}
 
arena = hose->sg_pci;
@@ -307,7 +307,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, 
size_t size,
if (dma_ofs < 0) {
printk(KERN_WARNING "pci_map_single failed: "
   "could not allocate dma page tables\n");
-   return 0;
+   return DMA_MAPPING_ERROR;
}
 
paddr &= PAGE_MASK;
@@ -455,7 +455,7 @@ static void *alpha_pci_alloc_coherent(struct device *dev, 
size_t size,
memset(cpu_addr, 0, size);
 
*dma_addrp = pci_map_single_1(pdev, cpu_addr, size, 0);
-   if (*dma_addrp == 0) {
+   if (*dma_addrp == DMA_MAPPING_ERROR) {
free_pages((unsigned long)cpu_addr, order);
if (alpha_mv.mv_pci_tbi || (gfp & GFP_DMA))
return NULL;
@@ -671,7 +671,7 @@ static int alpha_pci_map_sg(struct device *dev, struct 
scatterlist *sg,
sg->dma_address
  = pci_map_single_1(pdev, SG_ENT_VIRT_ADDRESS(sg),
 sg->length, dac_allowed);
-   return sg->dma_address != 0;
+   return sg->dma_address != DMA_MAPPING_ERROR;
}
 
start = sg;
@@ -935,11 +935,6 @@ iommu_unbind(struct pci_iommu_arena *arena, long pg_start, 
long pg_count)
return 0;
 }
 
-static int alpha_pci_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return dma_addr == 0;
-}
-
 const struct dma_map_ops alpha_pci_ops = {
.alloc  = alpha_pci_alloc_coherent,
.free   = alpha_pci_free_coherent,
@@ -947,7 +942,6 @@ const struct dma_map_ops alpha_pci_ops = {
.unmap_page = alpha_pci_unmap_page,
.map_sg = alpha_pci_map_sg,
.unmap_sg   = alpha_pci_unmap_sg,
-   .mapping_error  = alpha_pci_mapping_error,
.dma_supported  = alpha_pci_supported,
 };
 EXPORT_SYMBOL(alpha_pci_ops);
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 08/23] parisc/ccio: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
The CCIO iommu code already returns (~(dma_addr_t)0x0) on mapping
failures, so we can switch over to returning DMA_MAPPING_ERROR and let
the core dma-mapping code handle the rest.

Signed-off-by: Christoph Hellwig 
---
 drivers/parisc/ccio-dma.c | 10 +-
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 701a7d6a74d5..714aac72df0e 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -110,8 +110,6 @@
 #define CMD_TLB_DIRECT_WRITE 35 /* IO_COMMAND for I/O TLB Writes */
 #define CMD_TLB_PURGE33 /* IO_COMMAND to Purge I/O TLB entry */
 
-#define CCIO_MAPPING_ERROR(~(dma_addr_t)0)
-
 struct ioa_registers {
 /* Runway Supervisory Set */
 int32_tunused1[12];
@@ -740,7 +738,7 @@ ccio_map_single(struct device *dev, void *addr, size_t size,
BUG_ON(!dev);
ioc = GET_IOC(dev);
if (!ioc)
-   return CCIO_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
 
BUG_ON(size <= 0);
 
@@ -1021,11 +1019,6 @@ ccio_unmap_sg(struct device *dev, struct scatterlist 
*sglist, int nents,
DBG_RUN_SG("%s() DONE (nents %d)\n", __func__, nents);
 }
 
-static int ccio_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return dma_addr == CCIO_MAPPING_ERROR;
-}
-
 static const struct dma_map_ops ccio_ops = {
.dma_supported =ccio_dma_supported,
.alloc =ccio_alloc,
@@ -1034,7 +1027,6 @@ static const struct dma_map_ops ccio_ops = {
.unmap_page =   ccio_unmap_page,
.map_sg =   ccio_map_sg,
.unmap_sg = ccio_unmap_sg,
-   .mapping_error =ccio_mapping_error,
 };
 
 #ifdef CONFIG_PROC_FS
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 10/23] arm64: remove the dummy_dma_ops mapping_error method

2018-11-30 Thread Christoph Hellwig
Just return DMA_MAPPING_ERROR from __dummy_map_page and let the core
dma-mapping code handle the rest.

Signed-off-by: Christoph Hellwig 
---
 arch/arm64/mm/dma-mapping.c | 8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index a3ac26284845..fdc26ea5036c 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -282,7 +282,7 @@ static dma_addr_t __dummy_map_page(struct device *dev, 
struct page *page,
   enum dma_data_direction dir,
   unsigned long attrs)
 {
-   return 0;
+   return DMA_MAPPING_ERROR;
 }
 
 static void __dummy_unmap_page(struct device *dev, dma_addr_t dev_addr,
@@ -317,11 +317,6 @@ static void __dummy_sync_sg(struct device *dev,
 {
 }
 
-static int __dummy_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
-{
-   return 1;
-}
-
 static int __dummy_dma_supported(struct device *hwdev, u64 mask)
 {
return 0;
@@ -339,7 +334,6 @@ const struct dma_map_ops dummy_dma_ops = {
.sync_single_for_device = __dummy_sync_single,
.sync_sg_for_cpu= __dummy_sync_sg,
.sync_sg_for_device = __dummy_sync_sg,
-   .mapping_error  = __dummy_mapping_error,
.dma_supported  = __dummy_dma_supported,
 };
 EXPORT_SYMBOL(dummy_dma_ops);
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 06/23] s390: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
S390 already returns (~(dma_addr_t)0x0) on mapping failures, so we can
switch over to returning DMA_MAPPING_ERROR and let the core dma-mapping
code handle the rest.

Signed-off-by: Christoph Hellwig 
---
 arch/s390/pci/pci_dma.c | 18 +-
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index d387a0fbdd7e..346ba382193a 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -15,8 +15,6 @@
 #include 
 #include 
 
-#define S390_MAPPING_ERROR (~(dma_addr_t) 0x0)
-
 static struct kmem_cache *dma_region_table_cache;
 static struct kmem_cache *dma_page_table_cache;
 static int s390_iommu_strict;
@@ -301,7 +299,7 @@ static dma_addr_t dma_alloc_address(struct device *dev, int 
size)
 
 out_error:
spin_unlock_irqrestore(&zdev->iommu_bitmap_lock, flags);
-   return S390_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
 }
 
 static void dma_free_address(struct device *dev, dma_addr_t dma_addr, int size)
@@ -349,7 +347,7 @@ static dma_addr_t s390_dma_map_pages(struct device *dev, 
struct page *page,
/* This rounds up number of pages based on size and offset */
nr_pages = iommu_num_pages(pa, size, PAGE_SIZE);
dma_addr = dma_alloc_address(dev, nr_pages);
-   if (dma_addr == S390_MAPPING_ERROR) {
+   if (dma_addr == DMA_MAPPING_ERROR) {
ret = -ENOSPC;
goto out_err;
}
@@ -372,7 +370,7 @@ static dma_addr_t s390_dma_map_pages(struct device *dev, 
struct page *page,
 out_err:
zpci_err("map error:\n");
zpci_err_dma(ret, pa);
-   return S390_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
 }
 
 static void s390_dma_unmap_pages(struct device *dev, dma_addr_t dma_addr,
@@ -449,7 +447,7 @@ static int __s390_dma_map_sg(struct device *dev, struct 
scatterlist *sg,
int ret;
 
dma_addr_base = dma_alloc_address(dev, nr_pages);
-   if (dma_addr_base == S390_MAPPING_ERROR)
+   if (dma_addr_base == DMA_MAPPING_ERROR)
return -ENOMEM;
 
dma_addr = dma_addr_base;
@@ -496,7 +494,7 @@ static int s390_dma_map_sg(struct device *dev, struct 
scatterlist *sg,
for (i = 1; i < nr_elements; i++) {
s = sg_next(s);
 
-   s->dma_address = S390_MAPPING_ERROR;
+   s->dma_address = DMA_MAPPING_ERROR;
s->dma_length = 0;
 
if (s->offset || (size & ~PAGE_MASK) ||
@@ -546,11 +544,6 @@ static void s390_dma_unmap_sg(struct device *dev, struct 
scatterlist *sg,
}
 }

-static int s390_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return dma_addr == S390_MAPPING_ERROR;
-}
-
 int zpci_dma_init_device(struct zpci_dev *zdev)
 {
int rc;
@@ -675,7 +668,6 @@ const struct dma_map_ops s390_pci_dma_ops = {
.unmap_sg   = s390_dma_unmap_sg,
.map_page   = s390_dma_map_pages,
.unmap_page = s390_dma_unmap_pages,
-   .mapping_error  = s390_mapping_error,
/* dma_supported is unconditionally true without a callback */
 };
 EXPORT_SYMBOL_GPL(s390_pci_dma_ops);
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 07/23] sparc: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
Sparc already returns (~(dma_addr_t)0x0) on mapping failures, so we can
switch over to returning DMA_MAPPING_ERROR and let the core dma-mapping
code handle the rest.

Signed-off-by: Christoph Hellwig 
---
 arch/sparc/kernel/iommu.c| 12 +++-
 arch/sparc/kernel/iommu_common.h |  2 --
 arch/sparc/kernel/pci_sun4v.c| 14 --
 3 files changed, 7 insertions(+), 21 deletions(-)

diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c
index 40d008b0bd3e..0626bae5e3da 100644
--- a/arch/sparc/kernel/iommu.c
+++ b/arch/sparc/kernel/iommu.c
@@ -315,7 +315,7 @@ static dma_addr_t dma_4u_map_page(struct device *dev, 
struct page *page,
 bad_no_ctx:
if (printk_ratelimit())
WARN_ON(1);
-   return SPARC_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
 }
 
 static void strbuf_flush(struct strbuf *strbuf, struct iommu *iommu,
@@ -548,7 +548,7 @@ static int dma_4u_map_sg(struct device *dev, struct 
scatterlist *sglist,
 
if (outcount < incount) {
outs = sg_next(outs);
-   outs->dma_address = SPARC_MAPPING_ERROR;
+   outs->dma_address = DMA_MAPPING_ERROR;
outs->dma_length = 0;
}
 
@@ -574,7 +574,7 @@ static int dma_4u_map_sg(struct device *dev, struct 
scatterlist *sglist,
iommu_tbl_range_free(&iommu->tbl, vaddr, npages,
 IOMMU_ERROR_CODE);
 
-   s->dma_address = SPARC_MAPPING_ERROR;
+   s->dma_address = DMA_MAPPING_ERROR;
s->dma_length = 0;
}
if (s == outs)
@@ -742,11 +742,6 @@ static void dma_4u_sync_sg_for_cpu(struct device *dev,
spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
-static int dma_4u_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return dma_addr == SPARC_MAPPING_ERROR;
-}
-
 static int dma_4u_supported(struct device *dev, u64 device_mask)
 {
struct iommu *iommu = dev->archdata.iommu;
@@ -772,7 +767,6 @@ static const struct dma_map_ops sun4u_dma_ops = {
.sync_single_for_cpu= dma_4u_sync_single_for_cpu,
.sync_sg_for_cpu= dma_4u_sync_sg_for_cpu,
.dma_supported  = dma_4u_supported,
-   .mapping_error  = dma_4u_mapping_error,
 };
 
 const struct dma_map_ops *dma_ops = &sun4u_dma_ops;
diff --git a/arch/sparc/kernel/iommu_common.h b/arch/sparc/kernel/iommu_common.h
index e3c02ba32500..d62ed9c5682d 100644
--- a/arch/sparc/kernel/iommu_common.h
+++ b/arch/sparc/kernel/iommu_common.h
@@ -48,6 +48,4 @@ static inline int is_span_boundary(unsigned long entry,
return iommu_is_span_boundary(entry, nr, shift, boundary_size);
 }
 
-#define SPARC_MAPPING_ERROR(~(dma_addr_t)0x0)
-
 #endif /* _IOMMU_COMMON_H */
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c
index 565d9ac883d0..fa0e42b4cbfb 100644
--- a/arch/sparc/kernel/pci_sun4v.c
+++ b/arch/sparc/kernel/pci_sun4v.c
@@ -414,12 +414,12 @@ static dma_addr_t dma_4v_map_page(struct device *dev, 
struct page *page,
 bad:
if (printk_ratelimit())
WARN_ON(1);
-   return SPARC_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
 
 iommu_map_fail:
local_irq_restore(flags);
iommu_tbl_range_free(tbl, bus_addr, npages, IOMMU_ERROR_CODE);
-   return SPARC_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
 }
 
 static void dma_4v_unmap_page(struct device *dev, dma_addr_t bus_addr,
@@ -592,7 +592,7 @@ static int dma_4v_map_sg(struct device *dev, struct 
scatterlist *sglist,
 
if (outcount < incount) {
outs = sg_next(outs);
-   outs->dma_address = SPARC_MAPPING_ERROR;
+   outs->dma_address = DMA_MAPPING_ERROR;
outs->dma_length = 0;
}
 
@@ -609,7 +609,7 @@ static int dma_4v_map_sg(struct device *dev, struct 
scatterlist *sglist,
iommu_tbl_range_free(tbl, vaddr, npages,
 IOMMU_ERROR_CODE);
/* XXX demap? XXX */
-   s->dma_address = SPARC_MAPPING_ERROR;
+   s->dma_address = DMA_MAPPING_ERROR;
s->dma_length = 0;
}
if (s == outs)
@@ -688,11 +688,6 @@ static int dma_4v_supported(struct device *dev, u64 
device_mask)
return pci64_dma_supported(to_pci_dev(dev), device_mask);
 }
 
-static int dma_4v_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return dma_addr == SPARC_MAPPING_ERROR;
-}
-
 static const struct dma_map_ops sun4v_dma_ops = {
.alloc  = dma_4v_alloc_coherent,
.free   = dma_4v_free_coherent,
@@ -701,7 +696,6 @@ static const struct dma_map_ops sun4v_dma_ops = {
.map_sg = dma_4v_map_sg,
.unmap_sg   = dma_4v_unmap_sg,

[PATCH 04/23] powerpc/iommu: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
The powerpc iommu code already returns (~(dma_addr_t)0x0) on mapping
failures, so we can switch over to returning DMA_MAPPING_ERROR and let
the core dma-mapping code handle the rest.

Signed-off-by: Christoph Hellwig 
---
 arch/powerpc/include/asm/iommu.h |  4 
 arch/powerpc/kernel/dma-iommu.c  |  6 --
 arch/powerpc/kernel/iommu.c  | 28 ++--
 arch/powerpc/platforms/cell/iommu.c  |  1 -
 arch/powerpc/platforms/pseries/vio.c |  3 +--
 5 files changed, 15 insertions(+), 27 deletions(-)

diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h
index 35db0cbc9222..55312990d1d2 100644
--- a/arch/powerpc/include/asm/iommu.h
+++ b/arch/powerpc/include/asm/iommu.h
@@ -143,8 +143,6 @@ struct scatterlist;
 
 #ifdef CONFIG_PPC64
 
-#define IOMMU_MAPPING_ERROR(~(dma_addr_t)0x0)
-
 static inline void set_iommu_table_base(struct device *dev,
struct iommu_table *base)
 {
@@ -242,8 +240,6 @@ static inline int __init tce_iommu_bus_notifier_init(void)
 }
 #endif /* !CONFIG_IOMMU_API */
 
-int dma_iommu_mapping_error(struct device *dev, dma_addr_t dma_addr);
-
 #else
 
 static inline void *get_iommu_table_base(struct device *dev)
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index f9fe2080ceb9..5ebacf0fe41a 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -106,11 +106,6 @@ static u64 dma_iommu_get_required_mask(struct device *dev)
return mask;
 }
 
-int dma_iommu_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return dma_addr == IOMMU_MAPPING_ERROR;
-}
-
 struct dma_map_ops dma_iommu_ops = {
.alloc  = dma_iommu_alloc_coherent,
.free   = dma_iommu_free_coherent,
@@ -121,6 +116,5 @@ struct dma_map_ops dma_iommu_ops = {
.map_page   = dma_iommu_map_page,
.unmap_page = dma_iommu_unmap_page,
.get_required_mask  = dma_iommu_get_required_mask,
-   .mapping_error  = dma_iommu_mapping_error,
 };
 EXPORT_SYMBOL(dma_iommu_ops);
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index f0dc680e659a..ca7f73488c62 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -197,11 +197,11 @@ static unsigned long iommu_range_alloc(struct device *dev,
if (unlikely(npages == 0)) {
if (printk_ratelimit())
WARN_ON(1);
-   return IOMMU_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
}
 
if (should_fail_iommu(dev))
-   return IOMMU_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
 
/*
 * We don't need to disable preemption here because any CPU can
@@ -277,7 +277,7 @@ static unsigned long iommu_range_alloc(struct device *dev,
} else {
/* Give up */
spin_unlock_irqrestore(&(pool->lock), flags);
-   return IOMMU_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
}
}
 
@@ -309,13 +309,13 @@ static dma_addr_t iommu_alloc(struct device *dev, struct 
iommu_table *tbl,
  unsigned long attrs)
 {
unsigned long entry;
-   dma_addr_t ret = IOMMU_MAPPING_ERROR;
+   dma_addr_t ret = DMA_MAPPING_ERROR;
int build_fail;
 
entry = iommu_range_alloc(dev, tbl, npages, NULL, mask, align_order);
 
-   if (unlikely(entry == IOMMU_MAPPING_ERROR))
-   return IOMMU_MAPPING_ERROR;
+   if (unlikely(entry == DMA_MAPPING_ERROR))
+   return DMA_MAPPING_ERROR;
 
entry += tbl->it_offset;/* Offset into real TCE table */
ret = entry << tbl->it_page_shift;  /* Set the return dma address */
@@ -327,12 +327,12 @@ static dma_addr_t iommu_alloc(struct device *dev, struct 
iommu_table *tbl,
 
/* tbl->it_ops->set() only returns non-zero for transient errors.
 * Clean up the table bitmap in this case and return
-* IOMMU_MAPPING_ERROR. For all other errors the functionality is
+* DMA_MAPPING_ERROR. For all other errors the functionality is
 * not altered.
 */
if (unlikely(build_fail)) {
__iommu_free(tbl, ret, npages);
-   return IOMMU_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
}
 
/* Flush/invalidate TLB caches if necessary */
@@ -477,7 +477,7 @@ int ppc_iommu_map_sg(struct device *dev, struct iommu_table 
*tbl,
DBG("  - vaddr: %lx, size: %lx\n", vaddr, slen);
 
/* Handle failure */
-   if (unlikely(entry == IOMMU_MAPPING_ERROR)) {
+   if (unlikely(entry == DMA_MAPPING_ERROR)) {
if (!(attrs & DMA_ATTR_NO_WARN) &&
printk_ratelimit())
  

[PATCH 05/23] mips/jazz: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
The Jazz iommu code already returns (~(dma_addr_t)0x0) on mapping
failures, so we can switch over to returning DMA_MAPPING_ERROR and
let the core dma-mapping code handle the rest.

Signed-off-by: Christoph Hellwig 
---
 arch/mips/include/asm/jazzdma.h |  6 --
 arch/mips/jazz/jazzdma.c| 16 +---
 2 files changed, 5 insertions(+), 17 deletions(-)

diff --git a/arch/mips/include/asm/jazzdma.h b/arch/mips/include/asm/jazzdma.h
index d913439c738c..d13f940022d5 100644
--- a/arch/mips/include/asm/jazzdma.h
+++ b/arch/mips/include/asm/jazzdma.h
@@ -39,12 +39,6 @@ extern int vdma_get_enable(int channel);
 #define VDMA_PAGE(a)   ((unsigned int)(a) >> 12)
 #define VDMA_OFFSET(a) ((unsigned int)(a) & (VDMA_PAGESIZE-1))
 
-/*
- * error code returned by vdma_alloc()
- * (See also arch/mips/kernel/jazzdma.c)
- */
-#define VDMA_ERROR 0x
-
 /*
  * VDMA pagetable entry description
  */
diff --git a/arch/mips/jazz/jazzdma.c b/arch/mips/jazz/jazzdma.c
index 4c41ed0a637e..6256d35dbf4d 100644
--- a/arch/mips/jazz/jazzdma.c
+++ b/arch/mips/jazz/jazzdma.c
@@ -104,12 +104,12 @@ unsigned long vdma_alloc(unsigned long paddr, unsigned 
long size)
if (vdma_debug)
printk("vdma_alloc: Invalid physical address: %08lx\n",
   paddr);
-   return VDMA_ERROR;  /* invalid physical address */
+   return DMA_MAPPING_ERROR;   /* invalid physical address */
}
if (size > 0x40 || size == 0) {
if (vdma_debug)
printk("vdma_alloc: Invalid size: %08lx\n", size);
-   return VDMA_ERROR;  /* invalid physical address */
+   return DMA_MAPPING_ERROR;   /* invalid physical address */
}
 
spin_lock_irqsave(&vdma_lock, flags);
@@ -123,7 +123,7 @@ unsigned long vdma_alloc(unsigned long paddr, unsigned long 
size)
   first < VDMA_PGTBL_ENTRIES) first++;
if (first + pages > VDMA_PGTBL_ENTRIES) {   /* nothing free 
*/
spin_unlock_irqrestore(&vdma_lock, flags);
-   return VDMA_ERROR;
+   return DMA_MAPPING_ERROR;
}
 
last = first + 1;
@@ -569,7 +569,7 @@ static void *jazz_dma_alloc(struct device *dev, size_t size,
return NULL;
 
*dma_handle = vdma_alloc(virt_to_phys(ret), size);
-   if (*dma_handle == VDMA_ERROR) {
+   if (*dma_handle == DMA_MAPPING_ERROR) {
dma_direct_free_pages(dev, size, ret, *dma_handle, attrs);
return NULL;
}
@@ -620,7 +620,7 @@ static int jazz_dma_map_sg(struct device *dev, struct 
scatterlist *sglist,
arch_sync_dma_for_device(dev, sg_phys(sg), sg->length,
dir);
sg->dma_address = vdma_alloc(sg_phys(sg), sg->length);
-   if (sg->dma_address == VDMA_ERROR)
+   if (sg->dma_address == DMA_MAPPING_ERROR)
return 0;
sg_dma_len(sg) = sg->length;
}
@@ -674,11 +674,6 @@ static void jazz_dma_sync_sg_for_cpu(struct device *dev,
arch_sync_dma_for_cpu(dev, sg_phys(sg), sg->length, dir);
 }
 
-static int jazz_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return dma_addr == VDMA_ERROR;
-}
-
 const struct dma_map_ops jazz_dma_ops = {
.alloc  = jazz_dma_alloc,
.free   = jazz_dma_free,
@@ -692,6 +687,5 @@ const struct dma_map_ops jazz_dma_ops = {
.sync_sg_for_device = jazz_dma_sync_sg_for_device,
.dma_supported  = dma_direct_supported,
.cache_sync = arch_dma_cache_sync,
-   .mapping_error  = jazz_dma_mapping_error,
 };
 EXPORT_SYMBOL(jazz_dma_ops);
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 03/23] arm: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
Arm already returns (~(dma_addr_t)0x0) on mapping failures, so we can
switch over to returning DMA_MAPPING_ERROR and let the core dma-mapping
code handle the rest.

Signed-off-by: Christoph Hellwig 
---
 arch/arm/common/dmabounce.c  | 12 +++---
 arch/arm/include/asm/dma-iommu.h |  2 --
 arch/arm/mm/dma-mapping.c| 39 
 3 files changed, 18 insertions(+), 35 deletions(-)

diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 9a92de63426f..5ba4622030ca 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -257,7 +257,7 @@ static inline dma_addr_t map_single(struct device *dev, 
void *ptr, size_t size,
if (buf == NULL) {
dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
   __func__, ptr);
-   return ARM_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
}
 
dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
@@ -327,7 +327,7 @@ static dma_addr_t dmabounce_map_page(struct device *dev, 
struct page *page,
 
ret = needs_bounce(dev, dma_addr, size);
if (ret < 0)
-   return ARM_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
 
if (ret == 0) {
arm_dma_ops.sync_single_for_device(dev, dma_addr, size, dir);
@@ -336,7 +336,7 @@ static dma_addr_t dmabounce_map_page(struct device *dev, 
struct page *page,
 
if (PageHighMem(page)) {
dev_err(dev, "DMA buffer bouncing of HIGHMEM pages is not 
supported\n");
-   return ARM_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
}
 
return map_single(dev, page_address(page) + offset, size, dir, attrs);
@@ -453,11 +453,6 @@ static int dmabounce_dma_supported(struct device *dev, u64 
dma_mask)
return arm_dma_ops.dma_supported(dev, dma_mask);
 }
 
-static int dmabounce_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return arm_dma_ops.mapping_error(dev, dma_addr);
-}
-
 static const struct dma_map_ops dmabounce_ops = {
.alloc  = arm_dma_alloc,
.free   = arm_dma_free,
@@ -472,7 +467,6 @@ static const struct dma_map_ops dmabounce_ops = {
.sync_sg_for_cpu= arm_dma_sync_sg_for_cpu,
.sync_sg_for_device = arm_dma_sync_sg_for_device,
.dma_supported  = dmabounce_dma_supported,
-   .mapping_error  = dmabounce_mapping_error,
 };
 
 static int dmabounce_init_pool(struct dmabounce_pool *pool, struct device *dev,
diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h
index 6821f1249300..772f48ef84b7 100644
--- a/arch/arm/include/asm/dma-iommu.h
+++ b/arch/arm/include/asm/dma-iommu.h
@@ -9,8 +9,6 @@
 #include 
 #include 
 
-#define ARM_MAPPING_ERROR  (~(dma_addr_t)0x0)
-
 struct dma_iommu_mapping {
/* iommu specific data */
struct iommu_domain *domain;
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 661fe48ab78d..2cfb17bad1e6 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -179,11 +179,6 @@ static void arm_dma_sync_single_for_device(struct device 
*dev,
__dma_page_cpu_to_dev(page, offset, size, dir);
 }
 
-static int arm_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return dma_addr == ARM_MAPPING_ERROR;
-}
-
 const struct dma_map_ops arm_dma_ops = {
.alloc  = arm_dma_alloc,
.free   = arm_dma_free,
@@ -197,7 +192,6 @@ const struct dma_map_ops arm_dma_ops = {
.sync_single_for_device = arm_dma_sync_single_for_device,
.sync_sg_for_cpu= arm_dma_sync_sg_for_cpu,
.sync_sg_for_device = arm_dma_sync_sg_for_device,
-   .mapping_error  = arm_dma_mapping_error,
.dma_supported  = arm_dma_supported,
 };
 EXPORT_SYMBOL(arm_dma_ops);
@@ -217,7 +211,6 @@ const struct dma_map_ops arm_coherent_dma_ops = {
.get_sgtable= arm_dma_get_sgtable,
.map_page   = arm_coherent_dma_map_page,
.map_sg = arm_dma_map_sg,
-   .mapping_error  = arm_dma_mapping_error,
.dma_supported  = arm_dma_supported,
 };
 EXPORT_SYMBOL(arm_coherent_dma_ops);
@@ -774,7 +767,7 @@ static void *__dma_alloc(struct device *dev, size_t size, 
dma_addr_t *handle,
gfp &= ~(__GFP_COMP);
args.gfp = gfp;
 
-   *handle = ARM_MAPPING_ERROR;
+   *handle = DMA_MAPPING_ERROR;
allowblock = gfpflags_allow_blocking(gfp);
cma = allowblock ? dev_get_cma_area(dev) : false;
 
@@ -1217,7 +1210,7 @@ static inline dma_addr_t __alloc_iova(struct 
dma_iommu_mapping *mapping,
if (i == mapping->nr_bitmaps) {
if (extend_iommu_mapping(mapping)) {
spin_unlock_irqrestore(&mapping->lock, flags);
-   ret

[PATCH 02/23] dma-direct: remove the mapping_error dma_map_ops method

2018-11-30 Thread Christoph Hellwig
The dma-direct code already returns (~(dma_addr_t)0x0) on mapping
failures, so we can switch over to returning DMA_MAPPING_ERROR and let
the core dma-mapping code handle the rest.

Signed-off-by: Christoph Hellwig 
---
 arch/powerpc/kernel/dma-swiotlb.c |  1 -
 include/linux/dma-direct.h|  3 ---
 kernel/dma/direct.c   |  8 +---
 kernel/dma/swiotlb.c  | 11 +--
 4 files changed, 6 insertions(+), 17 deletions(-)

diff --git a/arch/powerpc/kernel/dma-swiotlb.c 
b/arch/powerpc/kernel/dma-swiotlb.c
index 5fc335f4d9cd..3d8df2cf8be9 100644
--- a/arch/powerpc/kernel/dma-swiotlb.c
+++ b/arch/powerpc/kernel/dma-swiotlb.c
@@ -59,7 +59,6 @@ const struct dma_map_ops powerpc_swiotlb_dma_ops = {
.sync_single_for_device = swiotlb_sync_single_for_device,
.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
.sync_sg_for_device = swiotlb_sync_sg_for_device,
-   .mapping_error = dma_direct_mapping_error,
.get_required_mask = swiotlb_powerpc_get_required,
 };
 
diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h
index 9e66bfe369aa..e7600f92d876 100644
--- a/include/linux/dma-direct.h
+++ b/include/linux/dma-direct.h
@@ -5,8 +5,6 @@
 #include 
 #include 
 
-#define DIRECT_MAPPING_ERROR   (~(dma_addr_t)0)
-
 #ifdef CONFIG_ARCH_HAS_PHYS_TO_DMA
 #include 
 #else
@@ -73,5 +71,4 @@ dma_addr_t dma_direct_map_page(struct device *dev, struct 
page *page,
 int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
enum dma_data_direction dir, unsigned long attrs);
 int dma_direct_supported(struct device *dev, u64 mask);
-int dma_direct_mapping_error(struct device *dev, dma_addr_t dma_addr);
 #endif /* _LINUX_DMA_DIRECT_H */
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 22a12ab5a5e9..d4335a03193a 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -265,7 +265,7 @@ dma_addr_t dma_direct_map_page(struct device *dev, struct 
page *page,
dma_addr_t dma_addr = phys_to_dma(dev, phys);
 
if (!check_addr(dev, dma_addr, size, __func__))
-   return DIRECT_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
 
if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
dma_direct_sync_single_for_device(dev, dma_addr, size, dir);
@@ -312,11 +312,6 @@ int dma_direct_supported(struct device *dev, u64 mask)
return mask >= phys_to_dma(dev, min_mask);
 }
 
-int dma_direct_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-   return dma_addr == DIRECT_MAPPING_ERROR;
-}
-
 const struct dma_map_ops dma_direct_ops = {
.alloc  = dma_direct_alloc,
.free   = dma_direct_free,
@@ -335,7 +330,6 @@ const struct dma_map_ops dma_direct_ops = {
 #endif
.get_required_mask  = dma_direct_get_required_mask,
.dma_supported  = dma_direct_supported,
-   .mapping_error  = dma_direct_mapping_error,
.cache_sync = arch_dma_cache_sync,
 };
 EXPORT_SYMBOL(dma_direct_ops);
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index 045930e32c0e..ff1ce81bb623 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -631,21 +631,21 @@ static dma_addr_t swiotlb_bounce_page(struct device *dev, 
phys_addr_t *phys,
if (unlikely(swiotlb_force == SWIOTLB_NO_FORCE)) {
dev_warn_ratelimited(dev,
"Cannot do DMA to address %pa\n", phys);
-   return DIRECT_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
}
 
/* Oh well, have to allocate and map a bounce buffer. */
*phys = swiotlb_tbl_map_single(dev, __phys_to_dma(dev, io_tlb_start),
*phys, size, dir, attrs);
if (*phys == SWIOTLB_MAP_ERROR)
-   return DIRECT_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
 
/* Ensure that the address returned is DMA'ble */
dma_addr = __phys_to_dma(dev, *phys);
if (unlikely(!dma_capable(dev, dma_addr, size))) {
swiotlb_tbl_unmap_single(dev, *phys, size, dir,
attrs | DMA_ATTR_SKIP_CPU_SYNC);
-   return DIRECT_MAPPING_ERROR;
+   return DMA_MAPPING_ERROR;
}
 
return dma_addr;
@@ -680,7 +680,7 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page 
*page,
 
if (!dev_is_dma_coherent(dev) &&
(attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0 &&
-   dev_addr != DIRECT_MAPPING_ERROR)
+   dev_addr != DMA_MAPPING_ERROR)
arch_sync_dma_for_device(dev, phys, size, dir);
 
return dev_addr;
@@ -789,7 +789,7 @@ swiotlb_map_sg_attrs(struct device *dev, struct scatterlist 
*sgl, int nelems,
for_each_sg(sgl, sg, nelems, i) {
sg->dma_address = swiotlb_map_page(dev, sg_page(sg), sg->offset,
sg->length, dir, attrs);
-   if (sg->dma_address == DIRECT

remove the ->mapping_error method from dma_map_ops V3

2018-11-30 Thread Christoph Hellwig
Error reporting for the dma_map_single and dma_map_page operations is
currently a mess.  Both APIs directly return the dma_addr_t to be used for
the DMA, with a magic error escape that is specific to the instance and
checked by another method provided.  This has a few downsides:

 - the error check is easily forgotten and a __must_check marker doesn't
   help as the value always is consumed anyway
 - the error checking requires another indirect call, which have gotten
   incredibly expensive
 - a lot of code is wasted on implementing these methods

The historical reason for this is that people thought DMA mappings would
not fail when the API was created, which sounds like a really bad
assumption in retrospective, and then we tried to cram error handling
onto it later on.

There basically are two variants:  the error code is 0 because the
implementation will never return 0 as a valid DMA address, or the error
code is all-F as the implementation won't ever return an address that
high.  The old AMD GART is the only one not falling into these two camps
as it picks sort of a relative zero relative to where it is mapped.

The 0 return doesn't work for direct mappings that have ram at address
zero and a lot of IOMMUs that start allocating bus space from address
zero, so we can't consolidate on that, but I think we can move everyone
to all-Fs, which the patch here does.  The reason for that is that
there is only one way to ever get this address: by doing a 1-byte long,
1-byte aligned mapping, but all our mappings are not only longer but
generally aligned, and the mappings have to keep at least the basic
alignment.

A git tree is also available here:

git://git.infradead.org/users/hch/misc.git dma-mapping-error.3

Gitweb:


http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/dma-mapping-error.3

Changes since v2:
 - fix a compile error in the ia64 sba_iommu driver
 - return an errno value from dma_mapping_error

Changes since v1:
 - dropped the signature change
 - split into multiple patches
 - fixed the iova allocator return check in amd-iommu
 - remove EMERGENCY_PAGES in amd_gart and calgary
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 01/23] dma-mapping: provide a generic DMA_MAPPING_ERROR

2018-11-30 Thread Christoph Hellwig
Error handling of the dma_map_single and dma_map_page APIs is a little
problematic at the moment, in that we use different encodings in the
returned dma_addr_t to indicate an error.  That means we require an
additional indirect call to figure out if a dma mapping call returned
an error, and a lot of boilerplate code to implement these semantics.

Instead return the maximum addressable value as the error.  As long
as we don't allow mapping single-byte ranges with single-byte alignment
this value can never be a valid return.  Additionaly if drivers do
not check the return value from the dma_map* routines this values means
they will generally not be pointed to actual memory.

Once the default value is added here we can start removing the
various mapping_error methods and just rely on this generic check.

Signed-off-by: Christoph Hellwig 
---
 include/linux/dma-mapping.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 0f81c713f6e9..46bd612d929e 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -133,6 +133,8 @@ struct dma_map_ops {
u64 (*get_required_mask)(struct device *dev);
 };
 
+#define DMA_MAPPING_ERROR  (~(dma_addr_t)0)
+
 extern const struct dma_map_ops dma_direct_ops;
 extern const struct dma_map_ops dma_virt_ops;
 
@@ -576,6 +578,10 @@ static inline int dma_mapping_error(struct device *dev, 
dma_addr_t dma_addr)
const struct dma_map_ops *ops = get_dma_ops(dev);
 
debug_dma_mapping_error(dev, dma_addr);
+
+   if (dma_addr == DMA_MAPPING_ERROR)
+   return 1;
+
if (ops->mapping_error)
return ops->mapping_error(dev, dma_addr);
return 0;
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: use generic DMA mapping code in powerpc V4

2018-11-30 Thread Christoph Hellwig
On Fri, Nov 30, 2018 at 01:23:20PM +0100, Christian Zigotzky wrote:
> Hi Christoph,
>
> Thanks a lot for your fast reply.
>
> On 30 November 2018 at 11:53AM, Christoph Hellwig wrote:
>> Hi Christian,
>>
>> for such a diverse architecture like powerpc we'll have to rely on
>> users / non core developers like you to help with testing.
> I see. I will help as good as I can.
>>
>> Can you try the patch below for he cyrus config?
> Yes, of course. I patched your Git kernel and after that I compiled it 
> again. U-Boot loads the kernel and the dtb file. Then the kernel starts but 
> it doesn't find any hard disks (partitions).

Interesting.  Does it find the storage controller (what kind of
storage does it use?).

For the PASEMI board can you test the attached patch?  Also are you
using Compact Flash cards on that system?

> @All
> Could you please also test Christoph's kernel on your PASEMI and NXP 
> boards? Download: 'git clone git://git.infradead.org/users/hch/misc.git -b 
> powerpc-dma.4 a'

FYI, I've pushed a new powerpc-dma.5 with the various fixes discussed
in this thread.

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: use generic DMA mapping code in powerpc V4

2018-11-30 Thread Christian Zigotzky

Hi Christoph,

Thanks a lot for your fast reply.

On 30 November 2018 at 11:53AM, Christoph Hellwig wrote:

Hi Christian,

for such a diverse architecture like powerpc we'll have to rely on
users / non core developers like you to help with testing.

I see. I will help as good as I can.


Can you try the patch below for he cyrus config?
Yes, of course. I patched your Git kernel and after that I compiled it 
again. U-Boot loads the kernel and the dtb file. Then the kernel starts 
but it doesn't find any hard disks (partitions).


@All
Could you please also test Christoph's kernel on your PASEMI and NXP 
boards? Download: 'git clone git://git.infradead.org/users/hch/misc.git 
-b powerpc-dma.4 a'

*PLEASE*


For the nemo one I have no idea yet,
We had some problems with the PASEMI ethernet and DMA two years ago. I 
had to deactivate the option PASEMI_IOMMU_DMA_FORCE.


commit 416f37d0816b powerpc/pasemi: Fix coherent_dma_mask for dma engine:

Commit 817820b0 ("powerpc/iommu: Support "hybrid" iommu/direct DMA
ops for coherent_mask < dma_mask) adds a check of coherent_dma_mask for
dma allocations.

Unfortunately current PASemi code does not set this value for the DMA
engine, which ends up with the default value of 0x, the result
is on a PASemi system with >2Gb ram and iommu enabled the onboard
ethernet stops working due to an inability to allocate memory. Add an
initialisation to pci_dma_dev_setup_pasemi().
Signed-off-by: Darren Stevens 
Signed-off-by: Michael Ellerman 

Links:
https://lists.ozlabs.org/pipermail/linuxppc-dev/2016-July/146701.html
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=416f37d0816b9720b8227953e55954d81456f991

FYI: DMA handling has been rewritten in 2015. We had some problems with 
the new DMA code in 2015. I had to revert the commit ' [RFC/PATCH,v2] 
powerpc/iommu: Support "hybrid" iommu/direct DMA ops for coherent_mask < 
dma_mask' in 2015.


Link: https://patchwork.ozlabs.org/patch/472535/

I had to create a patch in 2015:

    diff -rupN linux-4.4/arch/powerpc/Kconfig 
linux-4.4-nemo/arch/powerpc/Kconfig
    --- linux-4.4/arch/powerpc/Kconfig    2015-12-07 00:43:12.0 
+0100
    +++ linux-4.4-nemo/arch/powerpc/Kconfig    2015-12-07 
14:48:23.371987988 +0100

    @@ -158,8 +155,6 @@ config PPC
 select HAVE_PERF_EVENTS_NMI if PPC64
 select EDAC_SUPPORT
 select EDAC_ATOMIC_SCRUB
    -    select ARCH_HAS_DMA_SET_COHERENT_MASK
    -    select HAVE_ARCH_SECCOMP_FILTER

 config GENERIC_CSUM
 def_bool CPU_LITTLE_ENDIAN
    @@ -419,8 +414,7 @@ config PPC64_SUPPORTS_MEMORY_FAILURE

 config KEXEC
 bool "kexec system call"
    -    depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP)) || 
PPC_BOOK3E

    -    select KEXEC_CORE
    +    depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP))
 help
   kexec is a system call that implements the ability to 
shutdown your
   current kernel, and to start another kernel.  It is like a 
reboot


    diff -rupN linux-4.4/arch/powerpc/kernel/dma.c 
linux-4.4-nemo/arch/powerpc/kernel/dma.c
    --- linux-4.4/arch/powerpc/kernel/dma.c    2015-12-07 
00:43:12.0 +0100
    +++ linux-4.4-nemo/arch/powerpc/kernel/dma.c    2015-12-07 
14:49:38.098286892 +0100

    @@ -40,31 +39,9 @@ static u64 __maybe_unused get_pfn_limit(
 return pfn;
 }

    -static int dma_direct_dma_supported(struct device *dev, u64 mask)
    -{
    -#ifdef CONFIG_PPC64
    -    u64 limit = get_dma_offset(dev) + (memblock_end_of_DRAM() - 1);
    -
    -    /* Limit fits in the mask, we are good */
    -    if (mask >= limit)
    -    return 1;
    -
    -#ifdef CONFIG_FSL_SOC
    -    /* Freescale gets another chance via ZONE_DMA/ZONE_DMA32, however
    - * that will have to be refined if/when they support iommus
    - */
    -    return 1;
    -#endif
    -    /* Sorry ... */
    -    return 0;
    -#else
    -    return 1;
    -#endif
    -}
    -
    -void *__dma_direct_alloc_coherent(struct device *dev, size_t size,
    -  dma_addr_t *dma_handle, gfp_t flag,
    -  struct dma_attrs *attrs)
    +void *dma_direct_alloc_coherent(struct device *dev, size_t size,
    +    dma_addr_t *dma_handle, gfp_t flag,
    +    struct dma_attrs *attrs)
 {
 void *ret;
 #ifdef CONFIG_NOT_COHERENT_CACHE
    @@ -119,9 +96,9 @@ void *__dma_direct_alloc_coherent(struct
 #endif
 }

    -void __dma_direct_free_coherent(struct device *dev, size_t size,
    -    void *vaddr, dma_addr_t dma_handle,
    -    struct dma_attrs *attrs)
    +void dma_direct_free_coherent(struct device *dev, size_t size,
    +  void *vaddr, dma_addr_t dma_handle,
    +  struct dma_attrs *attrs)
 {
 #ifdef CONFIG_NOT_COHERENT_CACHE
 __dma_free_coherent(size, vaddr);
    @@ -130,51 +107,6 @@ void __dma_direct_free_coherent(struct d
 #endif
   

Re: [PATCH] dma-debug: hns_enet_drv could use more DMA entries

2018-11-30 Thread Robin Murphy

On 30/11/2018 08:42, Christoph Hellwig wrote:

On Thu, Nov 29, 2018 at 10:54:56PM -0500, Qian Cai wrote:

  /* allow architectures to override this if absolutely required */
  #ifndef PREALLOC_DMA_DEBUG_ENTRIES
+/* amount of DMA mappings on this driver is huge. */
+#ifdef HNS_ENET
+#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 17)
+#else
  #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
  #endif
+#endif


How would this be defined in a header that leaks into this file?


Apparently it wouldn't, because nothing defines that macro anywhere 
anyway. CONFIG_HNS_ENET, on the other hand, would be available by virtue 
of autoconf.h which is just about everywhere.



I think we need to turn PREALLOC_DMA_DEBUG_ENTRIES into a user
selectable config options, as I really don't want to collect hacks like
this.


Agreed - we already have per-arch overrides scattered about, so growing 
special cases in yet another place just makes even more of a mess. 
Rounding all of it up into Kconfig would definitely make sense.


Robin.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4] iommu/dma: Use NUMA aware memory allocations in __iommu_dma_alloc_pages()

2018-11-30 Thread John Garry
From: Ganapatrao Kulkarni 

Change function __iommu_dma_alloc_pages() to allocate pages for DMA from
respective device NUMA node. The ternary operator which would be for
alloc_pages_node() is tidied along with this.

The motivation for this change is to have a policy for page allocation
consistent with direct DMA mapping, which attempts to allocate pages local
to the device, as mentioned in [1].

In addition, for certain workloads it has been observed a marginal
performance improvement. The patch caused an observation of 0.9% average
throughput improvement for running tcrypt with HiSilicon crypto engine.

We also include a modification to use kvzalloc() for kzalloc()/vzalloc()
combination.

[1] https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1692998.html

Signed-off-by: Ganapatrao Kulkarni 
[JPG: Added kvzalloc(), drop pages ** being device local, remove ternary 
operator, update message]
Signed-off-by: John Garry 
---
Difference:
v1->v2:
- Add Ganapatrao's tag and change author

v2->v3:
- removed ternary operator
- stopped making pages ** allocation local to device

v3->v4:
- Update commit message to include motivation for patch, including
  headline performance improvement for test.

Some notes:
This patch was originally posted by Ganapatrao in [2].

However, after initial review, it was never reposted (due to lack of
cycles, I think). In addition, the functionality in its sibling patches
were merged through patches, as mentioned in [2]; this also refers to a
discussion on device local allocations vs CPU local allocations for DMA
pool, and which is better [1].

However, as mentioned in [1], dma_alloc_coherent() uses the locality
information from the device - as in direct DMA - so this patch is just
applying this same policy.

And from some testing, mentioned in commit message, shows marginal
improvement.

[2] https://lore.kernel.org/patchwork/patch/833004/
[3] https://lkml.org/lkml/2018/8/22/391

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index d1b0475..4afb1a8 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -449,20 +449,17 @@ static void __iommu_dma_free_pages(struct page **pages, 
int count)
kvfree(pages);
 }
 
-static struct page **__iommu_dma_alloc_pages(unsigned int count,
-   unsigned long order_mask, gfp_t gfp)
+static struct page **__iommu_dma_alloc_pages(struct device *dev,
+   unsigned int count, unsigned long order_mask, gfp_t gfp)
 {
struct page **pages;
-   unsigned int i = 0, array_size = count * sizeof(*pages);
+   unsigned int i = 0, nid = dev_to_node(dev);
 
order_mask &= (2U << MAX_ORDER) - 1;
if (!order_mask)
return NULL;
 
-   if (array_size <= PAGE_SIZE)
-   pages = kzalloc(array_size, GFP_KERNEL);
-   else
-   pages = vzalloc(array_size);
+   pages = kvzalloc(count * sizeof(*pages), GFP_KERNEL);
if (!pages)
return NULL;
 
@@ -481,10 +478,12 @@ static struct page **__iommu_dma_alloc_pages(unsigned int 
count,
for (order_mask &= (2U << __fls(count)) - 1;
 order_mask; order_mask &= ~order_size) {
unsigned int order = __fls(order_mask);
+   gfp_t alloc_flags = gfp;
 
order_size = 1U << order;
-   page = alloc_pages((order_mask - order_size) ?
-  gfp | __GFP_NORETRY : gfp, order);
+   if (order_mask > order_size)
+   alloc_flags |= __GFP_NORETRY;
+   page = alloc_pages_node(nid, alloc_flags, order);
if (!page)
continue;
if (!order)
@@ -569,7 +568,8 @@ struct page **iommu_dma_alloc(struct device *dev, size_t 
size, gfp_t gfp,
alloc_sizes = min_size;
 
count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-   pages = __iommu_dma_alloc_pages(count, alloc_sizes >> PAGE_SHIFT, gfp);
+   pages = __iommu_dma_alloc_pages(dev, count, alloc_sizes >> PAGE_SHIFT,
+   gfp);
if (!pages)
return NULL;
 
-- 
1.9.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: use generic DMA mapping code in powerpc V4

2018-11-30 Thread Christoph Hellwig
Hi Christian,

for such a diverse architecture like powerpc we'll have to rely on
users / non core developers like you to help with testing.

Can you try the patch below for he cyrus config?

For the nemo one I have no idea yet, there is no chance I could trick
you into a git bisect to see which patch caused the problem, is there?


diff --git a/arch/powerpc/include/asm/machdep.h 
b/arch/powerpc/include/asm/machdep.h
index 7b70dcbce1b9..2f0ca6560e47 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -47,7 +47,7 @@ struct machdep_calls {
 #endif
 #endif /* CONFIG_PPC64 */
 
-   int (*dma_set_mask)(struct device *dev, u64 dma_mask);
+   void(*dma_set_mask)(struct device *dev, u64 dma_mask);
 
int (*probe)(void);
void(*setup_arch)(void); /* Optional, may be NULL */
diff --git a/arch/powerpc/kernel/dma-swiotlb.c 
b/arch/powerpc/kernel/dma-swiotlb.c
index bded4127791a..2587eb0f3fde 100644
--- a/arch/powerpc/kernel/dma-swiotlb.c
+++ b/arch/powerpc/kernel/dma-swiotlb.c
@@ -22,11 +22,10 @@
 #include 
 #include 
 
-bool arch_dma_set_mask(struct device *dev, u64 dma_mask)
+void arch_dma_set_mask(struct device *dev, u64 dma_mask)
 {
-   if (!ppc_md.dma_set_mask)
-   return 0;
-   return ppc_md.dma_set_mask(dev, dma_mask);
+   if (ppc_md.dma_set_mask)
+   ppc_md.dma_set_mask(dev, dma_mask);
 }
 EXPORT_SYMBOL(arch_dma_set_mask);
 
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 9584765dbe3b..8582a418516b 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -134,7 +134,7 @@ static void setup_swiotlb_ops(struct pci_controller *hose)
 static inline void setup_swiotlb_ops(struct pci_controller *hose) {}
 #endif
 
-static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask)
+static void fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask)
 {
/*
 * Fix up PCI devices that are able to DMA to the large inbound
@@ -144,8 +144,6 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 
dma_mask)
dev->bus_dma_mask = 0;
dev->archdata.dma_offset = pci64_dma_offset;
}
-
-   return 0;
 }
 
 static int setup_one_atmu(struct ccsr_pci __iomem *pci,
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 8dd19e66c0e5..94a4db5f7ec3 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -599,17 +599,16 @@ static inline int dma_supported(struct device *dev, u64 
mask)
 }
 
 #ifdef CONFIG_ARCH_HAS_DMA_SET_MASK
-bool arch_dma_set_mask(struct device *dev, u64 mask);
+void arch_dma_set_mask(struct device *dev, u64 mask);
 #else
-#define arch_dma_set_mask(dev, mask)   true
+#define arch_dma_set_mask(dev, mask)   do { } while (0)
 #endif
 
 static inline int dma_set_mask(struct device *dev, u64 mask)
 {
if (!dev->dma_mask || !dma_supported(dev, mask))
return -EIO;
-   if (!arch_dma_set_mask(dev, mask))
-   return -EIO;
+   arch_dma_set_mask(dev, mask);
dma_check_mask(dev, mask);
 
*dev->dma_mask = mask;

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH] dma-debug: hns_enet_drv could use more DMA entries

2018-11-30 Thread John Garry

+

Pasting original message at bottom.


On 30/11/2018 08:42, Christoph Hellwig wrote:

On Thu, Nov 29, 2018 at 10:54:56PM -0500, Qian Cai wrote:

 /* allow architectures to override this if absolutely required */
 #ifndef PREALLOC_DMA_DEBUG_ENTRIES
+/* amount of DMA mappings on this driver is huge. */
+#ifdef HNS_ENET
+#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 17)
+#else
 #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
 #endif
+#endif


How would this be defined in a header that leaks into this file?

I think we need to turn PREALLOC_DMA_DEBUG_ENTRIES into a user
selectable config options, as I really don't want to collect hacks like
this.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu










The amount of DMA mappings from Hisilicon HNS ethernet devices is huge,
so it could trigger "DMA-API: debugging out of memory - disabling".

hnae_get_handle [1]
  hnae_init_queue
hnae_init_ring
  hnae_alloc_buffers [2]
debug_dma_map_page
  dma_entry_alloc

[1] for (i = 0; i < handle->q_num; i++)
[2] for (i = 0; i < ring->desc_num; i++)

On this Huawei TaiShan 2280 aarch64 server, it has reached the limit
already,

4 (ports) x 16 (handles) x 1024 (rings) = 65536

Signed-off-by: Qian Cai 
---
 kernel/dma/debug.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/kernel/dma/debug.c b/kernel/dma/debug.c
index 231ca4628062..ae91689cc9ad 100644
--- a/kernel/dma/debug.c
+++ b/kernel/dma/debug.c
@@ -43,8 +43,13 @@

 /* allow architectures to override this if absolutely required */
 #ifndef PREALLOC_DMA_DEBUG_ENTRIES
+/* amount of DMA mappings on this driver is huge. */
+#ifdef HNS_ENET
+#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 17)
+#else
 #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
 #endif
+#endif

 enum {
dma_debug_single,


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH] dma-debug: hns_enet_drv could use more DMA entries

2018-11-30 Thread Christoph Hellwig
On Thu, Nov 29, 2018 at 10:54:56PM -0500, Qian Cai wrote:
>  /* allow architectures to override this if absolutely required */
>  #ifndef PREALLOC_DMA_DEBUG_ENTRIES
> +/* amount of DMA mappings on this driver is huge. */
> +#ifdef   HNS_ENET
> +#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 17)
> +#else
>  #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
>  #endif
> +#endif

How would this be defined in a header that leaks into this file?

I think we need to turn PREALLOC_DMA_DEBUG_ENTRIES into a user
selectable config options, as I really don't want to collect hacks like
this.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu