diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2010-06-21 10:10:07 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-07-01 05:12:31 -0400 |
commit | ad642d9f58f1af6e96efccb5f84e52c6d01db5c4 (patch) | |
tree | 4319ed1e81f50c7035457cc0fa1cf4bcdf760abb | |
parent | ca57926d53580f7c950496cb7ef6d7930610e1dd (diff) |
ARM: 6188/1: Add a config option for the ARM11MPCore DMA cache maintenance workaround
Commit f4d6477f introduced a workaround for the lack of hardware
broadcasting of the cache maintenance operations on ARM11MPCore.
However, the workaround is only valid on CPUs that do not do speculative
loads into the D-cache.
This patch adds a Kconfig option with the corresponding help to make the
above clear. When the DMA_CACHE_RWFO option is disabled, the kernel
behaviour is that prior to the f4d6477f commit. This also allows ARMv6
UP processors with speculative loads to work correctly.
For other processors, a different workaround may be needed.
Cc: Ronen Shitrit <rshitrit@marvell.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/mm/Kconfig | 19 | ||||
-rw-r--r-- | arch/arm/mm/cache-v6.S | 15 |
2 files changed, 31 insertions, 3 deletions
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 346ae14824a5..fc1b2fa59429 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -735,6 +735,25 @@ config NEEDS_SYSCALL_FOR_CMPXCHG | |||
735 | Forget about fast user space cmpxchg support. | 735 | Forget about fast user space cmpxchg support. |
736 | It is just not possible. | 736 | It is just not possible. |
737 | 737 | ||
738 | config DMA_CACHE_RWFO | ||
739 | bool "Enable read/write for ownership DMA cache maintenance" | ||
740 | depends on CPU_V6 && SMP | ||
741 | default y | ||
742 | help | ||
743 | The Snoop Control Unit on ARM11MPCore does not detect the | ||
744 | cache maintenance operations and the dma_{map,unmap}_area() | ||
745 | functions may leave stale cache entries on other CPUs. By | ||
746 | enabling this option, Read or Write For Ownership in the ARMv6 | ||
747 | DMA cache maintenance functions is performed. These LDR/STR | ||
748 | instructions change the cache line state to shared or modified | ||
749 | so that the cache operation has the desired effect. | ||
750 | |||
751 | Note that the workaround is only valid on processors that do | ||
752 | not perform speculative loads into the D-cache. For such | ||
753 | processors, if cache maintenance operations are not broadcast | ||
754 | in hardware, other workarounds are needed (e.g. cache | ||
755 | maintenance broadcasting in software via FIQ). | ||
756 | |||
738 | config OUTER_CACHE | 757 | config OUTER_CACHE |
739 | bool | 758 | bool |
740 | 759 | ||
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 332b48c6d4ff..86aa689ef1aa 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S | |||
@@ -211,7 +211,7 @@ v6_dma_inv_range: | |||
211 | mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line | 211 | mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line |
212 | #endif | 212 | #endif |
213 | 1: | 213 | 1: |
214 | #ifdef CONFIG_SMP | 214 | #ifdef CONFIG_DMA_CACHE_RWFO |
215 | ldr r2, [r0] @ read for ownership | 215 | ldr r2, [r0] @ read for ownership |
216 | str r2, [r0] @ write for ownership | 216 | str r2, [r0] @ write for ownership |
217 | #endif | 217 | #endif |
@@ -235,7 +235,7 @@ v6_dma_inv_range: | |||
235 | v6_dma_clean_range: | 235 | v6_dma_clean_range: |
236 | bic r0, r0, #D_CACHE_LINE_SIZE - 1 | 236 | bic r0, r0, #D_CACHE_LINE_SIZE - 1 |
237 | 1: | 237 | 1: |
238 | #ifdef CONFIG_SMP | 238 | #ifdef CONFIG_DMA_CACHE_RWFO |
239 | ldr r2, [r0] @ read for ownership | 239 | ldr r2, [r0] @ read for ownership |
240 | #endif | 240 | #endif |
241 | #ifdef HARVARD_CACHE | 241 | #ifdef HARVARD_CACHE |
@@ -258,7 +258,7 @@ v6_dma_clean_range: | |||
258 | ENTRY(v6_dma_flush_range) | 258 | ENTRY(v6_dma_flush_range) |
259 | bic r0, r0, #D_CACHE_LINE_SIZE - 1 | 259 | bic r0, r0, #D_CACHE_LINE_SIZE - 1 |
260 | 1: | 260 | 1: |
261 | #ifdef CONFIG_SMP | 261 | #ifdef CONFIG_DMA_CACHE_RWFO |
262 | ldr r2, [r0] @ read for ownership | 262 | ldr r2, [r0] @ read for ownership |
263 | str r2, [r0] @ write for ownership | 263 | str r2, [r0] @ write for ownership |
264 | #endif | 264 | #endif |
@@ -284,9 +284,13 @@ ENTRY(v6_dma_map_area) | |||
284 | add r1, r1, r0 | 284 | add r1, r1, r0 |
285 | teq r2, #DMA_FROM_DEVICE | 285 | teq r2, #DMA_FROM_DEVICE |
286 | beq v6_dma_inv_range | 286 | beq v6_dma_inv_range |
287 | #ifndef CONFIG_DMA_CACHE_RWFO | ||
288 | b v6_dma_clean_range | ||
289 | #else | ||
287 | teq r2, #DMA_TO_DEVICE | 290 | teq r2, #DMA_TO_DEVICE |
288 | beq v6_dma_clean_range | 291 | beq v6_dma_clean_range |
289 | b v6_dma_flush_range | 292 | b v6_dma_flush_range |
293 | #endif | ||
290 | ENDPROC(v6_dma_map_area) | 294 | ENDPROC(v6_dma_map_area) |
291 | 295 | ||
292 | /* | 296 | /* |
@@ -296,6 +300,11 @@ ENDPROC(v6_dma_map_area) | |||
296 | * - dir - DMA direction | 300 | * - dir - DMA direction |
297 | */ | 301 | */ |
298 | ENTRY(v6_dma_unmap_area) | 302 | ENTRY(v6_dma_unmap_area) |
303 | #ifndef CONFIG_DMA_CACHE_RWFO | ||
304 | add r1, r1, r0 | ||
305 | teq r2, #DMA_TO_DEVICE | ||
306 | bne v6_dma_inv_range | ||
307 | #endif | ||
299 | mov pc, lr | 308 | mov pc, lr |
300 | ENDPROC(v6_dma_unmap_area) | 309 | ENDPROC(v6_dma_unmap_area) |
301 | 310 | ||