summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2005-06-20 12:31:14 +0100
committerRussell King <rmk@dyn-67.arm.linux.org.uk>2005-06-20 12:31:14 +0100
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 5797b1b100a..39dd33ff6f3 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,
DO_STATS ( device_info->bounce_count++ );
- if ((dir == DMA_FROM_DEVICE) ||
- (dir == DMA_BIDIRECTIONAL)) {
+ if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
+ unsigned long ptr;
+
dev_dbg(dev,
"%s: copy back safe %p to unsafe %p size %d\n",
__func__, buf->safe, buf->ptr, size);
memcpy(buf->ptr, buf->safe, size);
+
+ /*
+ * DMA buffers must have the same cache properties
+ * as if they were really used for DMA - which means
+ * data must be written back to RAM. Note that
+ * we don't use dmac_flush_range() here for the
+ * bidirectional case because we know the cache
+ * lines will be coherent with the data written.
+ */
+ ptr = (unsigned long)buf->ptr;
+ dmac_clean_range(ptr, ptr + size);
}
free_safe_buffer(device_info, buf);
}