Re: + arc-convert-to-dma_map_ops.patch added to -mm tree

From: Vineet Gupta
Date: Mon Nov 23 2015 - 23:24:01 EST


On Wednesday 18 November 2015 03:08 AM, akpm@xxxxxxxxxxxxxxxxxxxx wrote:
> The patch titled
> Subject: arc: convert to dma_map_ops
> has been added to the -mm tree. Its filename is
> arc-convert-to-dma_map_ops.patch
>
> This patch should soon appear at
> http://ozlabs.org/~akpm/mmots/broken-out/arc-convert-to-dma_map_ops.patch
> and later at
> http://ozlabs.org/~akpm/mmotm/broken-out/arc-convert-to-dma_map_ops.patch
>
> Before you just go and hit "reply", please:
> a) Consider who else should be cc'ed
> b) Prefer to cc a suitable mailing list as well
> c) Ideally: find the original patch on the mailing list and do a
> reply-to-all to that, adding suitable additional cc's
>
> *** Remember to use Documentation/SubmitChecklist when testing your code ***
>
> The -mm tree is included into linux-next and is updated
> there every 3-4 working days
>
> ------------------------------------------------------
> From: Christoph Hellwig <hch@xxxxxx>
> Subject: arc: convert to dma_map_ops
>
> Signed-off-by: Christoph Hellwig <hch@xxxxxx>
> Cc: Vineet Gupta <vgupta@xxxxxxxxxxxx>
> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
> ---
>
> arch/arc/Kconfig | 1
> arch/arc/include/asm/dma-mapping.h | 187 ---------------------------
> arch/arc/mm/dma.c | 151 +++++++++++++++------
> 3 files changed, 109 insertions(+), 230 deletions(-)
>
> diff -puN arch/arc/Kconfig~arc-convert-to-dma_map_ops arch/arc/Kconfig
> --- a/arch/arc/Kconfig~arc-convert-to-dma_map_ops
> +++ a/arch/arc/Kconfig
> @@ -38,6 +38,7 @@ config ARC
> select OF_EARLY_FLATTREE
> select PERF_USE_VMALLOC
> select HAVE_DEBUG_STACKOVERFLOW
> + select HAVE_DMA_ATTRS
>
> config TRACE_IRQFLAGS_SUPPORT
> def_bool y
> diff -puN arch/arc/include/asm/dma-mapping.h~arc-convert-to-dma_map_ops arch/arc/include/asm/dma-mapping.h
> --- a/arch/arc/include/asm/dma-mapping.h~arc-convert-to-dma_map_ops
> +++ a/arch/arc/include/asm/dma-mapping.h
> @@ -11,192 +11,13 @@
> #ifndef ASM_ARC_DMA_MAPPING_H
> #define ASM_ARC_DMA_MAPPING_H
>
> -#include <asm-generic/dma-coherent.h>
> -#include <asm/cacheflush.h>
> +extern struct dma_map_ops arc_dma_ops;
>
> -void *dma_alloc_noncoherent(struct device *dev, size_t size,
> - dma_addr_t *dma_handle, gfp_t gfp);
> -
> -void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
> - dma_addr_t dma_handle);
> -
> -void *dma_alloc_coherent(struct device *dev, size_t size,
> - dma_addr_t *dma_handle, gfp_t gfp);
> -
> -void dma_free_coherent(struct device *dev, size_t size, void *kvaddr,
> - dma_addr_t dma_handle);
> -
> -/* drivers/base/dma-mapping.c */
> -extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
> - void *cpu_addr, dma_addr_t dma_addr, size_t size);
> -extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
> - void *cpu_addr, dma_addr_t dma_addr,
> - size_t size);
> -
> -#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s)
> -#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s)
> -
> -/*
> - * streaming DMA Mapping API...
> - * CPU accesses page via normal paddr, thus needs to explicitly made
> - * consistent before each use
> - */
> -
> -static inline void __inline_dma_cache_sync(unsigned long paddr, size_t size,
> - enum dma_data_direction dir)
> -{
> - switch (dir) {
> - case DMA_FROM_DEVICE:
> - dma_cache_inv(paddr, size);
> - break;
> - case DMA_TO_DEVICE:
> - dma_cache_wback(paddr, size);
> - break;
> - case DMA_BIDIRECTIONAL:
> - dma_cache_wback_inv(paddr, size);
> - break;
> - default:
> - pr_err("Invalid DMA dir [%d] for OP @ %lx\n", dir, paddr);
> - }
> -}
> -
> -void __arc_dma_cache_sync(unsigned long paddr, size_t size,
> - enum dma_data_direction dir);
> -
> -#define _dma_cache_sync(addr, sz, dir) \
> -do { \
> - if (__builtin_constant_p(dir)) \
> - __inline_dma_cache_sync(addr, sz, dir); \
> - else \
> - __arc_dma_cache_sync(addr, sz, dir); \
> -} \
> -while (0);
> -
> -static inline dma_addr_t
> -dma_map_single(struct device *dev, void *cpu_addr, size_t size,
> - enum dma_data_direction dir)
> -{
> - _dma_cache_sync((unsigned long)cpu_addr, size, dir);
> - return (dma_addr_t)cpu_addr;
> -}
> -
> -static inline void
> -dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
> - size_t size, enum dma_data_direction dir)
> -{
> -}
> -
> -static inline dma_addr_t
> -dma_map_page(struct device *dev, struct page *page,
> - unsigned long offset, size_t size,
> - enum dma_data_direction dir)
> -{
> - unsigned long paddr = page_to_phys(page) + offset;
> - return dma_map_single(dev, (void *)paddr, size, dir);
> -}
> -
> -static inline void
> -dma_unmap_page(struct device *dev, dma_addr_t dma_handle,
> - size_t size, enum dma_data_direction dir)
> -{
> -}
> -
> -static inline int
> -dma_map_sg(struct device *dev, struct scatterlist *sg,
> - int nents, enum dma_data_direction dir)
> -{
> - struct scatterlist *s;
> - int i;
> -
> - for_each_sg(sg, s, nents, i)
> - s->dma_address = dma_map_page(dev, sg_page(s), s->offset,
> - s->length, dir);
> -
> - return nents;
> -}
> -
> -static inline void
> -dma_unmap_sg(struct device *dev, struct scatterlist *sg,
> - int nents, enum dma_data_direction dir)
> -{
> - struct scatterlist *s;
> - int i;
> -
> - for_each_sg(sg, s, nents, i)
> - dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
> -}
> -
> -static inline void
> -dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
> - size_t size, enum dma_data_direction dir)
> -{
> - _dma_cache_sync(dma_handle, size, DMA_FROM_DEVICE);
> -}
> -
> -static inline void
> -dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
> - size_t size, enum dma_data_direction dir)
> -{
> - _dma_cache_sync(dma_handle, size, DMA_TO_DEVICE);
> -}
> -
> -static inline void
> -dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
> - unsigned long offset, size_t size,
> - enum dma_data_direction direction)
> -{
> - _dma_cache_sync(dma_handle + offset, size, DMA_FROM_DEVICE);
> -}
> -
> -static inline void
> -dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
> - unsigned long offset, size_t size,
> - enum dma_data_direction direction)
> -{
> - _dma_cache_sync(dma_handle + offset, size, DMA_TO_DEVICE);
> -}
> -
> -static inline void
> -dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sglist, int nelems,
> - enum dma_data_direction dir)
> +static inline struct dma_map_ops *get_dma_ops(struct device *dev)
> {
> - int i;
> - struct scatterlist *sg;
> -
> - for_each_sg(sglist, sg, nelems, i)
> - _dma_cache_sync((unsigned int)sg_virt(sg), sg->length, dir);
> -}
> -
> -static inline void
> -dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist,
> - int nelems, enum dma_data_direction dir)
> -{
> - int i;
> - struct scatterlist *sg;
> -
> - for_each_sg(sglist, sg, nelems, i)
> - _dma_cache_sync((unsigned int)sg_virt(sg), sg->length, dir);
> -}
> -
> -static inline int dma_supported(struct device *dev, u64 dma_mask)
> -{
> - /* Support 32 bit DMA mask exclusively */
> - return dma_mask == DMA_BIT_MASK(32);
> + return &arc_dma_ops;
> }
>
> -static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
> -{
> - return 0;
> -}
> -
> -static inline int dma_set_mask(struct device *dev, u64 dma_mask)
> -{
> - if (!dev->dma_mask || !dma_supported(dev, dma_mask))
> - return -EIO;
> -
> - *dev->dma_mask = dma_mask;
> -
> - return 0;
> -}
> +#include <asm-generic/dma-mapping-common.h>
>
> #endif
> diff -puN arch/arc/mm/dma.c~arc-convert-to-dma_map_ops arch/arc/mm/dma.c
> --- a/arch/arc/mm/dma.c~arc-convert-to-dma_map_ops
> +++ a/arch/arc/mm/dma.c
> @@ -17,18 +17,14 @@
> */
>
> #include <linux/dma-mapping.h>
> -#include <linux/dma-debug.h>
> -#include <linux/export.h>
> #include <asm/cache.h>
> #include <asm/cacheflush.h>
>
> -/*
> - * Helpers for Coherent DMA API.
> - */
> -void *dma_alloc_noncoherent(struct device *dev, size_t size,
> - dma_addr_t *dma_handle, gfp_t gfp)
> +
> +static void *arc_dma_alloc(struct device *dev, size_t size,
> + dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
> {
> - void *paddr;
> + void *paddr, *kvaddr;
>
> /* This is linear addr (0x8000_0000 based) */
> paddr = alloc_pages_exact(size, gfp);
> @@ -38,22 +34,6 @@ void *dma_alloc_noncoherent(struct devic
> /* This is bus address, platform dependent */
> *dma_handle = (dma_addr_t)paddr;
>
> - return paddr;
> -}
> -EXPORT_SYMBOL(dma_alloc_noncoherent);
> -
> -void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
> - dma_addr_t dma_handle)
> -{
> - free_pages_exact((void *)dma_handle, size);
> -}
> -EXPORT_SYMBOL(dma_free_noncoherent);
> -
> -void *dma_alloc_coherent(struct device *dev, size_t size,
> - dma_addr_t *dma_handle, gfp_t gfp)
> -{
> - void *paddr, *kvaddr;
> -
> /*
> * IOC relies on all data (even coherent DMA data) being in cache
> * Thus allocate normal cached memory
> @@ -65,22 +45,15 @@ void *dma_alloc_coherent(struct device *
> * -For coherent data, Read/Write to buffers terminate early in cache
> * (vs. always going to memory - thus are faster)
> */
> - if (is_isa_arcv2() && ioc_exists)
> - return dma_alloc_noncoherent(dev, size, dma_handle, gfp);
> -
> - /* This is linear addr (0x8000_0000 based) */
> - paddr = alloc_pages_exact(size, gfp);
> - if (!paddr)
> - return NULL;
> + if ((is_isa_arcv2() && ioc_exists) ||
> + dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs)
> + return paddr;
>
> /* This is kernel Virtual address (0x7000_0000 based) */
> kvaddr = ioremap_nocache((unsigned long)paddr, size);
> if (kvaddr == NULL)
> return NULL;
>
> - /* This is bus address, platform dependent */
> - *dma_handle = (dma_addr_t)paddr;
> -
> /*
> * Evict any existing L1 and/or L2 lines for the backing page
> * in case it was used earlier as a normal "cached" page.
> @@ -95,26 +68,110 @@ void *dma_alloc_coherent(struct device *
>
> return kvaddr;
> }
> -EXPORT_SYMBOL(dma_alloc_coherent);
>
> -void dma_free_coherent(struct device *dev, size_t size, void *kvaddr,
> - dma_addr_t dma_handle)
> +static void arc_dma_free(struct device *dev, size_t size, void *vaddr,
> + dma_addr_t dma_handle, struct dma_attrs *attrs)
> {
> - if (is_isa_arcv2() && ioc_exists)
> - return dma_free_noncoherent(dev, size, kvaddr, dma_handle);
> -
> - iounmap((void __force __iomem *)kvaddr);
> + if (!(is_isa_arcv2() && ioc_exists) ||
> + dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs))
> + iounmap((void __force __iomem *)kvaddr);
>
> free_pages_exact((void *)dma_handle, size);
> }
> -EXPORT_SYMBOL(dma_free_coherent);
>
> /*
> - * Helper for streaming DMA...
> + * streaming DMA Mapping API...
> + * CPU accesses page via normal paddr, thus needs to explicitly made
> + * consistent before each use
> */
> -void __arc_dma_cache_sync(unsigned long paddr, size_t size,
> - enum dma_data_direction dir)
> +static void _dma_cache_sync(unsigned long paddr, size_t size,
> + enum dma_data_direction dir)
> +{
> + switch (dir) {
> + case DMA_FROM_DEVICE:
> + dma_cache_inv(paddr, size);
> + break;
> + case DMA_TO_DEVICE:
> + dma_cache_wback(paddr, size);
> + break;
> + case DMA_BIDIRECTIONAL:
> + dma_cache_wback_inv(paddr, size);
> + break;
> + default:
> + pr_err("Invalid DMA dir [%d] for OP @ %lx\n", dir, paddr);
> + }
> +}
> +
> +static dma_addr_t arc_dma_map_page(struct device *dev, struct page *page,
> + unsigned long offset, size_t size, enum dma_data_direction dir,
> + struct dma_attrs *attrs)
> +{
> + unsigned long paddr = page_to_phys(page) + offset;
> + return dma_map_single(dev, (void *)paddr, size, dir);
> +}
> +
> +static int arc_dma_map_sg(struct device *dev, struct scatterlist *sg,
> + int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
> +{
> + struct scatterlist *s;
> + int i;
> +
> + for_each_sg(sg, s, nents, i)
> + s->dma_address = dma_map_page(dev, sg_page(s), s->offset,
> + s->length, dir);
> +
> + return nents;
> +}
> +
> +static void arc_dma_sync_single_for_cpu(struct device *dev,
> + dma_addr_t dma_handle, size_t size, enum dma_data_direction dir)
> +{
> + _dma_cache_sync(dma_handle, size, DMA_FROM_DEVICE);
> +}
> +
> +static void arc_dma_sync_single_for_device(struct device *dev,
> + dma_addr_t dma_handle, size_t size, enum dma_data_direction dir)
> {
> - __inline_dma_cache_sync(paddr, size, dir);
> + _dma_cache_sync(dma_handle, size, DMA_TO_DEVICE);
> }
> -EXPORT_SYMBOL(__arc_dma_cache_sync);
> +
> +static void arm_dma_sync_sg_for_cpu(struct device *dev,
> + struct scatterlist *sglist, int nelems,
> + enum dma_data_direction dir)
> +{
> + int i;
> + struct scatterlist *sg;
> +
> + for_each_sg(sglist, sg, nelems, i)
> + _dma_cache_sync((unsigned int)sg_virt(sg), sg->length, dir);
> +}
> +
> +static void arc_dma_sync_sg_for_device(struct device *dev,
> + struct scatterlist *sglist, int nelems,
> + enum dma_data_direction dir)
> +{
> + int i;
> + struct scatterlist *sg;
> +
> + for_each_sg(sglist, sg, nelems, i)
> + _dma_cache_sync((unsigned int)sg_virt(sg), sg->length, dir);
> +}
> +
> +static int arc_dma_supported(struct device *dev, u64 dma_mask)
> +{
> + /* Support 32 bit DMA mask exclusively */
> + return dma_mask == DMA_BIT_MASK(32);
> +}
> +
> +struct dma_map_ops arc_dma_ops = {
> + .alloc = arc_dma_alloc,
> + .free = arc_dma_free,
> + .map_page = arc_dma_map_page,
> + .map_sg = arc_dma_map_sg,
> + .sync_single_for_device = arc_dma_sync_single_for_device,
> + .sync_single_for_cpu = arc_dma_sync_single_for_cpu,
> + .sync_sg_for_cpu = arc_dma_sync_sg_for_cpu,
> + .sync_sg_for_dev = arc_dma_sync_sg_for_device,
> + .dma_supported = arc_dma_supported,
> +};
> +EXPORT_SYMBOL(arc_dma_ops);
> _
>
> Patches currently in -mm which might be from hch@xxxxxx are
>
> dma-mapping-make-the-generic-coherent-dma-mmap-implementation-optional.patch
> arc-convert-to-dma_map_ops.patch
> avr32-convert-to-dma_map_ops.patch
> blackfin-convert-to-dma_map_ops.patch
> c6x-convert-to-dma_map_ops.patch
> cris-convert-to-dma_map_ops.patch
> nios2-convert-to-dma_map_ops.patch
> frv-convert-to-dma_map_ops.patch
> parisc-convert-to-dma_map_ops.patch
> mn10300-convert-to-dma_map_ops.patch
> m68k-convert-to-dma_map_ops.patch
> metag-convert-to-dma_map_ops.patch
> sparc-use-generic-dma_set_mask.patch
> tile-uninline-dma_set_mask.patch
> dma-mapping-always-provide-the-dma_map_ops-based-implementation.patch
> dma-mapping-remove-asm-generic-dma-coherenth.patch

Hi Christoph,

This patch in linux-next breaks ARC build.

Below is fixup patch which u can probably fold into your tree
------------>
>From d924a26542660cd1ac68f8f86f8b646835ef5179 Mon Sep 17 00:00:00 2001
From: Vineet Gupta <vgupta@xxxxxxxxxxxx>
Date: Tue, 24 Nov 2015 09:46:05 +0530
Subject: [PATCH] arc: fix wreakage of conversion to dma_map_ops

Obviously the initial patch was not build tested.

Reported-by: Anton Kolesov <akolesov@xxxxxxxxxxxx>
Signed-off-by: Vineet Gupta <vgupta@xxxxxxxxxxxx>
---
arch/arc/mm/dma.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arc/mm/dma.c b/arch/arc/mm/dma.c
index da289cb30ca5..695029f41a48 100644
--- a/arch/arc/mm/dma.c
+++ b/arch/arc/mm/dma.c
@@ -46,7 +46,7 @@ static void *arc_dma_alloc(struct device *dev, size_t size,
* (vs. always going to memory - thus are faster)
*/
if ((is_isa_arcv2() && ioc_exists) ||
- dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs)
+ dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs))
return paddr;

/* This is kernel Virtual address (0x7000_0000 based) */
@@ -74,7 +74,7 @@ static void arc_dma_free(struct device *dev, size_t size, void
*vaddr,
{
if (!(is_isa_arcv2() && ioc_exists) ||
dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs))
- iounmap((void __force __iomem *)kvaddr);
+ iounmap((void __force __iomem *)vaddr);

free_pages_exact((void *)dma_handle, size);
}
@@ -135,7 +135,7 @@ static void arc_dma_sync_single_for_device(struct device *dev,
_dma_cache_sync(dma_handle, size, DMA_TO_DEVICE);
}

-static void arm_dma_sync_sg_for_cpu(struct device *dev,
+static void arc_dma_sync_sg_for_cpu(struct device *dev,
struct scatterlist *sglist, int nelems,
enum dma_data_direction dir)
{
@@ -171,7 +171,7 @@ struct dma_map_ops arc_dma_ops = {
.sync_single_for_device = arc_dma_sync_single_for_device,
.sync_single_for_cpu = arc_dma_sync_single_for_cpu,
.sync_sg_for_cpu = arc_dma_sync_sg_for_cpu,
- .sync_sg_for_dev = arc_dma_sync_sg_for_device,
+ .sync_sg_for_device = arc_dma_sync_sg_for_device,
.dma_supported = arc_dma_supported,
};
EXPORT_SYMBOL(arc_dma_ops);
--
1.9.1


From d924a26542660cd1ac68f8f86f8b646835ef5179 Mon Sep 17 00:00:00 2001
From: Vineet Gupta <vgupta@xxxxxxxxxxxx>
Date: Tue, 24 Nov 2015 09:46:05 +0530
Subject: [PATCH] arc: fix wreakage of conversion to dma_map_ops

Obviously the initial patch was not build tested.

Reported-by: Anton Kolesov <akolesov@xxxxxxxxxxxx>
Signed-off-by: Vineet Gupta <vgupta@xxxxxxxxxxxx>
---
arch/arc/mm/dma.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arc/mm/dma.c b/arch/arc/mm/dma.c
index da289cb30ca5..695029f41a48 100644
--- a/arch/arc/mm/dma.c
+++ b/arch/arc/mm/dma.c
@@ -46,7 +46,7 @@ static void *arc_dma_alloc(struct device *dev, size_t size,
* (vs. always going to memory - thus are faster)
*/
if ((is_isa_arcv2() && ioc_exists) ||
- dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs)
+ dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs))
return paddr;

/* This is kernel Virtual address (0x7000_0000 based) */
@@ -74,7 +74,7 @@ static void arc_dma_free(struct device *dev, size_t size, void *vaddr,
{
if (!(is_isa_arcv2() && ioc_exists) ||
dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs))
- iounmap((void __force __iomem *)kvaddr);
+ iounmap((void __force __iomem *)vaddr);

free_pages_exact((void *)dma_handle, size);
}
@@ -135,7 +135,7 @@ static void arc_dma_sync_single_for_device(struct device *dev,
_dma_cache_sync(dma_handle, size, DMA_TO_DEVICE);
}

-static void arm_dma_sync_sg_for_cpu(struct device *dev,
+static void arc_dma_sync_sg_for_cpu(struct device *dev,
struct scatterlist *sglist, int nelems,
enum dma_data_direction dir)
{
@@ -171,7 +171,7 @@ struct dma_map_ops arc_dma_ops = {
.sync_single_for_device = arc_dma_sync_single_for_device,
.sync_single_for_cpu = arc_dma_sync_single_for_cpu,
.sync_sg_for_cpu = arc_dma_sync_sg_for_cpu,
- .sync_sg_for_dev = arc_dma_sync_sg_for_device,
+ .sync_sg_for_device = arc_dma_sync_sg_for_device,
.dma_supported = arc_dma_supported,
};
EXPORT_SYMBOL(arc_dma_ops);
--
1.9.1