From d89e2378a97fafdc74cbf997e7c88af75b81610a Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Thu, 12 Oct 2017 16:56:14 +0100 Subject: [PATCH 01/12] drivers: flag buses which demand DMA configuration We do not want the common dma_configure() pathway to apply indiscriminately to all devices, since there are plenty of buses which do not have DMA capability, and if their child devices were used for DMA API calls it would only be indicative of a driver bug. However, there are a number of buses for which DMA is implicitly expected even when not described by firmware - those we whitelist with an automatic opt-in to dma_configure(), assuming that the DMA address space and the physical address space are equivalent if not otherwise specified. Commit 723288836628 ("of: restrict DMA configuration") introduced a short-term fix by comparing explicit bus types, but this approach is far from pretty, doesn't scale well, and fails to cope at all with bus drivers which may be built as modules, like host1x. Let's refine things by making that opt-in a property of the bus type, which neatly addresses those problems and lets the decision of whether firmware description of DMA capability should be optional or mandatory stay internal to the bus drivers themselves. Signed-off-by: Robin Murphy Acked-by: Rob Herring Acked-by: Greg Kroah-Hartman Acked-by: Thierry Reding Signed-off-by: Christoph Hellwig --- drivers/amba/bus.c | 1 + drivers/base/platform.c | 1 + drivers/gpu/host1x/bus.c | 1 + drivers/of/device.c | 8 +------- drivers/pci/pci-driver.c | 1 + include/linux/device.h | 4 ++++ 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index e0f74ddc22b73..594c228d2f021 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -195,6 +195,7 @@ struct bus_type amba_bustype = { .match = amba_match, .uevent = amba_uevent, .pm = &amba_pm, + .force_dma = true, }; static int __init amba_init(void) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 9045c5f3734e8..c203fb90c1a01 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1143,6 +1143,7 @@ struct bus_type platform_bus_type = { .match = platform_match, .uevent = platform_uevent, .pm = &platform_dev_pm_ops, + .force_dma = true, }; EXPORT_SYMBOL_GPL(platform_bus_type); diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c index f9cde03030fd9..ed03b3243195b 100644 --- a/drivers/gpu/host1x/bus.c +++ b/drivers/gpu/host1x/bus.c @@ -320,6 +320,7 @@ struct bus_type host1x_bus_type = { .name = "host1x", .match = host1x_device_match, .pm = &host1x_device_pm_ops, + .force_dma = true, }; static void __host1x_device_del(struct host1x_device *device) diff --git a/drivers/of/device.c b/drivers/of/device.c index 64b710265d390..25bddf9c9fe1c 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -9,9 +9,7 @@ #include #include #include -#include #include -#include #include #include "of_private.h" @@ -101,11 +99,7 @@ int of_dma_configure(struct device *dev, struct device_node *np) * DMA configuration regardless of whether "dma-ranges" is * correctly specified or not. */ - if (!dev_is_pci(dev) && -#ifdef CONFIG_ARM_AMBA - dev->bus != &amba_bustype && -#endif - dev->bus != &platform_bus_type) + if (!dev->bus->force_dma) return ret == -ENODEV ? 0 : ret; dma_addr = offset = 0; diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 11bd267fc1371..38bdb97b6dc64 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -1466,6 +1466,7 @@ struct bus_type pci_bus_type = { .drv_groups = pci_drv_groups, .pm = PCI_PM_OPS_PTR, .num_vf = pci_bus_num_vf, + .force_dma = true, }; EXPORT_SYMBOL(pci_bus_type); diff --git a/include/linux/device.h b/include/linux/device.h index 66fe271c2544d..d60f7701e245f 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -97,6 +97,8 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); * @p: The private data of the driver core, only the driver core can * touch this. * @lock_key: Lock class key for use by the lock validator + * @force_dma: Assume devices on this bus should be set up by dma_configure() + * even if DMA capability is not explicitly described by firmware. * * A bus is a channel between the processor and one or more devices. For the * purposes of the device model, all devices are connected via a bus, even if @@ -135,6 +137,8 @@ struct bus_type { struct subsys_private *p; struct lock_class_key lock_key; + + bool force_dma; }; extern int __must_check bus_register(struct bus_type *bus); From acfef4f126a716018127dcf147be0cc16c304e72 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 13 Jul 2017 16:12:05 +0200 Subject: [PATCH 02/12] floppy: consolidate the dummy fd_cacheflush definition Only mips defines this helper, so remove all the other arch definitions. Signed-off-by: Christoph Hellwig Reviewed-by: Robin Murphy --- arch/alpha/include/asm/floppy.h | 2 -- arch/powerpc/include/asm/floppy.h | 2 -- arch/sparc/include/asm/floppy_32.h | 1 - arch/sparc/include/asm/floppy_64.h | 1 - drivers/block/floppy.c | 4 ++++ 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/alpha/include/asm/floppy.h b/arch/alpha/include/asm/floppy.h index bae97eb19d269..942924756cf21 100644 --- a/arch/alpha/include/asm/floppy.h +++ b/arch/alpha/include/asm/floppy.h @@ -24,7 +24,6 @@ #define fd_set_dma_count(count) set_dma_count(FLOPPY_DMA,count) #define fd_enable_irq() enable_irq(FLOPPY_IRQ) #define fd_disable_irq() disable_irq(FLOPPY_IRQ) -#define fd_cacheflush(addr,size) /* nothing */ #define fd_request_irq() request_irq(FLOPPY_IRQ, floppy_interrupt,\ 0, "floppy", NULL) #define fd_free_irq() free_irq(FLOPPY_IRQ, NULL) @@ -62,7 +61,6 @@ alpha_fd_dma_setup(char *addr, unsigned long size, int mode, int io) prev_dir = dir; fd_clear_dma_ff(); - fd_cacheflush(addr, size); fd_set_dma_mode(mode); set_dma_addr(FLOPPY_DMA, bus_addr); fd_set_dma_count(size); diff --git a/arch/powerpc/include/asm/floppy.h b/arch/powerpc/include/asm/floppy.h index 936a904ae78c6..167c44b588487 100644 --- a/arch/powerpc/include/asm/floppy.h +++ b/arch/powerpc/include/asm/floppy.h @@ -25,7 +25,6 @@ #define fd_get_dma_residue() fd_ops->_get_dma_residue(FLOPPY_DMA) #define fd_enable_irq() enable_irq(FLOPPY_IRQ) #define fd_disable_irq() disable_irq(FLOPPY_IRQ) -#define fd_cacheflush(addr,size) /* nothing */ #define fd_free_irq() free_irq(FLOPPY_IRQ, NULL); #include @@ -152,7 +151,6 @@ static int hard_dma_setup(char *addr, unsigned long size, int mode, int io) prev_dir = dir; fd_clear_dma_ff(); - fd_cacheflush(addr, size); fd_set_dma_mode(mode); set_dma_addr(FLOPPY_DMA, bus_addr); fd_set_dma_count(size); diff --git a/arch/sparc/include/asm/floppy_32.h b/arch/sparc/include/asm/floppy_32.h index 071b83e52f15d..dab58525229e7 100644 --- a/arch/sparc/include/asm/floppy_32.h +++ b/arch/sparc/include/asm/floppy_32.h @@ -70,7 +70,6 @@ static struct sun_floppy_ops sun_fdops; #define fd_set_dma_count(count) sun_fd_set_dma_count(count) #define fd_enable_irq() /* nothing... */ #define fd_disable_irq() /* nothing... */ -#define fd_cacheflush(addr, size) /* nothing... */ #define fd_request_irq() sun_fd_request_irq() #define fd_free_irq() /* nothing... */ #if 0 /* P3: added by Alain, these cause a MMU corruption. 19960524 XXX */ diff --git a/arch/sparc/include/asm/floppy_64.h b/arch/sparc/include/asm/floppy_64.h index 625756406a7ed..a1db35a22c998 100644 --- a/arch/sparc/include/asm/floppy_64.h +++ b/arch/sparc/include/asm/floppy_64.h @@ -72,7 +72,6 @@ static struct sun_floppy_ops sun_fdops; #define fd_set_dma_addr(addr) sun_fdops.fd_set_dma_addr(addr) #define fd_set_dma_count(count) sun_fdops.fd_set_dma_count(count) #define get_dma_residue(x) sun_fdops.get_dma_residue() -#define fd_cacheflush(addr, size) /* nothing... */ #define fd_request_irq() sun_fdops.fd_request_irq() #define fd_free_irq() sun_fdops.fd_free_irq() #define fd_eject(drive) sun_fdops.fd_eject(drive) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 60c086a536094..a54183935aa1a 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -275,6 +275,10 @@ static int set_next_request(void); #define fd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL, get_order(size)) #endif +#ifndef fd_cacheflush +#define fd_cacheflush(addr, size) /* nothing... */ +#endif + static inline void fallback_on_nodma_alloc(char **addr, size_t l) { #ifdef FLOPPY_CAN_FALLBACK_ON_NODMA From 95e499fc7fe9c58efedc079634582164de6bbd90 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 27 Aug 2017 10:06:22 +0200 Subject: [PATCH 03/12] x86: make dma_cache_sync a no-op x86 does not implement DMA_ATTR_NON_CONSISTENT allocations, so it doesn't make any sense to do any work in dma_cache_sync given that it must be a no-op when dma_alloc_attrs returns coherent memory. Signed-off-by: Christoph Hellwig Reviewed-by: Thomas Gleixner Reviewed-by: Robin Murphy --- arch/x86/include/asm/dma-mapping.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h index 1387dafdba2d2..c6d3367be9168 100644 --- a/arch/x86/include/asm/dma-mapping.h +++ b/arch/x86/include/asm/dma-mapping.h @@ -71,7 +71,6 @@ static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction dir) { - flush_write_buffers(); } static inline unsigned long dma_alloc_coherent_mask(struct device *dev, From 9d254b8e409e90db21384974f4725bff369c333f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 27 Aug 2017 09:59:32 +0200 Subject: [PATCH 04/12] frv: make dma_cache_sync a no-op frv does not implement DMA_ATTR_NON_CONSISTENT allocations, so it doesn't make any sense to do any work in dma_cache_sync given that it must be a no-op when dma_alloc_attrs returns coherent memory. Signed-off-by: Christoph Hellwig Reviewed-by: Robin Murphy --- arch/frv/include/asm/dma-mapping.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/frv/include/asm/dma-mapping.h b/arch/frv/include/asm/dma-mapping.h index 354900917585a..da0e5c9744c4c 100644 --- a/arch/frv/include/asm/dma-mapping.h +++ b/arch/frv/include/asm/dma-mapping.h @@ -18,7 +18,6 @@ static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { - flush_write_buffers(); } #endif /* _ASM_DMA_MAPPING_H */ From 562437a81aa48e54231896ad36d46439278df4b3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 27 Aug 2017 10:07:04 +0200 Subject: [PATCH 05/12] ia64: make dma_cache_sync a no-op ia64 does not implement DMA_ATTR_NON_CONSISTENT allocations, so it doesn't make any sense to do any work in dma_cache_sync given that it must be a no-op when dma_alloc_attrs returns coherent memory. Signed-off-by: Christoph Hellwig Reviewed-by: Robin Murphy --- arch/ia64/include/asm/dma-mapping.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h index 3ce5ab4339f31..99dfc1aa9d3ce 100644 --- a/arch/ia64/include/asm/dma-mapping.h +++ b/arch/ia64/include/asm/dma-mapping.h @@ -48,11 +48,6 @@ static inline void dma_cache_sync (struct device *dev, void *vaddr, size_t size, enum dma_data_direction dir) { - /* - * IA-64 is cache-coherent, so this is mostly a no-op. However, we do need to - * ensure that dma_cache_sync() enforces order, hence the mb(). - */ - mb(); } #endif /* _ASM_IA64_DMA_MAPPING_H */ From 64dc8700c01d94c46fd26b38b7e7d2891934a33b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 27 Aug 2017 10:12:57 +0200 Subject: [PATCH 06/12] microblaze: make dma_cache_sync a no-op microblaze does not implement DMA_ATTR_NON_CONSISTENT allocations, so it doesn't make any sense to do any work in dma_cache_sync given that it must be a no-op when dma_alloc_attrs returns coherent memory. This also allows moving __dma_sync out of the microblaze asm/dma-mapping.h and thus greatly reduce the amount of includes there. Signed-off-by: Christoph Hellwig Reviewed-by: Robin Murphy --- arch/microblaze/include/asm/dma-mapping.h | 34 ----------------------- arch/microblaze/kernel/dma.c | 17 ++++++++++++ 2 files changed, 17 insertions(+), 34 deletions(-) diff --git a/arch/microblaze/include/asm/dma-mapping.h b/arch/microblaze/include/asm/dma-mapping.h index e15cd2f76e23a..ad448e4aedb6b 100644 --- a/arch/microblaze/include/asm/dma-mapping.h +++ b/arch/microblaze/include/asm/dma-mapping.h @@ -15,22 +15,6 @@ #ifndef _ASM_MICROBLAZE_DMA_MAPPING_H #define _ASM_MICROBLAZE_DMA_MAPPING_H -/* - * See Documentation/DMA-API-HOWTO.txt and - * Documentation/DMA-API.txt for documentation. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define __dma_alloc_coherent(dev, gfp, size, handle) NULL -#define __dma_free_coherent(size, addr) ((void)0) - /* * Available generic sets of operations */ @@ -41,27 +25,9 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return &dma_direct_ops; } -static inline void __dma_sync(unsigned long paddr, - size_t size, enum dma_data_direction direction) -{ - switch (direction) { - case DMA_TO_DEVICE: - case DMA_BIDIRECTIONAL: - flush_dcache_range(paddr, paddr + size); - break; - case DMA_FROM_DEVICE: - invalidate_dcache_range(paddr, paddr + size); - break; - default: - BUG(); - } -} - static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { - BUG_ON(direction == DMA_NONE); - __dma_sync(virt_to_phys(vaddr), size, (int)direction); } #endif /* _ASM_MICROBLAZE_DMA_MAPPING_H */ diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c index 94700c5270a91..e52b684f8ea20 100644 --- a/arch/microblaze/kernel/dma.c +++ b/arch/microblaze/kernel/dma.c @@ -12,6 +12,7 @@ #include #include #include +#include #define NOT_COHERENT_CACHE @@ -51,6 +52,22 @@ static void dma_direct_free_coherent(struct device *dev, size_t size, #endif } +static inline void __dma_sync(unsigned long paddr, + size_t size, enum dma_data_direction direction) +{ + switch (direction) { + case DMA_TO_DEVICE: + case DMA_BIDIRECTIONAL: + flush_dcache_range(paddr, paddr + size); + break; + case DMA_FROM_DEVICE: + invalidate_dcache_range(paddr, paddr + size); + break; + default: + BUG(); + } +} + static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int nents, enum dma_data_direction direction, unsigned long attrs) From 622bd022078263fdebb566c32804551812576432 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 27 Aug 2017 10:16:02 +0200 Subject: [PATCH 07/12] mn10300: make dma_cache_sync a no-op mn10300 does not implement DMA_ATTR_NON_CONSISTENT allocations, so it doesn't make any sense to do any work in dma_cache_sync given that it must be a no-op when dma_alloc_attrs returns coherent memory. Signed-off-by: Christoph Hellwig Reviewed-by: Robin Murphy --- arch/mn10300/include/asm/dma-mapping.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/mn10300/include/asm/dma-mapping.h b/arch/mn10300/include/asm/dma-mapping.h index 737ef574b3eae..dc24163b190f4 100644 --- a/arch/mn10300/include/asm/dma-mapping.h +++ b/arch/mn10300/include/asm/dma-mapping.h @@ -11,9 +11,6 @@ #ifndef _ASM_DMA_MAPPING_H #define _ASM_DMA_MAPPING_H -#include -#include - extern const struct dma_map_ops mn10300_dma_ops; static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) @@ -25,7 +22,6 @@ static inline void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction direction) { - mn10300_dcache_flush_inv(); } #endif From 87f626348a7a4f9d21c321b6326492de9aef245f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 27 Aug 2017 10:17:48 +0200 Subject: [PATCH 08/12] powerpc: make dma_cache_sync a no-op powerpc does not implement DMA_ATTR_NON_CONSISTENT allocations, so it doesn't make any sense to do any work in dma_cache_sync given that it must be a no-op when dma_alloc_attrs returns coherent memory. Signed-off-by: Christoph Hellwig Reviewed-by: Robin Murphy --- arch/powerpc/include/asm/dma-mapping.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h index eaece3d3e2254..320846442bfb0 100644 --- a/arch/powerpc/include/asm/dma-mapping.h +++ b/arch/powerpc/include/asm/dma-mapping.h @@ -144,8 +144,6 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { - BUG_ON(direction == DMA_NONE); - __dma_sync(vaddr, size, (int)direction); } #endif /* __KERNEL__ */ From a535bb801036268c3d057d7584e9c8f35f69aad4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 27 Aug 2017 10:22:48 +0200 Subject: [PATCH 09/12] unicore32: make dma_cache_sync a no-op unicore32 does not implement DMA_ATTR_NON_CONSISTENT allocations, so it doesn't make any sense to do any work in dma_cache_sync given that it must be a no-op when dma_alloc_attrs returns coherent memory. Signed-off-by: Christoph Hellwig Reviewed-by: Robin Murphy --- arch/unicore32/include/asm/cacheflush.h | 9 --------- arch/unicore32/include/asm/dma-mapping.h | 17 ----------------- arch/unicore32/mm/proc-syms.c | 3 --- 3 files changed, 29 deletions(-) diff --git a/arch/unicore32/include/asm/cacheflush.h b/arch/unicore32/include/asm/cacheflush.h index c0301e6c8b812..a5e08e2d5d6d0 100644 --- a/arch/unicore32/include/asm/cacheflush.h +++ b/arch/unicore32/include/asm/cacheflush.h @@ -101,15 +101,6 @@ extern void __cpuc_coherent_user_range(unsigned long, unsigned long); extern void __cpuc_flush_dcache_area(void *, size_t); extern void __cpuc_flush_kern_dcache_area(void *addr, size_t size); -/* - * These are private to the dma-mapping API. Do not use directly. - * Their sole purpose is to ensure that data held in the cache - * is visible to DMA, or data written by DMA to system memory is - * visible to the CPU. - */ -extern void __cpuc_dma_clean_range(unsigned long, unsigned long); -extern void __cpuc_dma_flush_range(unsigned long, unsigned long); - /* * Copy user data from/to a page which is mapped into a different * processes address space. Really, we want to allow our "user diff --git a/arch/unicore32/include/asm/dma-mapping.h b/arch/unicore32/include/asm/dma-mapping.h index 518ba5848dd6c..e949855bb7944 100644 --- a/arch/unicore32/include/asm/dma-mapping.h +++ b/arch/unicore32/include/asm/dma-mapping.h @@ -18,9 +18,6 @@ #include #include -#include -#include - extern const struct dma_map_ops swiotlb_dma_map_ops; static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) @@ -51,20 +48,6 @@ static inline void dma_mark_clean(void *addr, size_t size) {} static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { - unsigned long start = (unsigned long)vaddr; - unsigned long end = start + size; - - switch (direction) { - case DMA_NONE: - BUG(); - case DMA_FROM_DEVICE: - case DMA_BIDIRECTIONAL: /* writeback and invalidate */ - __cpuc_dma_flush_range(start, end); - break; - case DMA_TO_DEVICE: /* writeback only */ - __cpuc_dma_clean_range(start, end); - break; - } } #endif /* __KERNEL__ */ diff --git a/arch/unicore32/mm/proc-syms.c b/arch/unicore32/mm/proc-syms.c index 21c00fc85c994..df215fd6d6395 100644 --- a/arch/unicore32/mm/proc-syms.c +++ b/arch/unicore32/mm/proc-syms.c @@ -20,6 +20,3 @@ EXPORT_SYMBOL(cpu_dcache_clean_area); EXPORT_SYMBOL(cpu_set_pte); EXPORT_SYMBOL(__cpuc_coherent_kern_range); - -EXPORT_SYMBOL(__cpuc_dma_flush_range); -EXPORT_SYMBOL(__cpuc_dma_clean_range); From d708e71ed78f56330325e8de304e2fb1e38ccf1c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 27 Aug 2017 10:27:49 +0200 Subject: [PATCH 10/12] xtensa: make dma_cache_sync a no-op xtensa does not implement DMA_ATTR_NON_CONSISTENT allocations, so it doesn't make any sense to do any work in dma_cache_sync given that it must be a no-op when dma_alloc_attrs returns coherent memory. Signed-off-by: Christoph Hellwig Reviewed-by: Robin Murphy --- arch/xtensa/include/asm/dma-mapping.h | 6 ++++-- arch/xtensa/kernel/pci-dma.c | 23 ----------------------- 2 files changed, 4 insertions(+), 25 deletions(-) diff --git a/arch/xtensa/include/asm/dma-mapping.h b/arch/xtensa/include/asm/dma-mapping.h index 269738dc9d1d7..353e0314d6ba3 100644 --- a/arch/xtensa/include/asm/dma-mapping.h +++ b/arch/xtensa/include/asm/dma-mapping.h @@ -23,8 +23,10 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return &xtensa_dma_map_ops; } -void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction direction); +static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, + enum dma_data_direction direction) +{ +} static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) { diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c index cec86a1c2acce..623720a111432 100644 --- a/arch/xtensa/kernel/pci-dma.c +++ b/arch/xtensa/kernel/pci-dma.c @@ -26,29 +26,6 @@ #include #include -void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction dir) -{ - switch (dir) { - case DMA_BIDIRECTIONAL: - __flush_invalidate_dcache_range((unsigned long)vaddr, size); - break; - - case DMA_FROM_DEVICE: - __invalidate_dcache_range((unsigned long)vaddr, size); - break; - - case DMA_TO_DEVICE: - __flush_dcache_range((unsigned long)vaddr, size); - break; - - case DMA_NONE: - BUG(); - break; - } -} -EXPORT_SYMBOL(dma_cache_sync); - static void do_cache_op(dma_addr_t dma_handle, size_t size, void (*fn)(unsigned long, unsigned long)) { From e0c6584df9c414b50de17e1abc1099f7501bbb60 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 27 Aug 2017 10:35:40 +0200 Subject: [PATCH 11/12] sh: make dma_cache_sync a no-op sh does not implement DMA_ATTR_NON_CONSISTENT allocations, so it doesn't make any sense to do any work in dma_cache_sync given that it must be a no-op when dma_alloc_attrs returns coherent memory. On the other hand sh uses dma_cache_sync internally in the dma_ops implementation and for the maple bus that does not use the DMA API, so a the old functionality for dma_cache_sync is still provided under the name sh_sync_dma_for_device, and without the redundant dev argument. While at it two of the syncing dma_ops also go the proper _for_device postfix. Signed-off-by: Christoph Hellwig Reviewed-by: Robin Murphy --- arch/sh/include/asm/dma-mapping.h | 9 +++++++-- arch/sh/kernel/dma-nommu.c | 17 +++++++++-------- arch/sh/mm/consistent.c | 6 +++--- drivers/sh/maple/maple.c | 5 ++--- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/arch/sh/include/asm/dma-mapping.h b/arch/sh/include/asm/dma-mapping.h index 9b06be07db4db..b46194ecef173 100644 --- a/arch/sh/include/asm/dma-mapping.h +++ b/arch/sh/include/asm/dma-mapping.h @@ -9,8 +9,10 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return dma_ops; } -void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction dir); +static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, + enum dma_data_direction dir) +{ +} /* arch/sh/mm/consistent.c */ extern void *dma_generic_alloc_coherent(struct device *dev, size_t size, @@ -20,4 +22,7 @@ extern void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle, unsigned long attrs); +void sh_sync_dma_for_device(void *vaddr, size_t size, + enum dma_data_direction dir); + #endif /* __ASM_SH_DMA_MAPPING_H */ diff --git a/arch/sh/kernel/dma-nommu.c b/arch/sh/kernel/dma-nommu.c index d24c707b21818..62b485107eae0 100644 --- a/arch/sh/kernel/dma-nommu.c +++ b/arch/sh/kernel/dma-nommu.c @@ -9,6 +9,7 @@ */ #include #include +#include static dma_addr_t nommu_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, @@ -20,7 +21,7 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page, WARN_ON(size == 0); if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) - dma_cache_sync(dev, page_address(page) + offset, size, dir); + sh_sync_dma_for_device(page_address(page) + offset, size, dir); return addr; } @@ -38,7 +39,7 @@ static int nommu_map_sg(struct device *dev, struct scatterlist *sg, BUG_ON(!sg_page(s)); if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) - dma_cache_sync(dev, sg_virt(s), s->length, dir); + sh_sync_dma_for_device(sg_virt(s), s->length, dir); s->dma_address = sg_phys(s); s->dma_length = s->length; @@ -48,20 +49,20 @@ static int nommu_map_sg(struct device *dev, struct scatterlist *sg, } #ifdef CONFIG_DMA_NONCOHERENT -static void nommu_sync_single(struct device *dev, dma_addr_t addr, +static void nommu_sync_single_for_device(struct device *dev, dma_addr_t addr, size_t size, enum dma_data_direction dir) { - dma_cache_sync(dev, phys_to_virt(addr), size, dir); + sh_sync_dma_for_device(phys_to_virt(addr), size, dir); } -static void nommu_sync_sg(struct device *dev, struct scatterlist *sg, +static void nommu_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, enum dma_data_direction dir) { struct scatterlist *s; int i; for_each_sg(sg, s, nelems, i) - dma_cache_sync(dev, sg_virt(s), s->length, dir); + sh_sync_dma_for_device(sg_virt(s), s->length, dir); } #endif @@ -71,8 +72,8 @@ const struct dma_map_ops nommu_dma_ops = { .map_page = nommu_map_page, .map_sg = nommu_map_sg, #ifdef CONFIG_DMA_NONCOHERENT - .sync_single_for_device = nommu_sync_single, - .sync_sg_for_device = nommu_sync_sg, + .sync_single_for_device = nommu_sync_single_for_device, + .sync_sg_for_device = nommu_sync_sg_for_device, #endif .is_phys = 1, }; diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c index d1275adfa0efb..6ea3aab508f22 100644 --- a/arch/sh/mm/consistent.c +++ b/arch/sh/mm/consistent.c @@ -49,7 +49,7 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size, * Pages from the page allocator may have data present in * cache. So flush the cache before using uncached memory. */ - dma_cache_sync(dev, ret, size, DMA_BIDIRECTIONAL); + sh_sync_dma_for_device(ret, size, DMA_BIDIRECTIONAL); ret_nocache = (void __force *)ioremap_nocache(virt_to_phys(ret), size); if (!ret_nocache) { @@ -78,7 +78,7 @@ void dma_generic_free_coherent(struct device *dev, size_t size, iounmap(vaddr); } -void dma_cache_sync(struct device *dev, void *vaddr, size_t size, +void sh_sync_dma_for_device(void *vaddr, size_t size, enum dma_data_direction direction) { void *addr; @@ -100,7 +100,7 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size, BUG(); } } -EXPORT_SYMBOL(dma_cache_sync); +EXPORT_SYMBOL(sh_sync_dma_for_device); static int __init memchunk_setup(char *str) { diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index bec81c2404f78..7525039d812ce 100644 --- a/drivers/sh/maple/maple.c +++ b/drivers/sh/maple/maple.c @@ -300,7 +300,7 @@ static void maple_send(void) mutex_unlock(&maple_wlist_lock); if (maple_packets > 0) { for (i = 0; i < (1 << MAPLE_DMA_PAGES); i++) - dma_cache_sync(0, maple_sendbuf + i * PAGE_SIZE, + sh_sync_dma_for_device(maple_sendbuf + i * PAGE_SIZE, PAGE_SIZE, DMA_BIDIRECTIONAL); } @@ -642,8 +642,7 @@ static void maple_dma_handler(struct work_struct *work) list_for_each_entry_safe(mq, nmq, &maple_sentq, list) { mdev = mq->dev; recvbuf = mq->recvbuf->buf; - dma_cache_sync(&mdev->dev, recvbuf, 0x400, - DMA_FROM_DEVICE); + sh_sync_dma_for_device(recvbuf, 0x400, DMA_FROM_DEVICE); code = recvbuf[0]; kfree(mq->sendbuf); list_del_init(&mq->list); From c9eb6172c328dde7e14812f94f8da87b691e41b5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 27 Aug 2017 10:37:15 +0200 Subject: [PATCH 12/12] dma-mapping: turn dma_cache_sync into a dma_map_ops method After we removed all the dead wood it turns out only two architectures actually implement dma_cache_sync as a real op: mips and parisc. Add a cache_sync method to struct dma_map_ops and implement it for the mips defualt DMA ops, and the parisc pa11 ops. Note that arm, arc and openrisc support DMA_ATTR_NON_CONSISTENT, but never provided a functional dma_cache_sync implementations, which seems somewhat odd. Signed-off-by: Christoph Hellwig Reviewed-by: Robin Murphy --- arch/alpha/include/asm/dma-mapping.h | 2 -- arch/cris/include/asm/dma-mapping.h | 6 ------ arch/frv/include/asm/dma-mapping.h | 6 ------ arch/hexagon/include/asm/dma-mapping.h | 3 --- arch/ia64/include/asm/dma-mapping.h | 6 ------ arch/m32r/include/asm/dma-mapping.h | 5 ----- arch/m68k/include/asm/dma-mapping.h | 6 ------ arch/metag/include/asm/dma-mapping.h | 10 ---------- arch/microblaze/include/asm/dma-mapping.h | 5 ----- arch/mips/include/asm/dma-mapping.h | 3 --- arch/mips/mm/dma-default.c | 7 +++---- arch/mn10300/include/asm/dma-mapping.h | 6 ------ arch/nios2/include/asm/dma-mapping.h | 9 --------- arch/parisc/include/asm/dma-mapping.h | 8 -------- arch/parisc/kernel/pci-dma.c | 8 ++++++++ arch/powerpc/include/asm/dma-mapping.h | 5 ----- arch/s390/include/asm/dma-mapping.h | 5 ----- arch/sh/include/asm/dma-mapping.h | 6 ------ arch/sparc/include/asm/dma-mapping.h | 8 -------- arch/tile/include/asm/dma-mapping.h | 9 --------- arch/unicore32/include/asm/dma-mapping.h | 5 ----- arch/x86/include/asm/dma-mapping.h | 6 ------ arch/xtensa/include/asm/dma-mapping.h | 5 ----- include/linux/dma-mapping.h | 13 +++++++++++++ 24 files changed, 24 insertions(+), 128 deletions(-) diff --git a/arch/alpha/include/asm/dma-mapping.h b/arch/alpha/include/asm/dma-mapping.h index 5d53666935e6b..399a4f49355eb 100644 --- a/arch/alpha/include/asm/dma-mapping.h +++ b/arch/alpha/include/asm/dma-mapping.h @@ -8,6 +8,4 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return dma_ops; } -#define dma_cache_sync(dev, va, size, dir) ((void)0) - #endif /* _ALPHA_DMA_MAPPING_H */ diff --git a/arch/cris/include/asm/dma-mapping.h b/arch/cris/include/asm/dma-mapping.h index 256169de3743d..e30adde42beb2 100644 --- a/arch/cris/include/asm/dma-mapping.h +++ b/arch/cris/include/asm/dma-mapping.h @@ -16,10 +16,4 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) } #endif -static inline void -dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction direction) -{ -} - #endif diff --git a/arch/frv/include/asm/dma-mapping.h b/arch/frv/include/asm/dma-mapping.h index da0e5c9744c4c..da24ae943f028 100644 --- a/arch/frv/include/asm/dma-mapping.h +++ b/arch/frv/include/asm/dma-mapping.h @@ -14,10 +14,4 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return &frv_dma_ops; } -static inline -void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction direction) -{ -} - #endif /* _ASM_DMA_MAPPING_H */ diff --git a/arch/hexagon/include/asm/dma-mapping.h b/arch/hexagon/include/asm/dma-mapping.h index 463dbc18f853e..5208de242e794 100644 --- a/arch/hexagon/include/asm/dma-mapping.h +++ b/arch/hexagon/include/asm/dma-mapping.h @@ -37,9 +37,6 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return dma_ops; } -extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction direction); - static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) { if (!dev->dma_mask) diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h index 99dfc1aa9d3ce..9e5b5df76ff8b 100644 --- a/arch/ia64/include/asm/dma-mapping.h +++ b/arch/ia64/include/asm/dma-mapping.h @@ -44,10 +44,4 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) return daddr; } -static inline void -dma_cache_sync (struct device *dev, void *vaddr, size_t size, - enum dma_data_direction dir) -{ -} - #endif /* _ASM_IA64_DMA_MAPPING_H */ diff --git a/arch/m32r/include/asm/dma-mapping.h b/arch/m32r/include/asm/dma-mapping.h index aff3ae8b62f76..9e993daed7a06 100644 --- a/arch/m32r/include/asm/dma-mapping.h +++ b/arch/m32r/include/asm/dma-mapping.h @@ -13,11 +13,6 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return &dma_noop_ops; } -static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction direction) -{ -} - static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) { if (!dev->dma_mask) diff --git a/arch/m68k/include/asm/dma-mapping.h b/arch/m68k/include/asm/dma-mapping.h index 9210e470771bd..9a0d559fcc138 100644 --- a/arch/m68k/include/asm/dma-mapping.h +++ b/arch/m68k/include/asm/dma-mapping.h @@ -8,10 +8,4 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return &m68k_dma_ops; } -static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction dir) -{ - /* we use coherent allocation, so not much to do here. */ -} - #endif /* _M68K_DMA_MAPPING_H */ diff --git a/arch/metag/include/asm/dma-mapping.h b/arch/metag/include/asm/dma-mapping.h index ea573be2b6d05..340265dcf839b 100644 --- a/arch/metag/include/asm/dma-mapping.h +++ b/arch/metag/include/asm/dma-mapping.h @@ -8,14 +8,4 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return &metag_dma_ops; } -/* - * dma_alloc_attrs() always returns non-cacheable memory, so there's no need to - * do any flushing here. - */ -static inline void -dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction direction) -{ -} - #endif diff --git a/arch/microblaze/include/asm/dma-mapping.h b/arch/microblaze/include/asm/dma-mapping.h index ad448e4aedb6b..6b9ea39405b80 100644 --- a/arch/microblaze/include/asm/dma-mapping.h +++ b/arch/microblaze/include/asm/dma-mapping.h @@ -25,9 +25,4 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return &dma_direct_ops; } -static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction direction) -{ -} - #endif /* _ASM_MICROBLAZE_DMA_MAPPING_H */ diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h index aba71385f9d15..6ea1439430a2d 100644 --- a/arch/mips/include/asm/dma-mapping.h +++ b/arch/mips/include/asm/dma-mapping.h @@ -26,9 +26,6 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) static inline void dma_mark_clean(void *addr, size_t size) {} -extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction direction); - #define arch_setup_dma_ops arch_setup_dma_ops static inline void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, const struct iommu_ops *iommu, diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index c01bd20d02081..2e2514e007206 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -383,7 +383,7 @@ static int mips_dma_supported(struct device *dev, u64 mask) return plat_dma_supported(dev, mask); } -void dma_cache_sync(struct device *dev, void *vaddr, size_t size, +static void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { BUG_ON(direction == DMA_NONE); @@ -392,8 +392,6 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size, __dma_sync_virtual(vaddr, size, direction); } -EXPORT_SYMBOL(dma_cache_sync); - static const struct dma_map_ops mips_default_dma_map_ops = { .alloc = mips_dma_alloc_coherent, .free = mips_dma_free_coherent, @@ -407,7 +405,8 @@ static const struct dma_map_ops mips_default_dma_map_ops = { .sync_sg_for_cpu = mips_dma_sync_sg_for_cpu, .sync_sg_for_device = mips_dma_sync_sg_for_device, .mapping_error = mips_dma_mapping_error, - .dma_supported = mips_dma_supported + .dma_supported = mips_dma_supported, + .cache_sync = mips_dma_cache_sync, }; const struct dma_map_ops *mips_dma_map_ops = &mips_default_dma_map_ops; diff --git a/arch/mn10300/include/asm/dma-mapping.h b/arch/mn10300/include/asm/dma-mapping.h index dc24163b190f4..439e474ed6d75 100644 --- a/arch/mn10300/include/asm/dma-mapping.h +++ b/arch/mn10300/include/asm/dma-mapping.h @@ -18,10 +18,4 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return &mn10300_dma_ops; } -static inline -void dma_cache_sync(void *vaddr, size_t size, - enum dma_data_direction direction) -{ -} - #endif diff --git a/arch/nios2/include/asm/dma-mapping.h b/arch/nios2/include/asm/dma-mapping.h index f8dc622227414..6ceb92251da0f 100644 --- a/arch/nios2/include/asm/dma-mapping.h +++ b/arch/nios2/include/asm/dma-mapping.h @@ -17,13 +17,4 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return &nios2_dma_ops; } -/* - * dma_alloc_attrs() always returns non-cacheable memory, so there's no need to - * do any flushing here. - */ -static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction direction) -{ -} - #endif /* _ASM_NIOS2_DMA_MAPPING_H */ diff --git a/arch/parisc/include/asm/dma-mapping.h b/arch/parisc/include/asm/dma-mapping.h index 2b16282add691..cb26bbd71d8a2 100644 --- a/arch/parisc/include/asm/dma-mapping.h +++ b/arch/parisc/include/asm/dma-mapping.h @@ -32,14 +32,6 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return hppa_dma_ops; } -static inline void -dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction direction) -{ - if (hppa_dma_ops->sync_single_for_cpu) - flush_kernel_dcache_range((unsigned long)vaddr, size); -} - static inline void * parisc_walk_tree(struct device *dev) { diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c index bd4c0a7471d30..f87c34cb3b439 100644 --- a/arch/parisc/kernel/pci-dma.c +++ b/arch/parisc/kernel/pci-dma.c @@ -571,6 +571,12 @@ static void pa11_dma_sync_sg_for_device(struct device *dev, struct scatterlist * flush_kernel_vmap_range(sg_virt(sg), sg->length); } +static void pa11_dma_cache_sync(struct device *dev, void *vaddr, size_t size, + enum dma_data_direction direction) +{ + flush_kernel_dcache_range((unsigned long)vaddr, size); +} + const struct dma_map_ops pcxl_dma_ops = { .dma_supported = pa11_dma_supported, .alloc = pa11_dma_alloc, @@ -583,6 +589,7 @@ const struct dma_map_ops pcxl_dma_ops = { .sync_single_for_device = pa11_dma_sync_single_for_device, .sync_sg_for_cpu = pa11_dma_sync_sg_for_cpu, .sync_sg_for_device = pa11_dma_sync_sg_for_device, + .cache_sync = pa11_dma_cache_sync, }; static void *pcx_dma_alloc(struct device *dev, size_t size, @@ -619,4 +626,5 @@ const struct dma_map_ops pcx_dma_ops = { .sync_single_for_device = pa11_dma_sync_single_for_device, .sync_sg_for_cpu = pa11_dma_sync_sg_for_cpu, .sync_sg_for_device = pa11_dma_sync_sg_for_device, + .cache_sync = pa11_dma_cache_sync, }; diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h index 320846442bfb0..2e43c2ef76323 100644 --- a/arch/powerpc/include/asm/dma-mapping.h +++ b/arch/powerpc/include/asm/dma-mapping.h @@ -141,10 +141,5 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) #define ARCH_HAS_DMA_MMAP_COHERENT -static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction direction) -{ -} - #endif /* __KERNEL__ */ #endif /* _ASM_DMA_MAPPING_H */ diff --git a/arch/s390/include/asm/dma-mapping.h b/arch/s390/include/asm/dma-mapping.h index 512ad0eaa11a7..b17304b13de5f 100644 --- a/arch/s390/include/asm/dma-mapping.h +++ b/arch/s390/include/asm/dma-mapping.h @@ -15,11 +15,6 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return &dma_noop_ops; } -static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction direction) -{ -} - static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) { if (!dev->dma_mask) diff --git a/arch/sh/include/asm/dma-mapping.h b/arch/sh/include/asm/dma-mapping.h index b46194ecef173..e89df111c0178 100644 --- a/arch/sh/include/asm/dma-mapping.h +++ b/arch/sh/include/asm/dma-mapping.h @@ -9,12 +9,6 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return dma_ops; } -static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction dir) -{ -} - -/* arch/sh/mm/consistent.c */ extern void *dma_generic_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr, gfp_t flag, unsigned long attrs); diff --git a/arch/sparc/include/asm/dma-mapping.h b/arch/sparc/include/asm/dma-mapping.h index 60bf1633d5541..b298ed45cb239 100644 --- a/arch/sparc/include/asm/dma-mapping.h +++ b/arch/sparc/include/asm/dma-mapping.h @@ -5,14 +5,6 @@ #include #include -static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction dir) -{ - /* Since dma_{alloc,free}_noncoherent() allocated coherent memory, this - * routine can be a nop. - */ -} - extern const struct dma_map_ops *dma_ops; extern const struct dma_map_ops pci32_dma_ops; diff --git a/arch/tile/include/asm/dma-mapping.h b/arch/tile/include/asm/dma-mapping.h index 7061dc8af43af..97ad628782904 100644 --- a/arch/tile/include/asm/dma-mapping.h +++ b/arch/tile/include/asm/dma-mapping.h @@ -67,13 +67,4 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) #define HAVE_ARCH_DMA_SET_MASK 1 int dma_set_mask(struct device *dev, u64 mask); -/* - * dma_alloc_attrs() always returns non-cacheable memory, so there's no need to - * do any flushing here. - */ -static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction direction) -{ -} - #endif /* _ASM_TILE_DMA_MAPPING_H */ diff --git a/arch/unicore32/include/asm/dma-mapping.h b/arch/unicore32/include/asm/dma-mapping.h index e949855bb7944..ac608c2f6af6a 100644 --- a/arch/unicore32/include/asm/dma-mapping.h +++ b/arch/unicore32/include/asm/dma-mapping.h @@ -45,10 +45,5 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) static inline void dma_mark_clean(void *addr, size_t size) {} -static inline void dma_cache_sync(struct device *dev, void *vaddr, - size_t size, enum dma_data_direction direction) -{ -} - #endif /* __KERNEL__ */ #endif diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h index c6d3367be9168..c26747340ba5b 100644 --- a/arch/x86/include/asm/dma-mapping.h +++ b/arch/x86/include/asm/dma-mapping.h @@ -67,12 +67,6 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) } #endif /* CONFIG_X86_DMA_REMAP */ -static inline void -dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction dir) -{ -} - static inline unsigned long dma_alloc_coherent_mask(struct device *dev, gfp_t gfp) { diff --git a/arch/xtensa/include/asm/dma-mapping.h b/arch/xtensa/include/asm/dma-mapping.h index 353e0314d6ba3..153bf23709885 100644 --- a/arch/xtensa/include/asm/dma-mapping.h +++ b/arch/xtensa/include/asm/dma-mapping.h @@ -23,11 +23,6 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) return &xtensa_dma_map_ops; } -static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction direction) -{ -} - static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) { return (dma_addr_t)paddr; diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 29ce9815da87f..028a375d240d8 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -126,6 +126,8 @@ struct dma_map_ops { void (*sync_sg_for_device)(struct device *dev, struct scatterlist *sg, int nents, 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); #ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK @@ -436,6 +438,17 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, #define dma_map_page(d, p, o, s, r) dma_map_page_attrs(d, p, o, s, r, 0) #define dma_unmap_page(d, a, s, r) dma_unmap_page_attrs(d, a, s, r, 0) +static inline void +dma_cache_sync(struct device *dev, void *vaddr, size_t size, + enum dma_data_direction dir) +{ + const struct dma_map_ops *ops = get_dma_ops(dev); + + BUG_ON(!valid_dma_direction(dir)); + if (ops->cache_sync) + ops->cache_sync(dev, vaddr, size, dir); +} + extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, void *cpu_addr, dma_addr_t dma_addr, size_t size);