aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2005-06-20 07:31:14 -0400
committerRussell King <rmk@dyn-67.arm.linux.org.uk>2005-06-20 07:31:14 -0400
commit5abc100e882a979f8f5be8184938305b3fb2df2b (patch)
tree75c19f3780250773c4457cf55a0c08ebcde480a0
parentb8a9b66fbee09d0cc71c272b5c1d1f3320afbbf0 (diff)
[PATCH] ARM: Ensure DMA-bounced buffers are properly written to RAM
When DMA bounce buffers were unmapped and the data was memcpy'd to the original buffer, we were not ensuring that the data was written to RAM. This means that there was the potential for page cache pages to have different cache states depending whether they've been bounced or not. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/common/dmabounce.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 5797b1b100a1..39dd33ff6f37 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -302,12 +302,24 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
302 302
303 DO_STATS ( device_info->bounce_count++ ); 303 DO_STATS ( device_info->bounce_count++ );
304 304
305 if ((dir == DMA_FROM_DEVICE) || 305 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
306 (dir == DMA_BIDIRECTIONAL)) { 306 unsigned long ptr;
307
307 dev_dbg(dev, 308 dev_dbg(dev,
308 "%s: copy back safe %p to unsafe %p size %d\n", 309 "%s: copy back safe %p to unsafe %p size %d\n",
309 __func__, buf->safe, buf->ptr, size); 310 __func__, buf->safe, buf->ptr, size);
310 memcpy(buf->ptr, buf->safe, size); 311 memcpy(buf->ptr, buf->safe, size);
312
313 /*
314 * DMA buffers must have the same cache properties
315 * as if they were really used for DMA - which means
316 * data must be written back to RAM. Note that
317 * we don't use dmac_flush_range() here for the
318 * bidirectional case because we know the cache
319 * lines will be coherent with the data written.
320 */
321 ptr = (unsigned long)buf->ptr;
322 dmac_clean_range(ptr, ptr + size);
311 } 323 }
312 free_safe_buffer(device_info, buf); 324 free_safe_buffer(device_info, buf);
313 } 325 }