diff options
| author | David Daney <ddaney@caviumnetworks.com> | 2010-10-01 16:27:32 -0400 |
|---|---|---|
| committer | Ralf Baechle <ralf@linux-mips.org> | 2010-10-29 14:08:31 -0400 |
| commit | 48e1fd5a81416a037f5a48120bf281102f2584e2 (patch) | |
| tree | c5c4bd344f50493bb1d1c36d485300e9061c5aa2 | |
| parent | 43e4f7ae4b4a96b5e84f6e1592d2e9353138e88c (diff) | |
MIPS: Convert DMA to use dma-mapping-common.h
Use asm-generic/dma-mapping-common.h to handle all DMA mapping operations
and establish a default get_dma_ops() that forwards all operations to the
existing code.
Augment dev_archdata to carry a pointer to the struct dma_map_ops, allowing
DMA operations to be overridden on a per device basis. Currently this is
never filled in, so the default dma_map_ops are used. A follow-on patch
sets this for Octeon PCI devices.
Also initialize the dma_debug system as it is now used if it is configured.
Includes fixes by Kevin Cernekee <cernekee@gmail.com>.
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Patchwork: http://patchwork.linux-mips.org/patch/1637/
Patchwork: http://patchwork.linux-mips.org/patch/1678/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
| -rw-r--r-- | arch/mips/Kconfig | 2 | ||||
| -rw-r--r-- | arch/mips/include/asm/device.h | 15 | ||||
| -rw-r--r-- | arch/mips/include/asm/dma-mapping.h | 96 | ||||
| -rw-r--r-- | arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h | 2 | ||||
| -rw-r--r-- | arch/mips/include/asm/mach-ip27/dma-coherence.h | 3 | ||||
| -rw-r--r-- | arch/mips/include/asm/mach-ip32/dma-coherence.h | 3 | ||||
| -rw-r--r-- | arch/mips/include/asm/mach-jazz/dma-coherence.h | 3 | ||||
| -rw-r--r-- | arch/mips/mm/dma-default.c | 165 |
8 files changed, 136 insertions, 153 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 4d4744f07e52..535a08ad69b3 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
| @@ -14,6 +14,8 @@ config MIPS | |||
| 14 | select HAVE_KRETPROBES | 14 | select HAVE_KRETPROBES |
| 15 | select RTC_LIB if !MACH_LOONGSON | 15 | select RTC_LIB if !MACH_LOONGSON |
| 16 | select GENERIC_ATOMIC64 if !64BIT | 16 | select GENERIC_ATOMIC64 if !64BIT |
| 17 | select HAVE_DMA_ATTRS | ||
| 18 | select HAVE_DMA_API_DEBUG | ||
| 17 | 19 | ||
| 18 | menu "Machine selection" | 20 | menu "Machine selection" |
| 19 | 21 | ||
diff --git a/arch/mips/include/asm/device.h b/arch/mips/include/asm/device.h index 06746c5e8099..c94fafba9e62 100644 --- a/arch/mips/include/asm/device.h +++ b/arch/mips/include/asm/device.h | |||
| @@ -3,4 +3,17 @@ | |||
| 3 | * | 3 | * |
| 4 | * This file is released under the GPLv2 | 4 | * This file is released under the GPLv2 |
| 5 | */ | 5 | */ |
| 6 | #include <asm-generic/device.h> | 6 | #ifndef _ASM_MIPS_DEVICE_H |
| 7 | #define _ASM_MIPS_DEVICE_H | ||
| 8 | |||
| 9 | struct dma_map_ops; | ||
| 10 | |||
| 11 | struct dev_archdata { | ||
| 12 | /* DMA operations on that device */ | ||
| 13 | struct dma_map_ops *dma_ops; | ||
| 14 | }; | ||
| 15 | |||
| 16 | struct pdev_archdata { | ||
| 17 | }; | ||
| 18 | |||
| 19 | #endif /* _ASM_MIPS_DEVICE_H*/ | ||
diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h index 18fbf7af8e93..655f849bd08d 100644 --- a/arch/mips/include/asm/dma-mapping.h +++ b/arch/mips/include/asm/dma-mapping.h | |||
| @@ -5,51 +5,41 @@ | |||
| 5 | #include <asm/cache.h> | 5 | #include <asm/cache.h> |
| 6 | #include <asm-generic/dma-coherent.h> | 6 | #include <asm-generic/dma-coherent.h> |
| 7 | 7 | ||
| 8 | void *dma_alloc_noncoherent(struct device *dev, size_t size, | 8 | #include <dma-coherence.h> |
| 9 | dma_addr_t *dma_handle, gfp_t flag); | ||
| 10 | 9 | ||
| 11 | void dma_free_noncoherent(struct device *dev, size_t size, | 10 | extern struct dma_map_ops *mips_dma_map_ops; |
| 12 | void *vaddr, dma_addr_t dma_handle); | ||
| 13 | 11 | ||
| 14 | void *dma_alloc_coherent(struct device *dev, size_t size, | 12 | static inline struct dma_map_ops *get_dma_ops(struct device *dev) |
| 15 | dma_addr_t *dma_handle, gfp_t flag); | 13 | { |
| 14 | if (dev && dev->archdata.dma_ops) | ||
| 15 | return dev->archdata.dma_ops; | ||
| 16 | else | ||
| 17 | return mips_dma_map_ops; | ||
| 18 | } | ||
| 16 | 19 | ||
| 17 | void dma_free_coherent(struct device *dev, size_t size, | 20 | static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) |
| 18 | void *vaddr, dma_addr_t dma_handle); | 21 | { |
| 22 | if (!dev->dma_mask) | ||
| 23 | return 0; | ||
| 19 | 24 | ||
| 20 | extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | 25 | return addr + size <= *dev->dma_mask; |
| 21 | enum dma_data_direction direction); | 26 | } |
| 22 | extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, | 27 | |
| 23 | size_t size, enum dma_data_direction direction); | 28 | static inline void dma_mark_clean(void *addr, size_t size) {} |
| 24 | extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | 29 | |
| 25 | enum dma_data_direction direction); | 30 | #include <asm-generic/dma-mapping-common.h> |
| 26 | extern dma_addr_t dma_map_page(struct device *dev, struct page *page, | 31 | |
| 27 | unsigned long offset, size_t size, enum dma_data_direction direction); | 32 | static inline int dma_supported(struct device *dev, u64 mask) |
| 28 | |||
| 29 | static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address, | ||
| 30 | size_t size, enum dma_data_direction direction) | ||
| 31 | { | 33 | { |
| 32 | dma_unmap_single(dev, dma_address, size, direction); | 34 | struct dma_map_ops *ops = get_dma_ops(dev); |
| 35 | return ops->dma_supported(dev, mask); | ||
| 33 | } | 36 | } |
| 34 | 37 | ||
| 35 | extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg, | 38 | static inline int dma_mapping_error(struct device *dev, u64 mask) |
| 36 | int nhwentries, enum dma_data_direction direction); | 39 | { |
| 37 | extern void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, | 40 | struct dma_map_ops *ops = get_dma_ops(dev); |
| 38 | size_t size, enum dma_data_direction direction); | 41 | return ops->mapping_error(dev, mask); |
| 39 | extern void dma_sync_single_for_device(struct device *dev, | 42 | } |
| 40 | dma_addr_t dma_handle, size_t size, enum dma_data_direction direction); | ||
| 41 | extern void dma_sync_single_range_for_cpu(struct device *dev, | ||
| 42 | dma_addr_t dma_handle, unsigned long offset, size_t size, | ||
| 43 | enum dma_data_direction direction); | ||
| 44 | extern void dma_sync_single_range_for_device(struct device *dev, | ||
| 45 | dma_addr_t dma_handle, unsigned long offset, size_t size, | ||
| 46 | enum dma_data_direction direction); | ||
| 47 | extern void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, | ||
| 48 | int nelems, enum dma_data_direction direction); | ||
| 49 | extern void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, | ||
| 50 | int nelems, enum dma_data_direction direction); | ||
| 51 | extern int dma_mapping_error(struct device *dev, dma_addr_t dma_addr); | ||
| 52 | extern int dma_supported(struct device *dev, u64 mask); | ||
| 53 | 43 | ||
| 54 | static inline int | 44 | static inline int |
| 55 | dma_set_mask(struct device *dev, u64 mask) | 45 | dma_set_mask(struct device *dev, u64 mask) |
| @@ -65,4 +55,34 @@ dma_set_mask(struct device *dev, u64 mask) | |||
| 65 | extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size, | 55 | extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size, |
| 66 | enum dma_data_direction direction); | 56 | enum dma_data_direction direction); |
| 67 | 57 | ||
| 58 | static inline void *dma_alloc_coherent(struct device *dev, size_t size, | ||
| 59 | dma_addr_t *dma_handle, gfp_t gfp) | ||
| 60 | { | ||
| 61 | void *ret; | ||
| 62 | struct dma_map_ops *ops = get_dma_ops(dev); | ||
| 63 | |||
| 64 | ret = ops->alloc_coherent(dev, size, dma_handle, gfp); | ||
| 65 | |||
| 66 | debug_dma_alloc_coherent(dev, size, *dma_handle, ret); | ||
| 67 | |||
| 68 | return ret; | ||
| 69 | } | ||
| 70 | |||
| 71 | static inline void dma_free_coherent(struct device *dev, size_t size, | ||
| 72 | void *vaddr, dma_addr_t dma_handle) | ||
| 73 | { | ||
| 74 | struct dma_map_ops *ops = get_dma_ops(dev); | ||
| 75 | |||
| 76 | ops->free_coherent(dev, size, vaddr, dma_handle); | ||
| 77 | |||
| 78 | debug_dma_free_coherent(dev, size, vaddr, dma_handle); | ||
| 79 | } | ||
| 80 | |||
| 81 | |||
| 82 | void *dma_alloc_noncoherent(struct device *dev, size_t size, | ||
| 83 | dma_addr_t *dma_handle, gfp_t flag); | ||
| 84 | |||
| 85 | void dma_free_noncoherent(struct device *dev, size_t size, | ||
| 86 | void *vaddr, dma_addr_t dma_handle); | ||
| 87 | |||
| 68 | #endif /* _ASM_DMA_MAPPING_H */ | 88 | #endif /* _ASM_DMA_MAPPING_H */ |
diff --git a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h index 17d579471ec4..f768f6fe712e 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h +++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h | |||
| @@ -27,7 +27,7 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, | |||
| 27 | static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, | 27 | static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, |
| 28 | struct page *page) | 28 | struct page *page) |
| 29 | { | 29 | { |
| 30 | return octeon_map_dma_mem(dev, page_address(page), PAGE_SIZE); | 30 | BUG(); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | static inline unsigned long plat_dma_addr_to_phys(struct device *dev, | 33 | static inline unsigned long plat_dma_addr_to_phys(struct device *dev, |
diff --git a/arch/mips/include/asm/mach-ip27/dma-coherence.h b/arch/mips/include/asm/mach-ip27/dma-coherence.h index 7aa5ef9c19bc..016d0989b141 100644 --- a/arch/mips/include/asm/mach-ip27/dma-coherence.h +++ b/arch/mips/include/asm/mach-ip27/dma-coherence.h | |||
| @@ -26,7 +26,8 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, | |||
| 26 | return pa; | 26 | return pa; |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) | 29 | static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, |
| 30 | struct page *page) | ||
| 30 | { | 31 | { |
| 31 | dma_addr_t pa = dev_to_baddr(dev, page_to_phys(page)); | 32 | dma_addr_t pa = dev_to_baddr(dev, page_to_phys(page)); |
| 32 | 33 | ||
diff --git a/arch/mips/include/asm/mach-ip32/dma-coherence.h b/arch/mips/include/asm/mach-ip32/dma-coherence.h index 55123fc0b2f0..c8fb5aacf50a 100644 --- a/arch/mips/include/asm/mach-ip32/dma-coherence.h +++ b/arch/mips/include/asm/mach-ip32/dma-coherence.h | |||
| @@ -37,7 +37,8 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, | |||
| 37 | return pa; | 37 | return pa; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) | 40 | static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, |
| 41 | struct page *page) | ||
| 41 | { | 42 | { |
| 42 | dma_addr_t pa; | 43 | dma_addr_t pa; |
| 43 | 44 | ||
diff --git a/arch/mips/include/asm/mach-jazz/dma-coherence.h b/arch/mips/include/asm/mach-jazz/dma-coherence.h index 2a10920473ec..302101b54acb 100644 --- a/arch/mips/include/asm/mach-jazz/dma-coherence.h +++ b/arch/mips/include/asm/mach-jazz/dma-coherence.h | |||
| @@ -17,7 +17,8 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t | |||
| 17 | return vdma_alloc(virt_to_phys(addr), size); | 17 | return vdma_alloc(virt_to_phys(addr), size); |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) | 20 | static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, |
| 21 | struct page *page) | ||
| 21 | { | 22 | { |
| 22 | return vdma_alloc(page_to_phys(page), PAGE_SIZE); | 23 | return vdma_alloc(page_to_phys(page), PAGE_SIZE); |
| 23 | } | 24 | } |
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 469d4019f795..4fc1a0fbe007 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c | |||
| @@ -95,10 +95,9 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size, | |||
| 95 | 95 | ||
| 96 | return ret; | 96 | return ret; |
| 97 | } | 97 | } |
| 98 | |||
| 99 | EXPORT_SYMBOL(dma_alloc_noncoherent); | 98 | EXPORT_SYMBOL(dma_alloc_noncoherent); |
| 100 | 99 | ||
| 101 | void *dma_alloc_coherent(struct device *dev, size_t size, | 100 | static void *mips_dma_alloc_coherent(struct device *dev, size_t size, |
| 102 | dma_addr_t * dma_handle, gfp_t gfp) | 101 | dma_addr_t * dma_handle, gfp_t gfp) |
| 103 | { | 102 | { |
| 104 | void *ret; | 103 | void *ret; |
| @@ -123,7 +122,6 @@ void *dma_alloc_coherent(struct device *dev, size_t size, | |||
| 123 | return ret; | 122 | return ret; |
| 124 | } | 123 | } |
| 125 | 124 | ||
| 126 | EXPORT_SYMBOL(dma_alloc_coherent); | ||
| 127 | 125 | ||
| 128 | void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, | 126 | void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, |
| 129 | dma_addr_t dma_handle) | 127 | dma_addr_t dma_handle) |
| @@ -131,10 +129,9 @@ void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, | |||
| 131 | plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL); | 129 | plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL); |
| 132 | free_pages((unsigned long) vaddr, get_order(size)); | 130 | free_pages((unsigned long) vaddr, get_order(size)); |
| 133 | } | 131 | } |
| 134 | |||
| 135 | EXPORT_SYMBOL(dma_free_noncoherent); | 132 | EXPORT_SYMBOL(dma_free_noncoherent); |
| 136 | 133 | ||
| 137 | void dma_free_coherent(struct device *dev, size_t size, void *vaddr, | 134 | static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr, |
| 138 | dma_addr_t dma_handle) | 135 | dma_addr_t dma_handle) |
| 139 | { | 136 | { |
| 140 | unsigned long addr = (unsigned long) vaddr; | 137 | unsigned long addr = (unsigned long) vaddr; |
| @@ -151,8 +148,6 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr, | |||
| 151 | free_pages(addr, get_order(size)); | 148 | free_pages(addr, get_order(size)); |
| 152 | } | 149 | } |
| 153 | 150 | ||
| 154 | EXPORT_SYMBOL(dma_free_coherent); | ||
| 155 | |||
| 156 | static inline void __dma_sync(unsigned long addr, size_t size, | 151 | static inline void __dma_sync(unsigned long addr, size_t size, |
| 157 | enum dma_data_direction direction) | 152 | enum dma_data_direction direction) |
| 158 | { | 153 | { |
| @@ -174,21 +169,8 @@ static inline void __dma_sync(unsigned long addr, size_t size, | |||
| 174 | } | 169 | } |
| 175 | } | 170 | } |
| 176 | 171 | ||
| 177 | dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | 172 | static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, |
| 178 | enum dma_data_direction direction) | 173 | size_t size, enum dma_data_direction direction, struct dma_attrs *attrs) |
| 179 | { | ||
| 180 | unsigned long addr = (unsigned long) ptr; | ||
| 181 | |||
| 182 | if (!plat_device_is_coherent(dev)) | ||
| 183 | __dma_sync(addr, size, direction); | ||
| 184 | |||
| 185 | return plat_map_dma_mem(dev, ptr, size); | ||
| 186 | } | ||
| 187 | |||
| 188 | EXPORT_SYMBOL(dma_map_single); | ||
| 189 | |||
| 190 | void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | ||
| 191 | enum dma_data_direction direction) | ||
| 192 | { | 174 | { |
| 193 | if (cpu_is_noncoherent_r10000(dev)) | 175 | if (cpu_is_noncoherent_r10000(dev)) |
| 194 | __dma_sync(dma_addr_to_virt(dev, dma_addr), size, | 176 | __dma_sync(dma_addr_to_virt(dev, dma_addr), size, |
| @@ -197,15 +179,11 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | |||
| 197 | plat_unmap_dma_mem(dev, dma_addr, size, direction); | 179 | plat_unmap_dma_mem(dev, dma_addr, size, direction); |
| 198 | } | 180 | } |
| 199 | 181 | ||
| 200 | EXPORT_SYMBOL(dma_unmap_single); | 182 | static int mips_dma_map_sg(struct device *dev, struct scatterlist *sg, |
| 201 | 183 | int nents, enum dma_data_direction direction, struct dma_attrs *attrs) | |
| 202 | int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | ||
| 203 | enum dma_data_direction direction) | ||
| 204 | { | 184 | { |
| 205 | int i; | 185 | int i; |
| 206 | 186 | ||
| 207 | BUG_ON(direction == DMA_NONE); | ||
| 208 | |||
| 209 | for (i = 0; i < nents; i++, sg++) { | 187 | for (i = 0; i < nents; i++, sg++) { |
| 210 | unsigned long addr; | 188 | unsigned long addr; |
| 211 | 189 | ||
| @@ -219,33 +197,27 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | |||
| 219 | return nents; | 197 | return nents; |
| 220 | } | 198 | } |
| 221 | 199 | ||
| 222 | EXPORT_SYMBOL(dma_map_sg); | 200 | static dma_addr_t mips_dma_map_page(struct device *dev, struct page *page, |
| 223 | 201 | unsigned long offset, size_t size, enum dma_data_direction direction, | |
| 224 | dma_addr_t dma_map_page(struct device *dev, struct page *page, | 202 | struct dma_attrs *attrs) |
| 225 | unsigned long offset, size_t size, enum dma_data_direction direction) | ||
| 226 | { | 203 | { |
| 227 | BUG_ON(direction == DMA_NONE); | 204 | unsigned long addr; |
| 228 | 205 | ||
| 229 | if (!plat_device_is_coherent(dev)) { | 206 | addr = (unsigned long) page_address(page) + offset; |
| 230 | unsigned long addr; | ||
| 231 | 207 | ||
| 232 | addr = (unsigned long) page_address(page) + offset; | 208 | if (!plat_device_is_coherent(dev)) |
| 233 | __dma_sync(addr, size, direction); | 209 | __dma_sync(addr, size, direction); |
| 234 | } | ||
| 235 | 210 | ||
| 236 | return plat_map_dma_mem_page(dev, page) + offset; | 211 | return plat_map_dma_mem(dev, (void *)addr, size); |
| 237 | } | 212 | } |
| 238 | 213 | ||
| 239 | EXPORT_SYMBOL(dma_map_page); | 214 | static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg, |
| 240 | 215 | int nhwentries, enum dma_data_direction direction, | |
| 241 | void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | 216 | struct dma_attrs *attrs) |
| 242 | enum dma_data_direction direction) | ||
| 243 | { | 217 | { |
| 244 | unsigned long addr; | 218 | unsigned long addr; |
| 245 | int i; | 219 | int i; |
| 246 | 220 | ||
| 247 | BUG_ON(direction == DMA_NONE); | ||
| 248 | |||
| 249 | for (i = 0; i < nhwentries; i++, sg++) { | 221 | for (i = 0; i < nhwentries; i++, sg++) { |
| 250 | if (!plat_device_is_coherent(dev) && | 222 | if (!plat_device_is_coherent(dev) && |
| 251 | direction != DMA_TO_DEVICE) { | 223 | direction != DMA_TO_DEVICE) { |
| @@ -257,13 +229,9 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | |||
| 257 | } | 229 | } |
| 258 | } | 230 | } |
| 259 | 231 | ||
| 260 | EXPORT_SYMBOL(dma_unmap_sg); | 232 | static void mips_dma_sync_single_for_cpu(struct device *dev, |
| 261 | 233 | dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) | |
| 262 | void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, | ||
| 263 | size_t size, enum dma_data_direction direction) | ||
| 264 | { | 234 | { |
| 265 | BUG_ON(direction == DMA_NONE); | ||
| 266 | |||
| 267 | if (cpu_is_noncoherent_r10000(dev)) { | 235 | if (cpu_is_noncoherent_r10000(dev)) { |
| 268 | unsigned long addr; | 236 | unsigned long addr; |
| 269 | 237 | ||
| @@ -272,13 +240,9 @@ void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, | |||
| 272 | } | 240 | } |
| 273 | } | 241 | } |
| 274 | 242 | ||
| 275 | EXPORT_SYMBOL(dma_sync_single_for_cpu); | 243 | static void mips_dma_sync_single_for_device(struct device *dev, |
| 276 | 244 | dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) | |
| 277 | void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, | ||
| 278 | size_t size, enum dma_data_direction direction) | ||
| 279 | { | 245 | { |
| 280 | BUG_ON(direction == DMA_NONE); | ||
| 281 | |||
| 282 | plat_extra_sync_for_device(dev); | 246 | plat_extra_sync_for_device(dev); |
| 283 | if (!plat_device_is_coherent(dev)) { | 247 | if (!plat_device_is_coherent(dev)) { |
| 284 | unsigned long addr; | 248 | unsigned long addr; |
| @@ -288,46 +252,11 @@ void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, | |||
| 288 | } | 252 | } |
| 289 | } | 253 | } |
| 290 | 254 | ||
| 291 | EXPORT_SYMBOL(dma_sync_single_for_device); | 255 | static void mips_dma_sync_sg_for_cpu(struct device *dev, |
| 292 | 256 | struct scatterlist *sg, int nelems, enum dma_data_direction direction) | |
| 293 | void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, | ||
| 294 | unsigned long offset, size_t size, enum dma_data_direction direction) | ||
| 295 | { | ||
| 296 | BUG_ON(direction == DMA_NONE); | ||
| 297 | |||
| 298 | if (cpu_is_noncoherent_r10000(dev)) { | ||
| 299 | unsigned long addr; | ||
| 300 | |||
| 301 | addr = dma_addr_to_virt(dev, dma_handle); | ||
| 302 | __dma_sync(addr + offset, size, direction); | ||
| 303 | } | ||
| 304 | } | ||
| 305 | |||
| 306 | EXPORT_SYMBOL(dma_sync_single_range_for_cpu); | ||
| 307 | |||
| 308 | void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, | ||
| 309 | unsigned long offset, size_t size, enum dma_data_direction direction) | ||
| 310 | { | ||
| 311 | BUG_ON(direction == DMA_NONE); | ||
| 312 | |||
| 313 | plat_extra_sync_for_device(dev); | ||
| 314 | if (!plat_device_is_coherent(dev)) { | ||
| 315 | unsigned long addr; | ||
| 316 | |||
| 317 | addr = dma_addr_to_virt(dev, dma_handle); | ||
| 318 | __dma_sync(addr + offset, size, direction); | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | EXPORT_SYMBOL(dma_sync_single_range_for_device); | ||
| 323 | |||
| 324 | void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, | ||
| 325 | enum dma_data_direction direction) | ||
| 326 | { | 257 | { |
| 327 | int i; | 258 | int i; |
| 328 | 259 | ||
| 329 | BUG_ON(direction == DMA_NONE); | ||
| 330 | |||
| 331 | /* Make sure that gcc doesn't leave the empty loop body. */ | 260 | /* Make sure that gcc doesn't leave the empty loop body. */ |
| 332 | for (i = 0; i < nelems; i++, sg++) { | 261 | for (i = 0; i < nelems; i++, sg++) { |
| 333 | if (cpu_is_noncoherent_r10000(dev)) | 262 | if (cpu_is_noncoherent_r10000(dev)) |
| @@ -336,15 +265,11 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, | |||
| 336 | } | 265 | } |
| 337 | } | 266 | } |
| 338 | 267 | ||
| 339 | EXPORT_SYMBOL(dma_sync_sg_for_cpu); | 268 | static void mips_dma_sync_sg_for_device(struct device *dev, |
| 340 | 269 | struct scatterlist *sg, int nelems, enum dma_data_direction direction) | |
| 341 | void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, | ||
| 342 | enum dma_data_direction direction) | ||
| 343 | { | 270 | { |
| 344 | int i; | 271 | int i; |
| 345 | 272 | ||
| 346 | BUG_ON(direction == DMA_NONE); | ||
| 347 | |||
| 348 | /* Make sure that gcc doesn't leave the empty loop body. */ | 273 | /* Make sure that gcc doesn't leave the empty loop body. */ |
| 349 | for (i = 0; i < nelems; i++, sg++) { | 274 | for (i = 0; i < nelems; i++, sg++) { |
| 350 | if (!plat_device_is_coherent(dev)) | 275 | if (!plat_device_is_coherent(dev)) |
| @@ -353,24 +278,18 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nele | |||
| 353 | } | 278 | } |
| 354 | } | 279 | } |
| 355 | 280 | ||
| 356 | EXPORT_SYMBOL(dma_sync_sg_for_device); | 281 | int mips_dma_mapping_error(struct device *dev, dma_addr_t dma_addr) |
| 357 | |||
| 358 | int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) | ||
| 359 | { | 282 | { |
| 360 | return plat_dma_mapping_error(dev, dma_addr); | 283 | return plat_dma_mapping_error(dev, dma_addr); |
| 361 | } | 284 | } |
| 362 | 285 | ||
| 363 | EXPORT_SYMBOL(dma_mapping_error); | 286 | int mips_dma_supported(struct device *dev, u64 mask) |
| 364 | |||
| 365 | int dma_supported(struct device *dev, u64 mask) | ||
| 366 | { | 287 | { |
| 367 | return plat_dma_supported(dev, mask); | 288 | return plat_dma_supported(dev, mask); |
| 368 | } | 289 | } |
| 369 | 290 | ||
| 370 | EXPORT_SYMBOL(dma_supported); | 291 | void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size, |
| 371 | 292 | enum dma_data_direction direction) | |
| 372 | void dma_cache_sync(struct device *dev, void *vaddr, size_t size, | ||
| 373 | enum dma_data_direction direction) | ||
| 374 | { | 293 | { |
| 375 | BUG_ON(direction == DMA_NONE); | 294 | BUG_ON(direction == DMA_NONE); |
| 376 | 295 | ||
| @@ -379,4 +298,30 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size, | |||
| 379 | __dma_sync((unsigned long)vaddr, size, direction); | 298 | __dma_sync((unsigned long)vaddr, size, direction); |
| 380 | } | 299 | } |
| 381 | 300 | ||
| 382 | EXPORT_SYMBOL(dma_cache_sync); | 301 | static struct dma_map_ops mips_default_dma_map_ops = { |
| 302 | .alloc_coherent = mips_dma_alloc_coherent, | ||
| 303 | .free_coherent = mips_dma_free_coherent, | ||
| 304 | .map_page = mips_dma_map_page, | ||
| 305 | .unmap_page = mips_dma_unmap_page, | ||
| 306 | .map_sg = mips_dma_map_sg, | ||
| 307 | .unmap_sg = mips_dma_unmap_sg, | ||
| 308 | .sync_single_for_cpu = mips_dma_sync_single_for_cpu, | ||
| 309 | .sync_single_for_device = mips_dma_sync_single_for_device, | ||
| 310 | .sync_sg_for_cpu = mips_dma_sync_sg_for_cpu, | ||
| 311 | .sync_sg_for_device = mips_dma_sync_sg_for_device, | ||
| 312 | .mapping_error = mips_dma_mapping_error, | ||
| 313 | .dma_supported = mips_dma_supported | ||
| 314 | }; | ||
| 315 | |||
| 316 | struct dma_map_ops *mips_dma_map_ops = &mips_default_dma_map_ops; | ||
| 317 | EXPORT_SYMBOL(mips_dma_map_ops); | ||
| 318 | |||
| 319 | #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) | ||
| 320 | |||
| 321 | static int __init mips_dma_init(void) | ||
| 322 | { | ||
| 323 | dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); | ||
| 324 | |||
| 325 | return 0; | ||
| 326 | } | ||
| 327 | fs_initcall(mips_dma_init); | ||
