From b2fcb677d4dd2aac3202365719733452b5512719 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 16 Apr 2018 17:26:38 +0200 Subject: sh: simplify get_arch_dma_ops Remove the indirection through the dma_ops variable, and just return nommu_dma_ops directly from get_arch_dma_ops. Signed-off-by: Christoph Hellwig Acked-by: Yoshinori Sato --- arch/sh/include/asm/dma-mapping.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/sh/include') diff --git a/arch/sh/include/asm/dma-mapping.h b/arch/sh/include/asm/dma-mapping.h index 41167931e5d9..149e71f95be7 100644 --- a/arch/sh/include/asm/dma-mapping.h +++ b/arch/sh/include/asm/dma-mapping.h @@ -2,12 +2,11 @@ #ifndef __ASM_SH_DMA_MAPPING_H #define __ASM_SH_DMA_MAPPING_H -extern const struct dma_map_ops *dma_ops; -extern void no_iommu_init(void); +extern const struct dma_map_ops nommu_dma_ops; static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) { - return dma_ops; + return &nommu_dma_ops; } extern void *dma_generic_alloc_coherent(struct device *dev, size_t size, -- cgit v1.2.3 From 47fcae0d2a5fc77123fc14b0db9fe0025a1a829a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 18 Apr 2018 08:53:46 +0200 Subject: sh: introduce a sh_cacheop_vaddr helper And use it in the maple bus code to avoid a dma API dependency. Signed-off-by: Christoph Hellwig Acked-by: Yoshinori Sato --- arch/sh/include/asm/cacheflush.h | 7 +++++++ arch/sh/mm/consistent.c | 6 +----- drivers/sh/maple/maple.c | 7 ++++--- 3 files changed, 12 insertions(+), 8 deletions(-) (limited to 'arch/sh/include') diff --git a/arch/sh/include/asm/cacheflush.h b/arch/sh/include/asm/cacheflush.h index d103ab5a4e4b..b932e42ef028 100644 --- a/arch/sh/include/asm/cacheflush.h +++ b/arch/sh/include/asm/cacheflush.h @@ -101,5 +101,12 @@ void kunmap_coherent(void *kvaddr); void cpu_cache_init(void); +static inline void *sh_cacheop_vaddr(void *vaddr) +{ + if (__in_29bit_mode()) + vaddr = (void *)CAC_ADDR((unsigned long)vaddr); + return vaddr; +} + #endif /* __KERNEL__ */ #endif /* __ASM_SH_CACHEFLUSH_H */ diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c index e9d422bd42a5..1622ae6b9dbd 100644 --- a/arch/sh/mm/consistent.c +++ b/arch/sh/mm/consistent.c @@ -74,10 +74,7 @@ void dma_generic_free_coherent(struct device *dev, size_t size, void sh_sync_dma_for_device(void *vaddr, size_t size, enum dma_data_direction direction) { - void *addr; - - addr = __in_29bit_mode() ? - (void *)CAC_ADDR((unsigned long)vaddr) : vaddr; + void *addr = sh_cacheop_vaddr(vaddr); switch (direction) { case DMA_FROM_DEVICE: /* invalidate only */ @@ -93,7 +90,6 @@ void sh_sync_dma_for_device(void *vaddr, size_t size, BUG(); } } -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 2e45988d1259..e5d7fb81ad66 100644 --- a/drivers/sh/maple/maple.c +++ b/drivers/sh/maple/maple.c @@ -300,8 +300,8 @@ static void maple_send(void) mutex_unlock(&maple_wlist_lock); if (maple_packets > 0) { for (i = 0; i < (1 << MAPLE_DMA_PAGES); i++) - sh_sync_dma_for_device(maple_sendbuf + i * PAGE_SIZE, - PAGE_SIZE, DMA_BIDIRECTIONAL); + __flush_purge_region(maple_sendbuf + i * PAGE_SIZE, + PAGE_SIZE); } finish: @@ -642,7 +642,8 @@ 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; - sh_sync_dma_for_device(recvbuf, 0x400, DMA_FROM_DEVICE); + __flush_invalidate_region(sh_cacheop_vaddr(recvbuf), + 0x400); code = recvbuf[0]; kfree(mq->sendbuf); list_del_init(&mq->list); -- cgit v1.2.3 From a602915f5d0d9eff96a1d85b6f81e4921b52edfe Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 17 Apr 2018 22:02:10 +0200 Subject: sh: use dma_direct_ops for the CONFIG_DMA_COHERENT case This is a slight change in behavior as we avoid the detour through the virtual mapping for the coherent allocator, but if this CPU really is coherent that should be the right thing to do. Signed-off-by: Christoph Hellwig Acked-by: Yoshinori Sato --- arch/sh/Kconfig | 1 + arch/sh/include/asm/dma-mapping.h | 4 ++++ arch/sh/kernel/Makefile | 4 ++-- arch/sh/kernel/dma-nommu.c | 4 ---- 4 files changed, 7 insertions(+), 6 deletions(-) (limited to 'arch/sh/include') diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index dd4f3d3e644f..c9993a0cdc7e 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -159,6 +159,7 @@ config SWAP_IO_SPACE bool config DMA_COHERENT + select DMA_DIRECT_OPS bool config DMA_NONCOHERENT diff --git a/arch/sh/include/asm/dma-mapping.h b/arch/sh/include/asm/dma-mapping.h index 149e71f95be7..1ebc6a4eb1c5 100644 --- a/arch/sh/include/asm/dma-mapping.h +++ b/arch/sh/include/asm/dma-mapping.h @@ -6,7 +6,11 @@ extern const struct dma_map_ops nommu_dma_ops; static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) { +#ifdef CONFIG_DMA_NONCOHERENT return &nommu_dma_ops; +#else + return &dma_direct_ops; +#endif } extern void *dma_generic_alloc_coherent(struct device *dev, size_t size, diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index dc80041f7363..cb5f1bfb52de 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -12,7 +12,7 @@ endif CFLAGS_REMOVE_return_address.o = -pg -obj-y := debugtraps.o dma-nommu.o dumpstack.o \ +obj-y := debugtraps.o dumpstack.o \ idle.o io.o irq.o irq_$(BITS).o kdebugfs.o \ machvec.o nmi_debug.o process.o \ process_$(BITS).o ptrace.o ptrace_$(BITS).o \ @@ -45,7 +45,7 @@ obj-$(CONFIG_DUMP_CODE) += disassemble.o obj-$(CONFIG_HIBERNATION) += swsusp.o obj-$(CONFIG_DWARF_UNWINDER) += dwarf.o obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_callchain.o - +obj-$(CONFIG_DMA_NONCOHERENT) += dma-nommu.o obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o ccflags-y := -Werror diff --git a/arch/sh/kernel/dma-nommu.c b/arch/sh/kernel/dma-nommu.c index 79a9edafa5b0..d8689b1cb743 100644 --- a/arch/sh/kernel/dma-nommu.c +++ b/arch/sh/kernel/dma-nommu.c @@ -51,7 +51,6 @@ static int nommu_map_sg(struct device *dev, struct scatterlist *sg, return nents; } -#ifdef CONFIG_DMA_NONCOHERENT static void nommu_sync_single_for_device(struct device *dev, dma_addr_t addr, size_t size, enum dma_data_direction dir) { @@ -67,16 +66,13 @@ static void nommu_sync_sg_for_device(struct device *dev, struct scatterlist *sg, for_each_sg(sg, s, nelems, i) sh_sync_dma_for_device(sg_virt(s), s->length, dir); } -#endif const struct dma_map_ops nommu_dma_ops = { .alloc = dma_generic_alloc_coherent, .free = dma_generic_free_coherent, .map_page = nommu_map_page, .map_sg = nommu_map_sg, -#ifdef CONFIG_DMA_NONCOHERENT .sync_single_for_device = nommu_sync_single_for_device, .sync_sg_for_device = nommu_sync_sg_for_device, -#endif }; EXPORT_SYMBOL(nommu_dma_ops); -- cgit v1.2.3 From 6fa1d28e38cfa0c90f8d64c0cab37769e5337b85 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 11 May 2018 08:36:53 +0200 Subject: sh: use generic dma_noncoherent_ops Switch to the generic noncoherent direct mapping implementation. Signed-off-by: Christoph Hellwig Acked-by: Yoshinori Sato --- arch/sh/Kconfig | 3 +- arch/sh/include/asm/Kbuild | 1 + arch/sh/include/asm/dma-mapping.h | 26 ------------- arch/sh/kernel/Makefile | 2 +- arch/sh/kernel/dma-coherent.c | 23 ++++++------ arch/sh/kernel/dma-nommu.c | 78 --------------------------------------- 6 files changed, 15 insertions(+), 118 deletions(-) delete mode 100644 arch/sh/include/asm/dma-mapping.h delete mode 100644 arch/sh/kernel/dma-nommu.c (limited to 'arch/sh/include') diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index c9993a0cdc7e..da4db4b5359f 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -51,7 +51,6 @@ config SUPERH select HAVE_ARCH_AUDITSYSCALL select HAVE_FUTEX_CMPXCHG if FUTEX select HAVE_NMI - select NEED_DMA_MAP_STATE select NEED_SG_DMA_LENGTH help @@ -164,6 +163,8 @@ config DMA_COHERENT config DMA_NONCOHERENT def_bool !DMA_COHERENT + select ARCH_HAS_SYNC_DMA_FOR_DEVICE + select DMA_NONCOHERENT_OPS config PGTABLE_LEVELS default 3 if X2TLB diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild index 46dd82ab2c29..6a5609a55965 100644 --- a/arch/sh/include/asm/Kbuild +++ b/arch/sh/include/asm/Kbuild @@ -2,6 +2,7 @@ generic-y += compat.h generic-y += current.h generic-y += delay.h generic-y += div64.h +generic-y += dma-mapping.h generic-y += emergency-restart.h generic-y += exec.h generic-y += irq_regs.h diff --git a/arch/sh/include/asm/dma-mapping.h b/arch/sh/include/asm/dma-mapping.h deleted file mode 100644 index 1ebc6a4eb1c5..000000000000 --- a/arch/sh/include/asm/dma-mapping.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_SH_DMA_MAPPING_H -#define __ASM_SH_DMA_MAPPING_H - -extern const struct dma_map_ops nommu_dma_ops; - -static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus) -{ -#ifdef CONFIG_DMA_NONCOHERENT - return &nommu_dma_ops; -#else - return &dma_direct_ops; -#endif -} - -extern void *dma_generic_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_addr, gfp_t flag, - unsigned long attrs); -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/Makefile b/arch/sh/kernel/Makefile index d5ddb64bfffe..59673f8a3379 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -45,7 +45,7 @@ obj-$(CONFIG_DUMP_CODE) += disassemble.o obj-$(CONFIG_HIBERNATION) += swsusp.o obj-$(CONFIG_DWARF_UNWINDER) += dwarf.o obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_callchain.o -obj-$(CONFIG_DMA_NONCOHERENT) += dma-nommu.o dma-coherent.o +obj-$(CONFIG_DMA_NONCOHERENT) += dma-coherent.o obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o ccflags-y := -Werror diff --git a/arch/sh/kernel/dma-coherent.c b/arch/sh/kernel/dma-coherent.c index 2518065d5d27..a0021eef956b 100644 --- a/arch/sh/kernel/dma-coherent.c +++ b/arch/sh/kernel/dma-coherent.c @@ -7,14 +7,13 @@ */ #include #include -#include +#include #include #include #include -void *dma_generic_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp, - unsigned long attrs) +void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, + gfp_t gfp, unsigned long attrs) { void *ret, *ret_nocache; int order = get_order(size); @@ -29,7 +28,8 @@ 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. */ - sh_sync_dma_for_device(ret, size, DMA_BIDIRECTIONAL); + arch_sync_dma_for_device(dev, virt_to_phys(ret), size, + DMA_BIDIRECTIONAL); ret_nocache = (void __force *)ioremap_nocache(virt_to_phys(ret), size); if (!ret_nocache) { @@ -46,9 +46,8 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size, return ret_nocache; } -void dma_generic_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle, - unsigned long attrs) +void arch_dma_free(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_handle, unsigned long attrs) { int order = get_order(size); unsigned long pfn = (dma_handle >> PAGE_SHIFT); @@ -63,12 +62,12 @@ void dma_generic_free_coherent(struct device *dev, size_t size, iounmap(vaddr); } -void sh_sync_dma_for_device(void *vaddr, size_t size, - enum dma_data_direction direction) +void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr, + size_t size, enum dma_data_direction dir) { - void *addr = sh_cacheop_vaddr(vaddr); + void *addr = sh_cacheop_vaddr(phys_to_virt(paddr)); - switch (direction) { + switch (dir) { case DMA_FROM_DEVICE: /* invalidate only */ __flush_invalidate_region(addr, size); break; diff --git a/arch/sh/kernel/dma-nommu.c b/arch/sh/kernel/dma-nommu.c deleted file mode 100644 index d8689b1cb743..000000000000 --- a/arch/sh/kernel/dma-nommu.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * DMA mapping support for platforms lacking IOMMUs. - * - * Copyright (C) 2009 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include - -static dma_addr_t nommu_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction dir, - unsigned long attrs) -{ - dma_addr_t addr = page_to_phys(page) + offset - - PFN_PHYS(dev->dma_pfn_offset); - - WARN_ON(size == 0); - - if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) - sh_sync_dma_for_device(page_address(page) + offset, size, dir); - - return addr; -} - -static int nommu_map_sg(struct device *dev, struct scatterlist *sg, - int nents, enum dma_data_direction dir, - unsigned long attrs) -{ - struct scatterlist *s; - int i; - - WARN_ON(nents == 0 || sg[0].length == 0); - - for_each_sg(sg, s, nents, i) { - dma_addr_t offset = PFN_PHYS(dev->dma_pfn_offset); - - BUG_ON(!sg_page(s)); - - if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) - sh_sync_dma_for_device(sg_virt(s), s->length, dir); - - s->dma_address = sg_phys(s) - offset; - s->dma_length = s->length; - } - - return nents; -} - -static void nommu_sync_single_for_device(struct device *dev, dma_addr_t addr, - size_t size, enum dma_data_direction dir) -{ - sh_sync_dma_for_device(phys_to_virt(addr), size, dir); -} - -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) - sh_sync_dma_for_device(sg_virt(s), s->length, dir); -} - -const struct dma_map_ops nommu_dma_ops = { - .alloc = dma_generic_alloc_coherent, - .free = dma_generic_free_coherent, - .map_page = nommu_map_page, - .map_sg = nommu_map_sg, - .sync_single_for_device = nommu_sync_single_for_device, - .sync_sg_for_device = nommu_sync_sg_for_device, -}; -EXPORT_SYMBOL(nommu_dma_ops); -- cgit v1.2.3