diff options
Diffstat (limited to 'arch/arm/include/asm/dma-mapping.h')
-rw-r--r-- | arch/arm/include/asm/dma-mapping.h | 79 |
1 files changed, 60 insertions, 19 deletions
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index a96300bf83fd..256ee1c9f51a 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h | |||
@@ -57,18 +57,58 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr) | |||
57 | #endif | 57 | #endif |
58 | 58 | ||
59 | /* | 59 | /* |
60 | * DMA-consistent mapping functions. These allocate/free a region of | 60 | * The DMA API is built upon the notion of "buffer ownership". A buffer |
61 | * uncached, unwrite-buffered mapped memory space for use with DMA | 61 | * is either exclusively owned by the CPU (and therefore may be accessed |
62 | * devices. This is the "generic" version. The PCI specific version | 62 | * by it) or exclusively owned by the DMA device. These helper functions |
63 | * is in pci.h | 63 | * represent the transitions between these two ownership states. |
64 | * | 64 | * |
65 | * Note: Drivers should NOT use this function directly, as it will break | 65 | * Note, however, that on later ARMs, this notion does not work due to |
66 | * platforms with CONFIG_DMABOUNCE. | 66 | * speculative prefetches. We model our approach on the assumption that |
67 | * Use the driver DMA support - see dma-mapping.h (dma_sync_*) | 67 | * the CPU does do speculative prefetches, which means we clean caches |
68 | * before transfers and delay cache invalidation until transfer completion. | ||
69 | * | ||
70 | * Private support functions: these are not part of the API and are | ||
71 | * liable to change. Drivers must not use these. | ||
68 | */ | 72 | */ |
69 | extern void dma_cache_maint(const void *kaddr, size_t size, int rw); | 73 | static inline void __dma_single_cpu_to_dev(const void *kaddr, size_t size, |
70 | extern void dma_cache_maint_page(struct page *page, unsigned long offset, | 74 | enum dma_data_direction dir) |
71 | size_t size, int rw); | 75 | { |
76 | extern void ___dma_single_cpu_to_dev(const void *, size_t, | ||
77 | enum dma_data_direction); | ||
78 | |||
79 | if (!arch_is_coherent()) | ||
80 | ___dma_single_cpu_to_dev(kaddr, size, dir); | ||
81 | } | ||
82 | |||
83 | static inline void __dma_single_dev_to_cpu(const void *kaddr, size_t size, | ||
84 | enum dma_data_direction dir) | ||
85 | { | ||
86 | extern void ___dma_single_dev_to_cpu(const void *, size_t, | ||
87 | enum dma_data_direction); | ||
88 | |||
89 | if (!arch_is_coherent()) | ||
90 | ___dma_single_dev_to_cpu(kaddr, size, dir); | ||
91 | } | ||
92 | |||
93 | static inline void __dma_page_cpu_to_dev(struct page *page, unsigned long off, | ||
94 | size_t size, enum dma_data_direction dir) | ||
95 | { | ||
96 | extern void ___dma_page_cpu_to_dev(struct page *, unsigned long, | ||
97 | size_t, enum dma_data_direction); | ||
98 | |||
99 | if (!arch_is_coherent()) | ||
100 | ___dma_page_cpu_to_dev(page, off, size, dir); | ||
101 | } | ||
102 | |||
103 | static inline void __dma_page_dev_to_cpu(struct page *page, unsigned long off, | ||
104 | size_t size, enum dma_data_direction dir) | ||
105 | { | ||
106 | extern void ___dma_page_dev_to_cpu(struct page *, unsigned long, | ||
107 | size_t, enum dma_data_direction); | ||
108 | |||
109 | if (!arch_is_coherent()) | ||
110 | ___dma_page_dev_to_cpu(page, off, size, dir); | ||
111 | } | ||
72 | 112 | ||
73 | /* | 113 | /* |
74 | * Return whether the given device DMA address mask can be supported | 114 | * Return whether the given device DMA address mask can be supported |
@@ -304,8 +344,7 @@ static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, | |||
304 | { | 344 | { |
305 | BUG_ON(!valid_dma_direction(dir)); | 345 | BUG_ON(!valid_dma_direction(dir)); |
306 | 346 | ||
307 | if (!arch_is_coherent()) | 347 | __dma_single_cpu_to_dev(cpu_addr, size, dir); |
308 | dma_cache_maint(cpu_addr, size, dir); | ||
309 | 348 | ||
310 | return virt_to_dma(dev, cpu_addr); | 349 | return virt_to_dma(dev, cpu_addr); |
311 | } | 350 | } |
@@ -329,8 +368,7 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, | |||
329 | { | 368 | { |
330 | BUG_ON(!valid_dma_direction(dir)); | 369 | BUG_ON(!valid_dma_direction(dir)); |
331 | 370 | ||
332 | if (!arch_is_coherent()) | 371 | __dma_page_cpu_to_dev(page, offset, size, dir); |
333 | dma_cache_maint_page(page, offset, size, dir); | ||
334 | 372 | ||
335 | return page_to_dma(dev, page) + offset; | 373 | return page_to_dma(dev, page) + offset; |
336 | } | 374 | } |
@@ -352,7 +390,7 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, | |||
352 | static inline void dma_unmap_single(struct device *dev, dma_addr_t handle, | 390 | static inline void dma_unmap_single(struct device *dev, dma_addr_t handle, |
353 | size_t size, enum dma_data_direction dir) | 391 | size_t size, enum dma_data_direction dir) |
354 | { | 392 | { |
355 | /* nothing to do */ | 393 | __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir); |
356 | } | 394 | } |
357 | 395 | ||
358 | /** | 396 | /** |
@@ -372,7 +410,8 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t handle, | |||
372 | static inline void dma_unmap_page(struct device *dev, dma_addr_t handle, | 410 | static inline void dma_unmap_page(struct device *dev, dma_addr_t handle, |
373 | size_t size, enum dma_data_direction dir) | 411 | size_t size, enum dma_data_direction dir) |
374 | { | 412 | { |
375 | /* nothing to do */ | 413 | __dma_page_dev_to_cpu(dma_to_page(dev, handle), handle & ~PAGE_MASK, |
414 | size, dir); | ||
376 | } | 415 | } |
377 | #endif /* CONFIG_DMABOUNCE */ | 416 | #endif /* CONFIG_DMABOUNCE */ |
378 | 417 | ||
@@ -400,7 +439,10 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev, | |||
400 | { | 439 | { |
401 | BUG_ON(!valid_dma_direction(dir)); | 440 | BUG_ON(!valid_dma_direction(dir)); |
402 | 441 | ||
403 | dmabounce_sync_for_cpu(dev, handle, offset, size, dir); | 442 | if (!dmabounce_sync_for_cpu(dev, handle, offset, size, dir)) |
443 | return; | ||
444 | |||
445 | __dma_single_dev_to_cpu(dma_to_virt(dev, handle) + offset, size, dir); | ||
404 | } | 446 | } |
405 | 447 | ||
406 | static inline void dma_sync_single_range_for_device(struct device *dev, | 448 | static inline void dma_sync_single_range_for_device(struct device *dev, |
@@ -412,8 +454,7 @@ static inline void dma_sync_single_range_for_device(struct device *dev, | |||
412 | if (!dmabounce_sync_for_device(dev, handle, offset, size, dir)) | 454 | if (!dmabounce_sync_for_device(dev, handle, offset, size, dir)) |
413 | return; | 455 | return; |
414 | 456 | ||
415 | if (!arch_is_coherent()) | 457 | __dma_single_cpu_to_dev(dma_to_virt(dev, handle) + offset, size, dir); |
416 | dma_cache_maint(dma_to_virt(dev, handle) + offset, size, dir); | ||
417 | } | 458 | } |
418 | 459 | ||
419 | static inline void dma_sync_single_for_cpu(struct device *dev, | 460 | static inline void dma_sync_single_for_cpu(struct device *dev, |