diff options
| author | Christoph Hellwig <hch@lst.de> | 2018-06-19 03:03:16 -0400 |
|---|---|---|
| committer | Max Filippov <jcmvbkbc@gmail.com> | 2018-07-11 14:10:21 -0400 |
| commit | 3f2bbf443e21584887f954328ceee8515d7691e7 (patch) | |
| tree | 98e357ff7a4a3340a810f8b99f75f91f2d38be84 | |
| parent | 1e4b044d22517cae7047c99038abb444423243ca (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/Kconfig | 3 | ||||
| -rw-r--r-- | arch/xtensa/include/asm/Kbuild | 1 | ||||
| -rw-r--r-- | arch/xtensa/include/asm/dma-mapping.h | 26 | ||||
| -rw-r--r-- | arch/xtensa/kernel/pci-dma.c | 130 |
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 | ||
| 5 | config XTENSA | 5 | config 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 | |||
| 3 | generic-y += device.h | 3 | generic-y += device.h |
| 4 | generic-y += div64.h | 4 | generic-y += div64.h |
| 5 | generic-y += dma-contiguous.h | 5 | generic-y += dma-contiguous.h |
| 6 | generic-y += dma-mapping.h | ||
| 6 | generic-y += emergency-restart.h | 7 | generic-y += emergency-restart.h |
| 7 | generic-y += exec.h | 8 | generic-y += exec.h |
| 8 | generic-y += extable.h | 9 | generic-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 | |||
| 19 | extern const struct dma_map_ops xtensa_dma_map_ops; | ||
| 20 | |||
| 21 | static 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 | ||
| 30 | static void do_cache_op(dma_addr_t dma_handle, size_t size, | 28 | static 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 | ||
| 52 | static void xtensa_sync_single_for_cpu(struct device *dev, | 50 | void 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 | ||
| 71 | static void xtensa_sync_single_for_device(struct device *dev, | 68 | void 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 | ||
| 91 | static 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 | |||
| 104 | static 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 | ||
| 122 | static void *xtensa_dma_alloc(struct device *dev, size_t size, | 92 | void *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 | ||
| 174 | static void xtensa_dma_free(struct device *dev, size_t size, void *vaddr, | 143 | void 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 | |||
| 196 | static 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 | |||
| 209 | static 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 | |||
| 217 | static 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 | |||
| 231 | static 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 | |||
| 245 | int xtensa_dma_mapping_error(struct device *dev, dma_addr_t dma_addr) | ||
| 246 | { | ||
| 247 | return 0; | ||
| 248 | } | ||
| 249 | |||
| 250 | const 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 | }; | ||
| 263 | EXPORT_SYMBOL(xtensa_dma_map_ops); | ||
