aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2018-06-19 03:03:16 -0400
committerMax Filippov <jcmvbkbc@gmail.com>2018-07-11 14:10:21 -0400
commit3f2bbf443e21584887f954328ceee8515d7691e7 (patch)
tree98e357ff7a4a3340a810f8b99f75f91f2d38be84
parent1e4b044d22517cae7047c99038abb444423243ca (diff)
xtensa: use generic dma_noncoherent_ops
Switch to the generic noncoherent direct mapping implementation. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
-rw-r--r--arch/xtensa/Kconfig3
-rw-r--r--arch/xtensa/include/asm/Kbuild1
-rw-r--r--arch/xtensa/include/asm/dma-mapping.h26
-rw-r--r--arch/xtensa/kernel/pci-dma.c130
4 files changed, 19 insertions, 141 deletions
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index d575e8701955..0d472595467a 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -4,12 +4,15 @@ config ZONE_DMA
4 4
5config XTENSA 5config XTENSA
6 def_bool y 6 def_bool y
7 select ARCH_HAS_SYNC_DMA_FOR_CPU
8 select ARCH_HAS_SYNC_DMA_FOR_DEVICE
7 select ARCH_NO_COHERENT_DMA_MMAP if !MMU 9 select ARCH_NO_COHERENT_DMA_MMAP if !MMU
8 select ARCH_WANT_FRAME_POINTERS 10 select ARCH_WANT_FRAME_POINTERS
9 select ARCH_WANT_IPC_PARSE_VERSION 11 select ARCH_WANT_IPC_PARSE_VERSION
10 select BUILDTIME_EXTABLE_SORT 12 select BUILDTIME_EXTABLE_SORT
11 select CLONE_BACKWARDS 13 select CLONE_BACKWARDS
12 select COMMON_CLK 14 select COMMON_CLK
15 select DMA_NONCOHERENT_OPS
13 select GENERIC_ATOMIC64 16 select GENERIC_ATOMIC64
14 select GENERIC_CLOCKEVENTS 17 select GENERIC_CLOCKEVENTS
15 select GENERIC_IRQ_SHOW 18 select GENERIC_IRQ_SHOW
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index e5e1e61c538c..82c756431b49 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -3,6 +3,7 @@ generic-y += compat.h
3generic-y += device.h 3generic-y += device.h
4generic-y += div64.h 4generic-y += div64.h
5generic-y += dma-contiguous.h 5generic-y += dma-contiguous.h
6generic-y += dma-mapping.h
6generic-y += emergency-restart.h 7generic-y += emergency-restart.h
7generic-y += exec.h 8generic-y += exec.h
8generic-y += extable.h 9generic-y += extable.h
diff --git a/arch/xtensa/include/asm/dma-mapping.h b/arch/xtensa/include/asm/dma-mapping.h
deleted file mode 100644
index 44098800dad7..000000000000
--- a/arch/xtensa/include/asm/dma-mapping.h
+++ /dev/null
@@ -1,26 +0,0 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2003 - 2005 Tensilica Inc.
7 * Copyright (C) 2015 Cadence Design Systems Inc.
8 */
9
10#ifndef _XTENSA_DMA_MAPPING_H
11#define _XTENSA_DMA_MAPPING_H
12
13#include <asm/cache.h>
14#include <asm/io.h>
15
16#include <linux/mm.h>
17#include <linux/scatterlist.h>
18
19extern const struct dma_map_ops xtensa_dma_map_ops;
20
21static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
22{
23 return &xtensa_dma_map_ops;
24}
25
26#endif /* _XTENSA_DMA_MAPPING_H */
diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c
index 392b4a80ebc2..a83d60e92908 100644
--- a/arch/xtensa/kernel/pci-dma.c
+++ b/arch/xtensa/kernel/pci-dma.c
@@ -16,26 +16,24 @@
16 */ 16 */
17 17
18#include <linux/dma-contiguous.h> 18#include <linux/dma-contiguous.h>
19#include <linux/dma-noncoherent.h>
19#include <linux/dma-direct.h> 20#include <linux/dma-direct.h>
20#include <linux/gfp.h> 21#include <linux/gfp.h>
21#include <linux/highmem.h> 22#include <linux/highmem.h>
22#include <linux/mm.h> 23#include <linux/mm.h>
23#include <linux/module.h>
24#include <linux/pci.h>
25#include <linux/string.h>
26#include <linux/types.h> 24#include <linux/types.h>
27#include <asm/cacheflush.h> 25#include <asm/cacheflush.h>
28#include <asm/io.h> 26#include <asm/io.h>
29 27
30static void do_cache_op(dma_addr_t dma_handle, size_t size, 28static void do_cache_op(phys_addr_t paddr, size_t size,
31 void (*fn)(unsigned long, unsigned long)) 29 void (*fn)(unsigned long, unsigned long))
32{ 30{
33 unsigned long off = dma_handle & (PAGE_SIZE - 1); 31 unsigned long off = paddr & (PAGE_SIZE - 1);
34 unsigned long pfn = PFN_DOWN(dma_handle); 32 unsigned long pfn = PFN_DOWN(paddr);
35 struct page *page = pfn_to_page(pfn); 33 struct page *page = pfn_to_page(pfn);
36 34
37 if (!PageHighMem(page)) 35 if (!PageHighMem(page))
38 fn((unsigned long)bus_to_virt(dma_handle), size); 36 fn((unsigned long)phys_to_virt(paddr), size);
39 else 37 else
40 while (size > 0) { 38 while (size > 0) {
41 size_t sz = min_t(size_t, size, PAGE_SIZE - off); 39 size_t sz = min_t(size_t, size, PAGE_SIZE - off);
@@ -49,14 +47,13 @@ static void do_cache_op(dma_addr_t dma_handle, size_t size,
49 } 47 }
50} 48}
51 49
52static void xtensa_sync_single_for_cpu(struct device *dev, 50void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
53 dma_addr_t dma_handle, size_t size, 51 size_t size, enum dma_data_direction dir)
54 enum dma_data_direction dir)
55{ 52{
56 switch (dir) { 53 switch (dir) {
57 case DMA_BIDIRECTIONAL: 54 case DMA_BIDIRECTIONAL:
58 case DMA_FROM_DEVICE: 55 case DMA_FROM_DEVICE:
59 do_cache_op(dma_handle, size, __invalidate_dcache_range); 56 do_cache_op(paddr, size, __invalidate_dcache_range);
60 break; 57 break;
61 58
62 case DMA_NONE: 59 case DMA_NONE:
@@ -68,15 +65,14 @@ static void xtensa_sync_single_for_cpu(struct device *dev,
68 } 65 }
69} 66}
70 67
71static void xtensa_sync_single_for_device(struct device *dev, 68void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
72 dma_addr_t dma_handle, size_t size, 69 size_t size, enum dma_data_direction dir)
73 enum dma_data_direction dir)
74{ 70{
75 switch (dir) { 71 switch (dir) {
76 case DMA_BIDIRECTIONAL: 72 case DMA_BIDIRECTIONAL:
77 case DMA_TO_DEVICE: 73 case DMA_TO_DEVICE:
78 if (XCHAL_DCACHE_IS_WRITEBACK) 74 if (XCHAL_DCACHE_IS_WRITEBACK)
79 do_cache_op(dma_handle, size, __flush_dcache_range); 75 do_cache_op(paddr, size, __flush_dcache_range);
80 break; 76 break;
81 77
82 case DMA_NONE: 78 case DMA_NONE:
@@ -88,40 +84,13 @@ static void xtensa_sync_single_for_device(struct device *dev,
88 } 84 }
89} 85}
90 86
91static void xtensa_sync_sg_for_cpu(struct device *dev,
92 struct scatterlist *sg, int nents,
93 enum dma_data_direction dir)
94{
95 struct scatterlist *s;
96 int i;
97
98 for_each_sg(sg, s, nents, i) {
99 xtensa_sync_single_for_cpu(dev, sg_dma_address(s),
100 sg_dma_len(s), dir);
101 }
102}
103
104static void xtensa_sync_sg_for_device(struct device *dev,
105 struct scatterlist *sg, int nents,
106 enum dma_data_direction dir)
107{
108 struct scatterlist *s;
109 int i;
110
111 for_each_sg(sg, s, nents, i) {
112 xtensa_sync_single_for_device(dev, sg_dma_address(s),
113 sg_dma_len(s), dir);
114 }
115}
116
117/* 87/*
118 * Note: We assume that the full memory space is always mapped to 'kseg' 88 * Note: We assume that the full memory space is always mapped to 'kseg'
119 * Otherwise we have to use page attributes (not implemented). 89 * Otherwise we have to use page attributes (not implemented).
120 */ 90 */
121 91
122static void *xtensa_dma_alloc(struct device *dev, size_t size, 92void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
123 dma_addr_t *handle, gfp_t flag, 93 gfp_t flag, unsigned long attrs)
124 unsigned long attrs)
125{ 94{
126 unsigned long ret; 95 unsigned long ret;
127 unsigned long uncached; 96 unsigned long uncached;
@@ -171,8 +140,8 @@ static void *xtensa_dma_alloc(struct device *dev, size_t size,
171 return (void *)uncached; 140 return (void *)uncached;
172} 141}
173 142
174static void xtensa_dma_free(struct device *dev, size_t size, void *vaddr, 143void arch_dma_free(struct device *dev, size_t size, void *vaddr,
175 dma_addr_t dma_handle, unsigned long attrs) 144 dma_addr_t dma_handle, unsigned long attrs)
176{ 145{
177 unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; 146 unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
178 unsigned long addr = (unsigned long)vaddr; 147 unsigned long addr = (unsigned long)vaddr;
@@ -192,72 +161,3 @@ static void xtensa_dma_free(struct device *dev, size_t size, void *vaddr,
192 if (!dma_release_from_contiguous(dev, page, count)) 161 if (!dma_release_from_contiguous(dev, page, count))
193 __free_pages(page, get_order(size)); 162 __free_pages(page, get_order(size));
194} 163}
195
196static dma_addr_t xtensa_map_page(struct device *dev, struct page *page,
197 unsigned long offset, size_t size,
198 enum dma_data_direction dir,
199 unsigned long attrs)
200{
201 dma_addr_t dma_handle = page_to_phys(page) + offset;
202
203 if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
204 xtensa_sync_single_for_device(dev, dma_handle, size, dir);
205
206 return dma_handle;
207}
208
209static void xtensa_unmap_page(struct device *dev, dma_addr_t dma_handle,
210 size_t size, enum dma_data_direction dir,
211 unsigned long attrs)
212{
213 if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
214 xtensa_sync_single_for_cpu(dev, dma_handle, size, dir);
215}
216
217static int xtensa_map_sg(struct device *dev, struct scatterlist *sg,
218 int nents, enum dma_data_direction dir,
219 unsigned long attrs)
220{
221 struct scatterlist *s;
222 int i;
223
224 for_each_sg(sg, s, nents, i) {
225 s->dma_address = xtensa_map_page(dev, sg_page(s), s->offset,
226 s->length, dir, attrs);
227 }
228 return nents;
229}
230
231static void xtensa_unmap_sg(struct device *dev,
232 struct scatterlist *sg, int nents,
233 enum dma_data_direction dir,
234 unsigned long attrs)
235{
236 struct scatterlist *s;
237 int i;
238
239 for_each_sg(sg, s, nents, i) {
240 xtensa_unmap_page(dev, sg_dma_address(s),
241 sg_dma_len(s), dir, attrs);
242 }
243}
244
245int xtensa_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
246{
247 return 0;
248}
249
250const struct dma_map_ops xtensa_dma_map_ops = {
251 .alloc = xtensa_dma_alloc,
252 .free = xtensa_dma_free,
253 .map_page = xtensa_map_page,
254 .unmap_page = xtensa_unmap_page,
255 .map_sg = xtensa_map_sg,
256 .unmap_sg = xtensa_unmap_sg,
257 .sync_single_for_cpu = xtensa_sync_single_for_cpu,
258 .sync_single_for_device = xtensa_sync_single_for_device,
259 .sync_sg_for_cpu = xtensa_sync_sg_for_cpu,
260 .sync_sg_for_device = xtensa_sync_sg_for_device,
261 .mapping_error = xtensa_dma_mapping_error,
262};
263EXPORT_SYMBOL(xtensa_dma_map_ops);