mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-06 10:57:46 +00:00
ARM: 6188/1: Add a config option for the ARM11MPCore DMA cache maintenance workaround
Commitf4d6477f
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 thef4d6477f
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>
This commit is contained in:
parent
ca57926d53
commit
ad642d9f58
2 changed files with 31 additions and 3 deletions
|
@ -735,6 +735,25 @@ config NEEDS_SYSCALL_FOR_CMPXCHG
|
||||||
Forget about fast user space cmpxchg support.
|
Forget about fast user space cmpxchg support.
|
||||||
It is just not possible.
|
It is just not possible.
|
||||||
|
|
||||||
|
config DMA_CACHE_RWFO
|
||||||
|
bool "Enable read/write for ownership DMA cache maintenance"
|
||||||
|
depends on CPU_V6 && SMP
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
The Snoop Control Unit on ARM11MPCore does not detect the
|
||||||
|
cache maintenance operations and the dma_{map,unmap}_area()
|
||||||
|
functions may leave stale cache entries on other CPUs. By
|
||||||
|
enabling this option, Read or Write For Ownership in the ARMv6
|
||||||
|
DMA cache maintenance functions is performed. These LDR/STR
|
||||||
|
instructions change the cache line state to shared or modified
|
||||||
|
so that the cache operation has the desired effect.
|
||||||
|
|
||||||
|
Note that the workaround is only valid on processors that do
|
||||||
|
not perform speculative loads into the D-cache. For such
|
||||||
|
processors, if cache maintenance operations are not broadcast
|
||||||
|
in hardware, other workarounds are needed (e.g. cache
|
||||||
|
maintenance broadcasting in software via FIQ).
|
||||||
|
|
||||||
config OUTER_CACHE
|
config OUTER_CACHE
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
|
|
@ -211,7 +211,7 @@ v6_dma_inv_range:
|
||||||
mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line
|
mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line
|
||||||
#endif
|
#endif
|
||||||
1:
|
1:
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_DMA_CACHE_RWFO
|
||||||
ldr r2, [r0] @ read for ownership
|
ldr r2, [r0] @ read for ownership
|
||||||
str r2, [r0] @ write for ownership
|
str r2, [r0] @ write for ownership
|
||||||
#endif
|
#endif
|
||||||
|
@ -235,7 +235,7 @@ v6_dma_inv_range:
|
||||||
v6_dma_clean_range:
|
v6_dma_clean_range:
|
||||||
bic r0, r0, #D_CACHE_LINE_SIZE - 1
|
bic r0, r0, #D_CACHE_LINE_SIZE - 1
|
||||||
1:
|
1:
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_DMA_CACHE_RWFO
|
||||||
ldr r2, [r0] @ read for ownership
|
ldr r2, [r0] @ read for ownership
|
||||||
#endif
|
#endif
|
||||||
#ifdef HARVARD_CACHE
|
#ifdef HARVARD_CACHE
|
||||||
|
@ -258,7 +258,7 @@ v6_dma_clean_range:
|
||||||
ENTRY(v6_dma_flush_range)
|
ENTRY(v6_dma_flush_range)
|
||||||
bic r0, r0, #D_CACHE_LINE_SIZE - 1
|
bic r0, r0, #D_CACHE_LINE_SIZE - 1
|
||||||
1:
|
1:
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_DMA_CACHE_RWFO
|
||||||
ldr r2, [r0] @ read for ownership
|
ldr r2, [r0] @ read for ownership
|
||||||
str r2, [r0] @ write for ownership
|
str r2, [r0] @ write for ownership
|
||||||
#endif
|
#endif
|
||||||
|
@ -284,9 +284,13 @@ ENTRY(v6_dma_map_area)
|
||||||
add r1, r1, r0
|
add r1, r1, r0
|
||||||
teq r2, #DMA_FROM_DEVICE
|
teq r2, #DMA_FROM_DEVICE
|
||||||
beq v6_dma_inv_range
|
beq v6_dma_inv_range
|
||||||
|
#ifndef CONFIG_DMA_CACHE_RWFO
|
||||||
|
b v6_dma_clean_range
|
||||||
|
#else
|
||||||
teq r2, #DMA_TO_DEVICE
|
teq r2, #DMA_TO_DEVICE
|
||||||
beq v6_dma_clean_range
|
beq v6_dma_clean_range
|
||||||
b v6_dma_flush_range
|
b v6_dma_flush_range
|
||||||
|
#endif
|
||||||
ENDPROC(v6_dma_map_area)
|
ENDPROC(v6_dma_map_area)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -296,6 +300,11 @@ ENDPROC(v6_dma_map_area)
|
||||||
* - dir - DMA direction
|
* - dir - DMA direction
|
||||||
*/
|
*/
|
||||||
ENTRY(v6_dma_unmap_area)
|
ENTRY(v6_dma_unmap_area)
|
||||||
|
#ifndef CONFIG_DMA_CACHE_RWFO
|
||||||
|
add r1, r1, r0
|
||||||
|
teq r2, #DMA_TO_DEVICE
|
||||||
|
bne v6_dma_inv_range
|
||||||
|
#endif
|
||||||
mov pc, lr
|
mov pc, lr
|
||||||
ENDPROC(v6_dma_unmap_area)
|
ENDPROC(v6_dma_unmap_area)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue