Commit f3ecc0ff authored by Christoph Hellwig's avatar Christoph Hellwig

dma-mapping: move the dma_coherent flag to struct device

Various architectures support both coherent and non-coherent dma on a
per-device basis.  Move the dma_noncoherent flag from the mips archdata
field to struct device proper to prepare the infrastructure for reuse on
other architectures.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Acked-by: default avatarPaul Burton <paul.burton@mips.com>
Acked-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 5748e1b3
...@@ -1106,6 +1106,7 @@ config ARCH_SUPPORTS_UPROBES ...@@ -1106,6 +1106,7 @@ config ARCH_SUPPORTS_UPROBES
bool bool
config DMA_MAYBE_COHERENT config DMA_MAYBE_COHERENT
select ARCH_HAS_DMA_COHERENCE_H
select DMA_NONCOHERENT select DMA_NONCOHERENT
bool bool
......
# MIPS headers # MIPS headers
generic-(CONFIG_GENERIC_CSUM) += checksum.h generic-(CONFIG_GENERIC_CSUM) += checksum.h
generic-y += current.h generic-y += current.h
generic-y += device.h
generic-y += dma-contiguous.h generic-y += dma-contiguous.h
generic-y += emergency-restart.h generic-y += emergency-restart.h
generic-y += export.h generic-y += export.h
......
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#ifndef _ASM_MIPS_DEVICE_H
#define _ASM_MIPS_DEVICE_H
struct dev_archdata {
#ifdef CONFIG_DMA_PERDEV_COHERENT
/* Non-zero if DMA is coherent with CPU caches */
bool dma_coherent;
#endif
};
struct pdev_archdata {
};
#endif /* _ASM_MIPS_DEVICE_H*/
...@@ -20,6 +20,12 @@ enum coherent_io_user_state { ...@@ -20,6 +20,12 @@ enum coherent_io_user_state {
#elif defined(CONFIG_DMA_MAYBE_COHERENT) #elif defined(CONFIG_DMA_MAYBE_COHERENT)
extern enum coherent_io_user_state coherentio; extern enum coherent_io_user_state coherentio;
extern int hw_coherentio; extern int hw_coherentio;
static inline bool dev_is_dma_coherent(struct device *dev)
{
return coherentio == IO_COHERENCE_ENABLED ||
(coherentio == IO_COHERENCE_DEFAULT && hw_coherentio);
}
#else #else
#ifdef CONFIG_DMA_NONCOHERENT #ifdef CONFIG_DMA_NONCOHERENT
#define coherentio IO_COHERENCE_DISABLED #define coherentio IO_COHERENCE_DISABLED
......
...@@ -25,7 +25,7 @@ static inline void arch_setup_dma_ops(struct device *dev, u64 dma_base, ...@@ -25,7 +25,7 @@ static inline void arch_setup_dma_ops(struct device *dev, u64 dma_base,
bool coherent) bool coherent)
{ {
#ifdef CONFIG_DMA_PERDEV_COHERENT #ifdef CONFIG_DMA_PERDEV_COHERENT
dev->archdata.dma_coherent = coherent; dev->dma_coherent = coherent;
#endif #endif
} }
......
...@@ -14,26 +14,6 @@ ...@@ -14,26 +14,6 @@
#include <asm/dma-coherence.h> #include <asm/dma-coherence.h>
#include <asm/io.h> #include <asm/io.h>
#ifdef CONFIG_DMA_PERDEV_COHERENT
static inline int dev_is_coherent(struct device *dev)
{
return dev->archdata.dma_coherent;
}
#else
static inline int dev_is_coherent(struct device *dev)
{
switch (coherentio) {
default:
case IO_COHERENCE_DEFAULT:
return hw_coherentio;
case IO_COHERENCE_ENABLED:
return 1;
case IO_COHERENCE_DISABLED:
return 0;
}
}
#endif /* CONFIG_DMA_PERDEV_COHERENT */
/* /*
* The affected CPUs below in 'cpu_needs_post_dma_flush()' can speculatively * The affected CPUs below in 'cpu_needs_post_dma_flush()' can speculatively
* fill random cachelines with stale data at any time, requiring an extra * fill random cachelines with stale data at any time, requiring an extra
...@@ -49,7 +29,7 @@ static inline int dev_is_coherent(struct device *dev) ...@@ -49,7 +29,7 @@ static inline int dev_is_coherent(struct device *dev)
*/ */
static inline bool cpu_needs_post_dma_flush(struct device *dev) static inline bool cpu_needs_post_dma_flush(struct device *dev)
{ {
if (dev_is_coherent(dev)) if (dev_is_dma_coherent(dev))
return false; return false;
switch (boot_cpu_type()) { switch (boot_cpu_type()) {
...@@ -76,7 +56,7 @@ void *arch_dma_alloc(struct device *dev, size_t size, ...@@ -76,7 +56,7 @@ void *arch_dma_alloc(struct device *dev, size_t size,
if (!ret) if (!ret)
return NULL; return NULL;
if (!dev_is_coherent(dev) && !(attrs & DMA_ATTR_NON_CONSISTENT)) { if (!dev_is_dma_coherent(dev) && !(attrs & DMA_ATTR_NON_CONSISTENT)) {
dma_cache_wback_inv((unsigned long) ret, size); dma_cache_wback_inv((unsigned long) ret, size);
ret = (void *)UNCAC_ADDR(ret); ret = (void *)UNCAC_ADDR(ret);
} }
...@@ -87,7 +67,7 @@ void *arch_dma_alloc(struct device *dev, size_t size, ...@@ -87,7 +67,7 @@ void *arch_dma_alloc(struct device *dev, size_t size,
void arch_dma_free(struct device *dev, size_t size, void *cpu_addr, void arch_dma_free(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_addr, unsigned long attrs) dma_addr_t dma_addr, unsigned long attrs)
{ {
if (!(attrs & DMA_ATTR_NON_CONSISTENT) && !dev_is_coherent(dev)) if (!(attrs & DMA_ATTR_NON_CONSISTENT) && !dev_is_dma_coherent(dev))
cpu_addr = (void *)CAC_ADDR((unsigned long)cpu_addr); cpu_addr = (void *)CAC_ADDR((unsigned long)cpu_addr);
dma_direct_free(dev, size, cpu_addr, dma_addr, attrs); dma_direct_free(dev, size, cpu_addr, dma_addr, attrs);
} }
...@@ -103,7 +83,7 @@ int arch_dma_mmap(struct device *dev, struct vm_area_struct *vma, ...@@ -103,7 +83,7 @@ int arch_dma_mmap(struct device *dev, struct vm_area_struct *vma,
unsigned long pfn; unsigned long pfn;
int ret = -ENXIO; int ret = -ENXIO;
if (!dev_is_coherent(dev)) if (!dev_is_dma_coherent(dev))
addr = CAC_ADDR(addr); addr = CAC_ADDR(addr);
pfn = page_to_pfn(virt_to_page((void *)addr)); pfn = page_to_pfn(virt_to_page((void *)addr));
...@@ -187,7 +167,7 @@ static inline void dma_sync_phys(phys_addr_t paddr, size_t size, ...@@ -187,7 +167,7 @@ static inline void dma_sync_phys(phys_addr_t paddr, size_t size,
void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr, void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
size_t size, enum dma_data_direction dir) size_t size, enum dma_data_direction dir)
{ {
if (!dev_is_coherent(dev)) if (!dev_is_dma_coherent(dev))
dma_sync_phys(paddr, size, dir); dma_sync_phys(paddr, size, dir);
} }
...@@ -203,6 +183,6 @@ void arch_dma_cache_sync(struct device *dev, void *vaddr, size_t size, ...@@ -203,6 +183,6 @@ void arch_dma_cache_sync(struct device *dev, void *vaddr, size_t size,
{ {
BUG_ON(direction == DMA_NONE); BUG_ON(direction == DMA_NONE);
if (!dev_is_coherent(dev)) if (!dev_is_dma_coherent(dev))
dma_sync_virt(vaddr, size, direction); dma_sync_virt(vaddr, size, direction);
} }
...@@ -927,6 +927,8 @@ struct dev_links_info { ...@@ -927,6 +927,8 @@ struct dev_links_info {
* @offline: Set after successful invocation of bus type's .offline(). * @offline: Set after successful invocation of bus type's .offline().
* @of_node_reused: Set if the device-tree node is shared with an ancestor * @of_node_reused: Set if the device-tree node is shared with an ancestor
* device. * device.
* @dma_coherent: this particular device is dma coherent, even if the
* architecture supports non-coherent devices.
* *
* At the lowest level, every device in a Linux system is represented by an * At the lowest level, every device in a Linux system is represented by an
* instance of struct device. The device structure contains the information * instance of struct device. The device structure contains the information
...@@ -1016,6 +1018,11 @@ struct device { ...@@ -1016,6 +1018,11 @@ struct device {
bool offline_disabled:1; bool offline_disabled:1;
bool offline:1; bool offline:1;
bool of_node_reused:1; bool of_node_reused:1;
#if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \
defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \
defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL)
bool dma_coherent:1;
#endif
}; };
static inline struct device *kobj_to_dev(struct kobject *kobj) static inline struct device *kobj_to_dev(struct kobject *kobj)
......
...@@ -4,6 +4,22 @@ ...@@ -4,6 +4,22 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#ifdef CONFIG_ARCH_HAS_DMA_COHERENCE_H
#include <asm/dma-coherence.h>
#elif defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \
defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \
defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL)
static inline bool dev_is_dma_coherent(struct device *dev)
{
return dev->dma_coherent;
}
#else
static inline bool dev_is_dma_coherent(struct device *dev)
{
return true;
}
#endif /* CONFIG_ARCH_HAS_DMA_COHERENCE_H */
void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
gfp_t gfp, unsigned long attrs); gfp_t gfp, unsigned long attrs);
void arch_dma_free(struct device *dev, size_t size, void *cpu_addr, void arch_dma_free(struct device *dev, size_t size, void *cpu_addr,
......
...@@ -13,6 +13,9 @@ config NEED_DMA_MAP_STATE ...@@ -13,6 +13,9 @@ config NEED_DMA_MAP_STATE
config ARCH_DMA_ADDR_T_64BIT config ARCH_DMA_ADDR_T_64BIT
def_bool 64BIT || PHYS_ADDR_T_64BIT def_bool 64BIT || PHYS_ADDR_T_64BIT
config ARCH_HAS_DMA_COHERENCE_H
bool
config HAVE_GENERIC_DMA_COHERENT config HAVE_GENERIC_DMA_COHERENT
bool bool
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment