diff options
| author | Christoph Hellwig <hch@lst.de> | 2016-01-20 18:01:29 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-20 20:09:18 -0500 |
| commit | a34a517ac96c6910a3a0aab9513035bfbed0020c (patch) | |
| tree | 2543525a6dbddc45bdd5ffad0cd60ad1e5e8239a | |
| parent | 052c96dbe33b032b949510ca724ed54d02e1255c (diff) | |
avr32: convert to dma_map_ops
Signed-off-by: Christoph Hellwig <hch@lst.de>
Cc: Haavard Skinnemoen <hskinnemoen@gmail.com>
Cc: Hans-Christian Egtvedt <egtvedt@samfundet.no>
Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: Joerg Roedel <jroedel@suse.de>
Cc: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | arch/avr32/Kconfig | 1 | ||||
| -rw-r--r-- | arch/avr32/include/asm/dma-mapping.h | 342 | ||||
| -rw-r--r-- | arch/avr32/mm/dma-coherent.c | 115 |
3 files changed, 85 insertions, 373 deletions
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index b6878eb64884..aac3d6972c30 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig | |||
| @@ -7,6 +7,7 @@ config AVR32 | |||
| 7 | select HAVE_OPROFILE | 7 | select HAVE_OPROFILE |
| 8 | select HAVE_KPROBES | 8 | select HAVE_KPROBES |
| 9 | select VIRT_TO_BUS | 9 | select VIRT_TO_BUS |
| 10 | select HAVE_DMA_ATTRS | ||
| 10 | select GENERIC_IRQ_PROBE | 11 | select GENERIC_IRQ_PROBE |
| 11 | select GENERIC_ATOMIC64 | 12 | select GENERIC_ATOMIC64 |
| 12 | select HARDIRQS_SW_RESEND | 13 | select HARDIRQS_SW_RESEND |
diff --git a/arch/avr32/include/asm/dma-mapping.h b/arch/avr32/include/asm/dma-mapping.h index ae7ac9205d20..0239ca84eb41 100644 --- a/arch/avr32/include/asm/dma-mapping.h +++ b/arch/avr32/include/asm/dma-mapping.h | |||
| @@ -1,350 +1,16 @@ | |||
| 1 | #ifndef __ASM_AVR32_DMA_MAPPING_H | 1 | #ifndef __ASM_AVR32_DMA_MAPPING_H |
| 2 | #define __ASM_AVR32_DMA_MAPPING_H | 2 | #define __ASM_AVR32_DMA_MAPPING_H |
| 3 | 3 | ||
| 4 | #include <linux/mm.h> | ||
| 5 | #include <linux/device.h> | ||
| 6 | #include <linux/scatterlist.h> | ||
| 7 | #include <asm/processor.h> | ||
| 8 | #include <asm/cacheflush.h> | ||
| 9 | #include <asm/io.h> | ||
| 10 | |||
| 11 | extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size, | 4 | extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size, |
| 12 | int direction); | 5 | int direction); |
| 13 | 6 | ||
| 14 | /* | 7 | extern struct dma_map_ops avr32_dma_ops; |
| 15 | * Return whether the given device DMA address mask can be supported | ||
| 16 | * properly. For example, if your device can only drive the low 24-bits | ||
| 17 | * during bus mastering, then you would pass 0x00ffffff as the mask | ||
| 18 | * to this function. | ||
| 19 | */ | ||
| 20 | static inline int dma_supported(struct device *dev, u64 mask) | ||
| 21 | { | ||
| 22 | /* Fix when needed. I really don't know of any limitations */ | ||
| 23 | return 1; | ||
| 24 | } | ||
| 25 | |||
| 26 | static inline int dma_set_mask(struct device *dev, u64 dma_mask) | ||
| 27 | { | ||
| 28 | if (!dev->dma_mask || !dma_supported(dev, dma_mask)) | ||
| 29 | return -EIO; | ||
| 30 | |||
| 31 | *dev->dma_mask = dma_mask; | ||
| 32 | return 0; | ||
| 33 | } | ||
| 34 | |||
| 35 | /* | ||
| 36 | * dma_map_single can't fail as it is implemented now. | ||
| 37 | */ | ||
| 38 | static inline int dma_mapping_error(struct device *dev, dma_addr_t addr) | ||
| 39 | { | ||
| 40 | return 0; | ||
| 41 | } | ||
| 42 | |||
| 43 | /** | ||
| 44 | * dma_alloc_coherent - allocate consistent memory for DMA | ||
| 45 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
| 46 | * @size: required memory size | ||
| 47 | * @handle: bus-specific DMA address | ||
| 48 | * | ||
| 49 | * Allocate some uncached, unbuffered memory for a device for | ||
| 50 | * performing DMA. This function allocates pages, and will | ||
| 51 | * return the CPU-viewed address, and sets @handle to be the | ||
| 52 | * device-viewed address. | ||
| 53 | */ | ||
| 54 | extern void *dma_alloc_coherent(struct device *dev, size_t size, | ||
| 55 | dma_addr_t *handle, gfp_t gfp); | ||
| 56 | |||
| 57 | /** | ||
| 58 | * dma_free_coherent - free memory allocated by dma_alloc_coherent | ||
| 59 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
| 60 | * @size: size of memory originally requested in dma_alloc_coherent | ||
| 61 | * @cpu_addr: CPU-view address returned from dma_alloc_coherent | ||
| 62 | * @handle: device-view address returned from dma_alloc_coherent | ||
| 63 | * | ||
| 64 | * Free (and unmap) a DMA buffer previously allocated by | ||
| 65 | * dma_alloc_coherent(). | ||
| 66 | * | ||
| 67 | * References to memory and mappings associated with cpu_addr/handle | ||
| 68 | * during and after this call executing are illegal. | ||
| 69 | */ | ||
| 70 | extern void dma_free_coherent(struct device *dev, size_t size, | ||
| 71 | void *cpu_addr, dma_addr_t handle); | ||
| 72 | |||
| 73 | /** | ||
| 74 | * dma_alloc_writecombine - allocate write-combining memory for DMA | ||
| 75 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
| 76 | * @size: required memory size | ||
| 77 | * @handle: bus-specific DMA address | ||
| 78 | * | ||
| 79 | * Allocate some uncached, buffered memory for a device for | ||
| 80 | * performing DMA. This function allocates pages, and will | ||
| 81 | * return the CPU-viewed address, and sets @handle to be the | ||
| 82 | * device-viewed address. | ||
| 83 | */ | ||
| 84 | extern void *dma_alloc_writecombine(struct device *dev, size_t size, | ||
| 85 | dma_addr_t *handle, gfp_t gfp); | ||
| 86 | |||
| 87 | /** | ||
| 88 | * dma_free_coherent - free memory allocated by dma_alloc_writecombine | ||
| 89 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
| 90 | * @size: size of memory originally requested in dma_alloc_writecombine | ||
| 91 | * @cpu_addr: CPU-view address returned from dma_alloc_writecombine | ||
| 92 | * @handle: device-view address returned from dma_alloc_writecombine | ||
| 93 | * | ||
| 94 | * Free (and unmap) a DMA buffer previously allocated by | ||
| 95 | * dma_alloc_writecombine(). | ||
| 96 | * | ||
| 97 | * References to memory and mappings associated with cpu_addr/handle | ||
| 98 | * during and after this call executing are illegal. | ||
| 99 | */ | ||
| 100 | extern void dma_free_writecombine(struct device *dev, size_t size, | ||
| 101 | void *cpu_addr, dma_addr_t handle); | ||
| 102 | |||
| 103 | /** | ||
| 104 | * dma_map_single - map a single buffer for streaming DMA | ||
| 105 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
| 106 | * @cpu_addr: CPU direct mapped address of buffer | ||
| 107 | * @size: size of buffer to map | ||
| 108 | * @dir: DMA transfer direction | ||
| 109 | * | ||
| 110 | * Ensure that any data held in the cache is appropriately discarded | ||
| 111 | * or written back. | ||
| 112 | * | ||
| 113 | * The device owns this memory once this call has completed. The CPU | ||
| 114 | * can regain ownership by calling dma_unmap_single() or dma_sync_single(). | ||
| 115 | */ | ||
| 116 | static inline dma_addr_t | ||
| 117 | dma_map_single(struct device *dev, void *cpu_addr, size_t size, | ||
| 118 | enum dma_data_direction direction) | ||
| 119 | { | ||
| 120 | dma_cache_sync(dev, cpu_addr, size, direction); | ||
| 121 | return virt_to_bus(cpu_addr); | ||
| 122 | } | ||
| 123 | |||
| 124 | /** | ||
| 125 | * dma_unmap_single - unmap a single buffer previously mapped | ||
| 126 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
| 127 | * @handle: DMA address of buffer | ||
| 128 | * @size: size of buffer to map | ||
| 129 | * @dir: DMA transfer direction | ||
| 130 | * | ||
| 131 | * Unmap a single streaming mode DMA translation. The handle and size | ||
| 132 | * must match what was provided in the previous dma_map_single() call. | ||
| 133 | * All other usages are undefined. | ||
| 134 | * | ||
| 135 | * After this call, reads by the CPU to the buffer are guaranteed to see | ||
| 136 | * whatever the device wrote there. | ||
| 137 | */ | ||
| 138 | static inline void | ||
| 139 | dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | ||
| 140 | enum dma_data_direction direction) | ||
| 141 | { | ||
| 142 | |||
| 143 | } | ||
| 144 | |||
| 145 | /** | ||
| 146 | * dma_map_page - map a portion of a page for streaming DMA | ||
| 147 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
| 148 | * @page: page that buffer resides in | ||
| 149 | * @offset: offset into page for start of buffer | ||
| 150 | * @size: size of buffer to map | ||
| 151 | * @dir: DMA transfer direction | ||
| 152 | * | ||
| 153 | * Ensure that any data held in the cache is appropriately discarded | ||
| 154 | * or written back. | ||
| 155 | * | ||
| 156 | * The device owns this memory once this call has completed. The CPU | ||
| 157 | * can regain ownership by calling dma_unmap_page() or dma_sync_single(). | ||
| 158 | */ | ||
| 159 | static inline dma_addr_t | ||
| 160 | dma_map_page(struct device *dev, struct page *page, | ||
| 161 | unsigned long offset, size_t size, | ||
| 162 | enum dma_data_direction direction) | ||
| 163 | { | ||
| 164 | return dma_map_single(dev, page_address(page) + offset, | ||
| 165 | size, direction); | ||
| 166 | } | ||
| 167 | |||
| 168 | /** | ||
| 169 | * dma_unmap_page - unmap a buffer previously mapped through dma_map_page() | ||
| 170 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
| 171 | * @handle: DMA address of buffer | ||
| 172 | * @size: size of buffer to map | ||
| 173 | * @dir: DMA transfer direction | ||
| 174 | * | ||
| 175 | * Unmap a single streaming mode DMA translation. The handle and size | ||
| 176 | * must match what was provided in the previous dma_map_single() call. | ||
| 177 | * All other usages are undefined. | ||
| 178 | * | ||
| 179 | * After this call, reads by the CPU to the buffer are guaranteed to see | ||
| 180 | * whatever the device wrote there. | ||
| 181 | */ | ||
| 182 | static inline void | ||
| 183 | dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, | ||
| 184 | enum dma_data_direction direction) | ||
| 185 | { | ||
| 186 | dma_unmap_single(dev, dma_address, size, direction); | ||
| 187 | } | ||
| 188 | |||
| 189 | /** | ||
| 190 | * dma_map_sg - map a set of SG buffers for streaming mode DMA | ||
| 191 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
| 192 | * @sg: list of buffers | ||
| 193 | * @nents: number of buffers to map | ||
| 194 | * @dir: DMA transfer direction | ||
| 195 | * | ||
| 196 | * Map a set of buffers described by scatterlist in streaming | ||
| 197 | * mode for DMA. This is the scatter-gather version of the | ||
| 198 | * above pci_map_single interface. Here the scatter gather list | ||
| 199 | * elements are each tagged with the appropriate dma address | ||
| 200 | * and length. They are obtained via sg_dma_{address,length}(SG). | ||
| 201 | * | ||
| 202 | * NOTE: An implementation may be able to use a smaller number of | ||
| 203 | * DMA address/length pairs than there are SG table elements. | ||
| 204 | * (for example via virtual mapping capabilities) | ||
| 205 | * The routine returns the number of addr/length pairs actually | ||
| 206 | * used, at most nents. | ||
| 207 | * | ||
| 208 | * Device ownership issues as mentioned above for pci_map_single are | ||
| 209 | * the same here. | ||
| 210 | */ | ||
| 211 | static inline int | ||
| 212 | dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, | ||
| 213 | enum dma_data_direction direction) | ||
| 214 | { | ||
| 215 | int i; | ||
| 216 | struct scatterlist *sg; | ||
| 217 | |||
| 218 | for_each_sg(sglist, sg, nents, i) { | ||
| 219 | char *virt; | ||
| 220 | |||
| 221 | sg->dma_address = page_to_bus(sg_page(sg)) + sg->offset; | ||
| 222 | virt = sg_virt(sg); | ||
| 223 | dma_cache_sync(dev, virt, sg->length, direction); | ||
| 224 | } | ||
| 225 | |||
| 226 | return nents; | ||
| 227 | } | ||
| 228 | |||
| 229 | /** | ||
| 230 | * dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg | ||
| 231 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
| 232 | * @sg: list of buffers | ||
| 233 | * @nents: number of buffers to map | ||
| 234 | * @dir: DMA transfer direction | ||
| 235 | * | ||
| 236 | * Unmap a set of streaming mode DMA translations. | ||
| 237 | * Again, CPU read rules concerning calls here are the same as for | ||
| 238 | * pci_unmap_single() above. | ||
| 239 | */ | ||
| 240 | static inline void | ||
| 241 | dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | ||
| 242 | enum dma_data_direction direction) | ||
| 243 | { | ||
| 244 | |||
| 245 | } | ||
| 246 | |||
| 247 | /** | ||
| 248 | * dma_sync_single_for_cpu | ||
| 249 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
| 250 | * @handle: DMA address of buffer | ||
| 251 | * @size: size of buffer to map | ||
| 252 | * @dir: DMA transfer direction | ||
| 253 | * | ||
| 254 | * Make physical memory consistent for a single streaming mode DMA | ||
| 255 | * translation after a transfer. | ||
| 256 | * | ||
| 257 | * If you perform a dma_map_single() but wish to interrogate the | ||
| 258 | * buffer using the cpu, yet do not wish to teardown the DMA mapping, | ||
| 259 | * you must call this function before doing so. At the next point you | ||
| 260 | * give the DMA address back to the card, you must first perform a | ||
| 261 | * dma_sync_single_for_device, and then the device again owns the | ||
| 262 | * buffer. | ||
| 263 | */ | ||
| 264 | static inline void | ||
| 265 | dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, | ||
| 266 | size_t size, enum dma_data_direction direction) | ||
| 267 | { | ||
| 268 | /* | ||
| 269 | * No need to do anything since the CPU isn't supposed to | ||
| 270 | * touch this memory after we flushed it at mapping- or | ||
| 271 | * sync-for-device time. | ||
| 272 | */ | ||
| 273 | } | ||
| 274 | |||
| 275 | static inline void | ||
| 276 | dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, | ||
| 277 | size_t size, enum dma_data_direction direction) | ||
| 278 | { | ||
| 279 | dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction); | ||
| 280 | } | ||
| 281 | |||
| 282 | static inline void | ||
| 283 | dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, | ||
| 284 | unsigned long offset, size_t size, | ||
| 285 | enum dma_data_direction direction) | ||
| 286 | { | ||
| 287 | /* just sync everything, that's all the pci API can do */ | ||
| 288 | dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction); | ||
| 289 | } | ||
| 290 | |||
| 291 | static inline void | ||
| 292 | dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, | ||
| 293 | unsigned long offset, size_t size, | ||
| 294 | enum dma_data_direction direction) | ||
| 295 | { | ||
| 296 | /* just sync everything, that's all the pci API can do */ | ||
| 297 | dma_sync_single_for_device(dev, dma_handle, offset+size, direction); | ||
| 298 | } | ||
| 299 | 8 | ||
| 300 | /** | 9 | static inline struct dma_map_ops *get_dma_ops(struct device *dev) |
| 301 | * dma_sync_sg_for_cpu | ||
| 302 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | ||
| 303 | * @sg: list of buffers | ||
| 304 | * @nents: number of buffers to map | ||
| 305 | * @dir: DMA transfer direction | ||
| 306 | * | ||
| 307 | * Make physical memory consistent for a set of streaming | ||
| 308 | * mode DMA translations after a transfer. | ||
| 309 | * | ||
| 310 | * The same as dma_sync_single_for_* but for a scatter-gather list, | ||
| 311 | * same rules and usage. | ||
| 312 | */ | ||
| 313 | static inline void | ||
| 314 | dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, | ||
| 315 | int nents, enum dma_data_direction direction) | ||
| 316 | { | 10 | { |
| 317 | /* | 11 | return &avr32_dma_ops; |
| 318 | * No need to do anything since the CPU isn't supposed to | ||
| 319 | * touch this memory after we flushed it at mapping- or | ||
| 320 | * sync-for-device time. | ||
| 321 | */ | ||
| 322 | } | 12 | } |
| 323 | 13 | ||
| 324 | static inline void | 14 | #include <asm-generic/dma-mapping-common.h> |
| 325 | dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist, | ||
| 326 | int nents, enum dma_data_direction direction) | ||
| 327 | { | ||
| 328 | int i; | ||
| 329 | struct scatterlist *sg; | ||
| 330 | |||
| 331 | for_each_sg(sglist, sg, nents, i) | ||
| 332 | dma_cache_sync(dev, sg_virt(sg), sg->length, direction); | ||
| 333 | } | ||
| 334 | |||
| 335 | /* Now for the API extensions over the pci_ one */ | ||
| 336 | |||
| 337 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) | ||
| 338 | #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) | ||
| 339 | |||
| 340 | /* drivers/base/dma-mapping.c */ | ||
| 341 | extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, | ||
| 342 | void *cpu_addr, dma_addr_t dma_addr, size_t size); | ||
| 343 | extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt, | ||
| 344 | void *cpu_addr, dma_addr_t dma_addr, | ||
| 345 | size_t size); | ||
| 346 | |||
| 347 | #define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s) | ||
| 348 | #define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s) | ||
| 349 | 15 | ||
| 350 | #endif /* __ASM_AVR32_DMA_MAPPING_H */ | 16 | #endif /* __ASM_AVR32_DMA_MAPPING_H */ |
diff --git a/arch/avr32/mm/dma-coherent.c b/arch/avr32/mm/dma-coherent.c index 50cdb5b10f0f..92cf1fb2b3e6 100644 --- a/arch/avr32/mm/dma-coherent.c +++ b/arch/avr32/mm/dma-coherent.c | |||
| @@ -9,9 +9,14 @@ | |||
| 9 | #include <linux/dma-mapping.h> | 9 | #include <linux/dma-mapping.h> |
| 10 | #include <linux/gfp.h> | 10 | #include <linux/gfp.h> |
| 11 | #include <linux/export.h> | 11 | #include <linux/export.h> |
| 12 | #include <linux/mm.h> | ||
| 13 | #include <linux/device.h> | ||
| 14 | #include <linux/scatterlist.h> | ||
| 12 | 15 | ||
| 13 | #include <asm/addrspace.h> | 16 | #include <asm/processor.h> |
| 14 | #include <asm/cacheflush.h> | 17 | #include <asm/cacheflush.h> |
| 18 | #include <asm/io.h> | ||
| 19 | #include <asm/addrspace.h> | ||
| 15 | 20 | ||
| 16 | void dma_cache_sync(struct device *dev, void *vaddr, size_t size, int direction) | 21 | void dma_cache_sync(struct device *dev, void *vaddr, size_t size, int direction) |
| 17 | { | 22 | { |
| @@ -93,60 +98,100 @@ static void __dma_free(struct device *dev, size_t size, | |||
| 93 | __free_page(page++); | 98 | __free_page(page++); |
| 94 | } | 99 | } |
| 95 | 100 | ||
| 96 | void *dma_alloc_coherent(struct device *dev, size_t size, | 101 | static void *avr32_dma_alloc(struct device *dev, size_t size, |
| 97 | dma_addr_t *handle, gfp_t gfp) | 102 | dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs) |
| 98 | { | 103 | { |
| 99 | struct page *page; | 104 | struct page *page; |
| 100 | void *ret = NULL; | 105 | dma_addr_t phys; |
| 101 | 106 | ||
| 102 | page = __dma_alloc(dev, size, handle, gfp); | 107 | page = __dma_alloc(dev, size, handle, gfp); |
| 103 | if (page) | 108 | if (!page) |
| 104 | ret = phys_to_uncached(page_to_phys(page)); | 109 | return NULL; |
| 110 | phys = page_to_phys(page); | ||
| 105 | 111 | ||
| 106 | return ret; | 112 | if (dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs)) { |
| 113 | /* Now, map the page into P3 with write-combining turned on */ | ||
| 114 | *handle = phys; | ||
| 115 | return __ioremap(phys, size, _PAGE_BUFFER); | ||
| 116 | } else { | ||
| 117 | return phys_to_uncached(phys); | ||
| 118 | } | ||
| 107 | } | 119 | } |
| 108 | EXPORT_SYMBOL(dma_alloc_coherent); | ||
| 109 | 120 | ||
| 110 | void dma_free_coherent(struct device *dev, size_t size, | 121 | static void avr32_dma_free(struct device *dev, size_t size, |
| 111 | void *cpu_addr, dma_addr_t handle) | 122 | void *cpu_addr, dma_addr_t handle, struct dma_attrs *attrs) |
| 112 | { | 123 | { |
| 113 | void *addr = phys_to_cached(uncached_to_phys(cpu_addr)); | ||
| 114 | struct page *page; | 124 | struct page *page; |
| 115 | 125 | ||
| 116 | pr_debug("dma_free_coherent addr %p (phys %08lx) size %u\n", | 126 | if (dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs)) { |
| 117 | cpu_addr, (unsigned long)handle, (unsigned)size); | 127 | iounmap(cpu_addr); |
| 118 | BUG_ON(!virt_addr_valid(addr)); | 128 | |
| 119 | page = virt_to_page(addr); | 129 | page = phys_to_page(handle); |
| 130 | } else { | ||
| 131 | void *addr = phys_to_cached(uncached_to_phys(cpu_addr)); | ||
| 132 | |||
| 133 | pr_debug("avr32_dma_free addr %p (phys %08lx) size %u\n", | ||
| 134 | cpu_addr, (unsigned long)handle, (unsigned)size); | ||
| 135 | |||
| 136 | BUG_ON(!virt_addr_valid(addr)); | ||
| 137 | page = virt_to_page(addr); | ||
| 138 | } | ||
| 139 | |||
| 120 | __dma_free(dev, size, page, handle); | 140 | __dma_free(dev, size, page, handle); |
| 121 | } | 141 | } |
| 122 | EXPORT_SYMBOL(dma_free_coherent); | ||
| 123 | 142 | ||
| 124 | void *dma_alloc_writecombine(struct device *dev, size_t size, | 143 | static dma_addr_t avr32_dma_map_page(struct device *dev, struct page *page, |
| 125 | dma_addr_t *handle, gfp_t gfp) | 144 | unsigned long offset, size_t size, |
| 145 | enum dma_data_direction direction, struct dma_attrs *attrs) | ||
| 126 | { | 146 | { |
| 127 | struct page *page; | 147 | void *cpu_addr = page_address(page) + offset; |
| 128 | dma_addr_t phys; | ||
| 129 | 148 | ||
| 130 | page = __dma_alloc(dev, size, handle, gfp); | 149 | dma_cache_sync(dev, cpu_addr, size, direction); |
| 131 | if (!page) | 150 | return virt_to_bus(cpu_addr); |
| 132 | return NULL; | 151 | } |
| 133 | 152 | ||
| 134 | phys = page_to_phys(page); | 153 | static int avr32_dma_map_sg(struct device *dev, struct scatterlist *sglist, |
| 135 | *handle = phys; | 154 | int nents, enum dma_data_direction direction, |
| 155 | struct dma_attrs *attrs) | ||
| 156 | { | ||
| 157 | int i; | ||
| 158 | struct scatterlist *sg; | ||
| 159 | |||
| 160 | for_each_sg(sglist, sg, nents, i) { | ||
| 161 | char *virt; | ||
| 136 | 162 | ||
| 137 | /* Now, map the page into P3 with write-combining turned on */ | 163 | sg->dma_address = page_to_bus(sg_page(sg)) + sg->offset; |
| 138 | return __ioremap(phys, size, _PAGE_BUFFER); | 164 | virt = sg_virt(sg); |
| 165 | dma_cache_sync(dev, virt, sg->length, direction); | ||
| 166 | } | ||
| 167 | |||
| 168 | return nents; | ||
| 139 | } | 169 | } |
| 140 | EXPORT_SYMBOL(dma_alloc_writecombine); | ||
| 141 | 170 | ||
| 142 | void dma_free_writecombine(struct device *dev, size_t size, | 171 | static void avr32_dma_sync_single_for_device(struct device *dev, |
| 143 | void *cpu_addr, dma_addr_t handle) | 172 | dma_addr_t dma_handle, size_t size, |
| 173 | enum dma_data_direction direction) | ||
| 144 | { | 174 | { |
| 145 | struct page *page; | 175 | dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction); |
| 176 | } | ||
| 146 | 177 | ||
| 147 | iounmap(cpu_addr); | 178 | static void avr32_dma_sync_sg_for_device(struct device *dev, |
| 179 | struct scatterlist *sglist, int nents, | ||
| 180 | enum dma_data_direction direction) | ||
| 181 | { | ||
| 182 | int i; | ||
| 183 | struct scatterlist *sg; | ||
| 148 | 184 | ||
| 149 | page = phys_to_page(handle); | 185 | for_each_sg(sglist, sg, nents, i) |
| 150 | __dma_free(dev, size, page, handle); | 186 | dma_cache_sync(dev, sg_virt(sg), sg->length, direction); |
| 151 | } | 187 | } |
| 152 | EXPORT_SYMBOL(dma_free_writecombine); | 188 | |
| 189 | struct dma_map_ops avr32_dma_ops = { | ||
| 190 | .alloc = avr32_dma_alloc, | ||
| 191 | .free = avr32_dma_free, | ||
| 192 | .map_page = avr32_dma_map_page, | ||
| 193 | .map_sg = avr32_dma_map_sg, | ||
| 194 | .sync_single_for_device = avr32_dma_sync_single_for_device, | ||
| 195 | .sync_sg_for_device = avr32_dma_sync_sg_for_device, | ||
| 196 | }; | ||
| 197 | EXPORT_SYMBOL(avr32_dma_ops); | ||
