diff options
author | Jim Quinlan <jim2101024@gmail.com> | 2013-08-27 16:57:51 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2013-09-04 12:55:58 -0400 |
commit | f86f55d3ad21b21b736bdeb29bee0f0937b77138 (patch) | |
tree | a6f3ff7f993e3bbacccd01d464e5c983094c76ca /arch/mips/mm | |
parent | 2a153f1c551e8b0012a2a901c5665fe4caf07a34 (diff) |
MIPS: DMA: For BMIPS5000 cores flush region just like non-coherent R10000
The BMIPS5000 (Zephyr) processor utilizes instruction speculation. A
stale misprediction address in either the JTB or the CRS may trigger
a prefetch inside a region that is currently being used by a DMA engine,
which is not IO-coherent. This prefetch will fetch a line into the
scache, and that line will soon become stale (ie wrong) during/after the
DMA. Mayhem ensues.
In dma-default.c, the r10000 is handled as a special case in the same way
that we want to handle Zephyr. So we generalize the exception cases into
a function, and include Zephyr as one of the processors that needs this
special care.
Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
Cc: linux-mips@linux-mips.org
Cc: cernekee@gmail.com
Patchwork: https://patchwork.linux-mips.org/patch/5776/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/mm')
-rw-r--r-- | arch/mips/mm/dma-default.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index aaccf1c10699..468f7f967f97 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c | |||
@@ -50,16 +50,20 @@ static inline struct page *dma_addr_to_page(struct device *dev, | |||
50 | } | 50 | } |
51 | 51 | ||
52 | /* | 52 | /* |
53 | * The affected CPUs below in 'cpu_needs_post_dma_flush()' can | ||
54 | * speculatively fill random cachelines with stale data at any time, | ||
55 | * requiring an extra flush post-DMA. | ||
56 | * | ||
53 | * Warning on the terminology - Linux calls an uncached area coherent; | 57 | * Warning on the terminology - Linux calls an uncached area coherent; |
54 | * MIPS terminology calls memory areas with hardware maintained coherency | 58 | * MIPS terminology calls memory areas with hardware maintained coherency |
55 | * coherent. | 59 | * coherent. |
56 | */ | 60 | */ |
57 | 61 | static inline int cpu_needs_post_dma_flush(struct device *dev) | |
58 | static inline int cpu_is_noncoherent_r10000(struct device *dev) | ||
59 | { | 62 | { |
60 | return !plat_device_is_coherent(dev) && | 63 | return !plat_device_is_coherent(dev) && |
61 | (current_cpu_type() == CPU_R10000 || | 64 | (current_cpu_type() == CPU_R10000 || |
62 | current_cpu_type() == CPU_R12000); | 65 | current_cpu_type() == CPU_R12000 || |
66 | current_cpu_type() == CPU_BMIPS5000); | ||
63 | } | 67 | } |
64 | 68 | ||
65 | static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp) | 69 | static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp) |
@@ -230,7 +234,7 @@ static inline void __dma_sync(struct page *page, | |||
230 | static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, | 234 | static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, |
231 | size_t size, enum dma_data_direction direction, struct dma_attrs *attrs) | 235 | size_t size, enum dma_data_direction direction, struct dma_attrs *attrs) |
232 | { | 236 | { |
233 | if (cpu_is_noncoherent_r10000(dev)) | 237 | if (cpu_needs_post_dma_flush(dev)) |
234 | __dma_sync(dma_addr_to_page(dev, dma_addr), | 238 | __dma_sync(dma_addr_to_page(dev, dma_addr), |
235 | dma_addr & ~PAGE_MASK, size, direction); | 239 | dma_addr & ~PAGE_MASK, size, direction); |
236 | 240 | ||
@@ -284,7 +288,7 @@ static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg, | |||
284 | static void mips_dma_sync_single_for_cpu(struct device *dev, | 288 | static void mips_dma_sync_single_for_cpu(struct device *dev, |
285 | dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) | 289 | dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) |
286 | { | 290 | { |
287 | if (cpu_is_noncoherent_r10000(dev)) | 291 | if (cpu_needs_post_dma_flush(dev)) |
288 | __dma_sync(dma_addr_to_page(dev, dma_handle), | 292 | __dma_sync(dma_addr_to_page(dev, dma_handle), |
289 | dma_handle & ~PAGE_MASK, size, direction); | 293 | dma_handle & ~PAGE_MASK, size, direction); |
290 | } | 294 | } |
@@ -305,7 +309,7 @@ static void mips_dma_sync_sg_for_cpu(struct device *dev, | |||
305 | 309 | ||
306 | /* Make sure that gcc doesn't leave the empty loop body. */ | 310 | /* Make sure that gcc doesn't leave the empty loop body. */ |
307 | for (i = 0; i < nelems; i++, sg++) { | 311 | for (i = 0; i < nelems; i++, sg++) { |
308 | if (cpu_is_noncoherent_r10000(dev)) | 312 | if (cpu_needs_post_dma_flush(dev)) |
309 | __dma_sync(sg_page(sg), sg->offset, sg->length, | 313 | __dma_sync(sg_page(sg), sg->offset, sg->length, |
310 | direction); | 314 | direction); |
311 | } | 315 | } |