瀏覽代碼

[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>
Russell King 20 年之前
父節點
當前提交
5abc100e88
共有 1 個文件被更改,包括 14 次插入2 次删除
  1. 14 2
      arch/arm/common/dmabounce.c

+ 14 - 2
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++ );
 		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,
 			dev_dbg(dev,
 				"%s: copy back safe %p to unsafe %p size %d\n",
 				"%s: copy back safe %p to unsafe %p size %d\n",
 				__func__, buf->safe, buf->ptr, size);
 				__func__, buf->safe, buf->ptr, size);
 			memcpy(buf->ptr, buf->safe, 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);
 		free_safe_buffer(device_info, buf);
 	}
 	}