Skip to content

Commit

Permalink
dma-mapping: consolidate dma_{alloc,free}_noncoherent
Browse files Browse the repository at this point in the history
Most architectures do not support non-coherent allocations and either
define dma_{alloc,free}_noncoherent to their coherent versions or stub
them out.

Openrisc uses dma_{alloc,free}_attrs to implement them, and only Mips
implements them directly.

This patch moves the Openrisc version to common code, and handles the
DMA_ATTR_NON_CONSISTENT case in the mips dma_map_ops instance.

Note that actual non-coherent allocations require a dma_cache_sync
implementation, so if non-coherent allocations didn't work on
an architecture before this patch they still won't work after it.

[[email protected]: fix xtensa]
Signed-off-by: Christoph Hellwig <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: Russell King <[email protected]>
Cc: Catalin Marinas <[email protected]>
Cc: Will Deacon <[email protected]>
Cc: Yoshinori Sato <[email protected]>
Cc: Michal Simek <[email protected]>
Cc: Jonas Bonn <[email protected]>
Cc: Chris Metcalf <[email protected]>
Cc: Guan Xuetao <[email protected]>
Cc: Ralf Baechle <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: Andy Shevchenko <[email protected]>
Signed-off-by: Max Filippov <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Christoph Hellwig authored and torvalds committed Sep 10, 2015
1 parent 6894258 commit 1e89375
Show file tree
Hide file tree
Showing 19 changed files with 39 additions and 99 deletions.
3 changes: 0 additions & 3 deletions arch/alpha/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
return get_dma_ops(dev)->set_dma_mask(dev, mask);
}

#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)

#define dma_cache_sync(dev, va, size, dir) ((void)0)

#endif /* _ALPHA_DMA_MAPPING_H */
21 changes: 6 additions & 15 deletions arch/arm/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
dev->archdata.dma_ops = ops;
}

/*
* Note that while the generic code provides dummy dma_{alloc,free}_noncoherent
* implementations, we don't provide a dma_cache_sync function so drivers using
* this API are highlighted with build warnings.
*/

#include <asm-generic/dma-mapping-common.h>

static inline int dma_set_mask(struct device *dev, u64 mask)
Expand Down Expand Up @@ -175,21 +181,6 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
return dma_addr == DMA_ERROR_CODE;
}

/*
* Dummy noncoherent implementation. We don't provide a dma_cache_sync
* function so drivers using this API are highlighted with build warnings.
*/
static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
dma_addr_t *handle, gfp_t gfp)
{
return NULL;
}

static inline void dma_free_noncoherent(struct device *dev, size_t size,
void *cpu_addr, dma_addr_t handle)
{
}

extern int dma_supported(struct device *dev, u64 mask);

extern int arm_dma_set_mask(struct device *dev, u64 dma_mask);
Expand Down
14 changes: 0 additions & 14 deletions arch/arm64/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,19 +118,5 @@ static inline void dma_mark_clean(void *addr, size_t size)
{
}

/*
* There is no dma_cache_sync() implementation, so just return NULL here.
*/
static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
dma_addr_t *handle, gfp_t flags)
{
return NULL;
}

static inline void dma_free_noncoherent(struct device *dev, size_t size,
void *cpu_addr, dma_addr_t handle)
{
}

#endif /* __KERNEL__ */
#endif /* __ASM_DMA_MAPPING_H */
3 changes: 0 additions & 3 deletions arch/h8300/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
return 0;
}

#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)

static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
return 0;
Expand Down
3 changes: 0 additions & 3 deletions arch/hexagon/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ extern int bad_dma_address;

extern struct dma_map_ops *dma_ops;

#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)

static inline struct dma_map_ops *get_dma_ops(struct device *dev)
{
if (unlikely(dev == NULL))
Expand Down
3 changes: 0 additions & 3 deletions arch/ia64/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ extern void machvec_dma_sync_single(struct device *, dma_addr_t, size_t,
extern void machvec_dma_sync_sg(struct device *, struct scatterlist *, int,
enum dma_data_direction);

#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)

#define get_dma_ops(dev) platform_dma_get_ops(dev)

#include <asm-generic/dma-mapping-common.h>
Expand Down
3 changes: 0 additions & 3 deletions arch/microblaze/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,6 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
return (dma_addr == DMA_ERROR_CODE);
}

#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)

static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction direction)
{
Expand Down
6 changes: 0 additions & 6 deletions arch/mips/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,4 @@ dma_set_mask(struct device *dev, u64 mask)
extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction direction);

void *dma_alloc_noncoherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag);

void dma_free_noncoherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle);

#endif /* _ASM_DMA_MAPPING_H */
20 changes: 15 additions & 5 deletions arch/mips/mm/dma-default.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp)
return gfp | dma_flag;
}

void *dma_alloc_noncoherent(struct device *dev, size_t size,
static void *mips_dma_alloc_noncoherent(struct device *dev, size_t size,
dma_addr_t * dma_handle, gfp_t gfp)
{
void *ret;
Expand All @@ -128,7 +128,6 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size,

return ret;
}
EXPORT_SYMBOL(dma_alloc_noncoherent);

static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t * dma_handle, gfp_t gfp, struct dma_attrs *attrs)
Expand All @@ -137,6 +136,13 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
struct page *page = NULL;
unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;

/*
* XXX: seems like the coherent and non-coherent implementations could
* be consolidated.
*/
if (dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs))
return mips_dma_alloc_noncoherent(dev, size, dma_handle, gfp);

gfp = massage_gfp_flags(dev, gfp);

if (IS_ENABLED(CONFIG_DMA_CMA) && !(gfp & GFP_ATOMIC))
Expand All @@ -161,13 +167,12 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
}


void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle)
static void mips_dma_free_noncoherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL);
free_pages((unsigned long) vaddr, get_order(size));
}
EXPORT_SYMBOL(dma_free_noncoherent);

static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle, struct dma_attrs *attrs)
Expand All @@ -176,6 +181,11 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
struct page *page = NULL;

if (dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs)) {
mips_dma_free_noncoherent(dev, size, vaddr, dma_handle);
return;
}

plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL);

if (!plat_device_is_coherent(dev) && !hw_coherentio)
Expand Down
20 changes: 0 additions & 20 deletions arch/openrisc/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,6 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)

#include <asm-generic/dma-mapping-common.h>

static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
{
struct dma_attrs attrs;

dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);

return dma_alloc_attrs(dev, size, dma_handle, gfp, &attrs);
}

static inline void dma_free_noncoherent(struct device *dev, size_t size,
void *cpu_addr, dma_addr_t dma_handle)
{
struct dma_attrs attrs;

dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);

dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs);
}

static inline int dma_supported(struct device *dev, u64 dma_mask)
{
/* Support 32 bit DMA mask exclusively */
Expand Down
3 changes: 0 additions & 3 deletions arch/powerpc/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,6 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
return daddr - get_dma_offset(dev);
}

#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)

#define ARCH_HAS_DMA_MMAP_COHERENT

static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
Expand Down
3 changes: 0 additions & 3 deletions arch/s390/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
{
}

#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)

#include <asm-generic/dma-mapping-common.h>

static inline int dma_supported(struct device *dev, u64 mask)
Expand Down
3 changes: 0 additions & 3 deletions arch/sh/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction dir);

#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)

static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
struct dma_map_ops *ops = get_dma_ops(dev);
Expand Down
3 changes: 0 additions & 3 deletions arch/sparc/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@

int dma_supported(struct device *dev, u64 mask);

#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)

static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction dir)
{
Expand Down
3 changes: 0 additions & 3 deletions arch/tile/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,6 @@ dma_set_mask(struct device *dev, u64 mask)
return 0;
}

#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
#define dma_free_noncoherent(d, s, v, h) dma_free_attrs(d, s, v, h, NULL)

/*
* dma_alloc_noncoherent() is #defined to return coherent memory,
* so there's no need to do any flushing here.
Expand Down
3 changes: 0 additions & 3 deletions arch/unicore32/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,6 @@ static inline int dma_set_mask(struct device *dev, u64 dma_mask)
return 0;
}

#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)

static inline void dma_cache_sync(struct device *dev, void *vaddr,
size_t size, enum dma_data_direction direction)
{
Expand Down
3 changes: 0 additions & 3 deletions arch/x86/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
return (dma_addr == DMA_ERROR_CODE);
}

#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)

extern int dma_supported(struct device *hwdev, u64 mask);
extern int dma_set_mask(struct device *dev, u64 mask);

Expand Down
3 changes: 0 additions & 3 deletions arch/xtensa/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)

#include <asm-generic/dma-mapping-common.h>

#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
#define dma_free_noncoherent(d, s, v, h) dma_free_attrs(d, s, v, h, NULL)

static inline int
dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
Expand Down
18 changes: 18 additions & 0 deletions include/asm-generic/dma-mapping-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,22 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
return dma_free_attrs(dev, size, cpu_addr, dma_handle, NULL);
}

static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
{
DEFINE_DMA_ATTRS(attrs);

dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);
return dma_alloc_attrs(dev, size, dma_handle, gfp, &attrs);
}

static inline void dma_free_noncoherent(struct device *dev, size_t size,
void *cpu_addr, dma_addr_t dma_handle)
{
DEFINE_DMA_ATTRS(attrs);

dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);
dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs);
}

#endif

0 comments on commit 1e89375

Please sign in to comment.