Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: 6405/1: Handle __flush_icache_all for CONFIG_SMP_ON_UP

Do this by adding flush_icache_all to cache_fns for ARMv6 and 7.
As flush_icache_all may neeed to be called from flush_kern_cache_all,
add it as the first entry in the cache_fns.

Note that now we can remove the ARM_ERRATA_411920 dependency
to !SMP so it can be selected on UP ARMv6 processors, such
as omap2.

Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by

Tony Lindgren and committed by
Russell King
81d11955 f9e417e9

+77 -27
+1 -1
arch/arm/Kconfig
··· 1002 1002 1003 1003 config ARM_ERRATA_411920 1004 1004 bool "ARM errata: Invalidation of the Instruction Cache operation can fail" 1005 - depends on CPU_V6 && !SMP 1005 + depends on CPU_V6 1006 1006 help 1007 1007 Invalidation of the Instruction Cache operation can 1008 1008 fail. This erratum is present in 1136 (before r1p4), 1156 and 1176.
+41 -15
arch/arm/include/asm/cacheflush.h
··· 156 156 * Please note that the implementation of these, and the required 157 157 * effects are cache-type (VIVT/VIPT/PIPT) specific. 158 158 * 159 + * flush_icache_all() 160 + * 161 + * Unconditionally clean and invalidate the entire icache. 162 + * Currently only needed for cache-v6.S and cache-v7.S, see 163 + * __flush_icache_all for the generic implementation. 164 + * 159 165 * flush_kern_all() 160 166 * 161 167 * Unconditionally clean and invalidate the entire cache. ··· 212 206 */ 213 207 214 208 struct cpu_cache_fns { 209 + void (*flush_icache_all)(void); 215 210 void (*flush_kern_all)(void); 216 211 void (*flush_user_all)(void); 217 212 void (*flush_user_range)(unsigned long, unsigned long, unsigned int); ··· 234 227 235 228 extern struct cpu_cache_fns cpu_cache; 236 229 230 + #define __cpuc_flush_icache_all cpu_cache.flush_icache_all 237 231 #define __cpuc_flush_kern_all cpu_cache.flush_kern_all 238 232 #define __cpuc_flush_user_all cpu_cache.flush_user_all 239 233 #define __cpuc_flush_user_range cpu_cache.flush_user_range ··· 254 246 255 247 #else 256 248 249 + #define __cpuc_flush_icache_all __glue(_CACHE,_flush_icache_all) 257 250 #define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all) 258 251 #define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all) 259 252 #define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range) ··· 262 253 #define __cpuc_coherent_user_range __glue(_CACHE,_coherent_user_range) 263 254 #define __cpuc_flush_dcache_area __glue(_CACHE,_flush_kern_dcache_area) 264 255 256 + extern void __cpuc_flush_icache_all(void); 265 257 extern void __cpuc_flush_kern_all(void); 266 258 extern void __cpuc_flush_user_all(void); 267 259 extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int); ··· 301 291 /* 302 292 * Convert calls to our calling convention. 303 293 */ 294 + 295 + /* Invalidate I-cache */ 296 + #define __flush_icache_all_generic() \ 297 + asm("mcr p15, 0, %0, c7, c5, 0" \ 298 + : : "r" (0)); 299 + 300 + /* Invalidate I-cache inner shareable */ 301 + #define __flush_icache_all_v7_smp() \ 302 + asm("mcr p15, 0, %0, c7, c1, 0" \ 303 + : : "r" (0)); 304 + 305 + /* 306 + * Optimized __flush_icache_all for the common cases. Note that UP ARMv7 307 + * will fall through to use __flush_icache_all_generic. 308 + */ 309 + #if (defined(CONFIG_CPU_V7) && defined(CONFIG_CPU_V6)) || \ 310 + defined(CONFIG_SMP_ON_UP) 311 + #define __flush_icache_preferred __cpuc_flush_icache_all 312 + #elif __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP) 313 + #define __flush_icache_preferred __flush_icache_all_v7_smp 314 + #elif __LINUX_ARM_ARCH__ == 6 && defined(CONFIG_ARM_ERRATA_411920) 315 + #define __flush_icache_preferred __cpuc_flush_icache_all 316 + #else 317 + #define __flush_icache_preferred __flush_icache_all_generic 318 + #endif 319 + 320 + static inline void __flush_icache_all(void) 321 + { 322 + __flush_icache_preferred(); 323 + } 324 + 304 325 #define flush_cache_all() __cpuc_flush_kern_all() 305 326 306 327 static inline void vivt_flush_cache_mm(struct mm_struct *mm) ··· 407 366 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 408 367 extern void flush_dcache_page(struct page *); 409 368 410 - static inline void __flush_icache_all(void) 411 - { 412 - #ifdef CONFIG_ARM_ERRATA_411920 413 - extern void v6_icache_inval_all(void); 414 - v6_icache_inval_all(); 415 - #elif defined(CONFIG_SMP) && __LINUX_ARM_ARCH__ >= 7 416 - asm("mcr p15, 0, %0, c7, c1, 0 @ invalidate I-cache inner shareable\n" 417 - : 418 - : "r" (0)); 419 - #else 420 - asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n" 421 - : 422 - : "r" (0)); 423 - #endif 424 - } 425 369 static inline void flush_kernel_vmap_range(void *addr, int size) 426 370 { 427 371 if ((cache_is_vivt() || cache_is_vipt_aliasing()))
+19 -11
arch/arm/mm/cache-v6.S
··· 21 21 #define D_CACHE_LINE_SIZE 32 22 22 #define BTB_FLUSH_SIZE 8 23 23 24 - #ifdef CONFIG_ARM_ERRATA_411920 25 24 /* 26 - * Invalidate the entire I cache (this code is a workaround for the ARM1136 27 - * erratum 411920 - Invalidate Instruction Cache operation can fail. This 28 - * erratum is present in 1136, 1156 and 1176. It does not affect the MPCore. 25 + * v6_flush_icache_all() 29 26 * 30 - * Registers: 31 - * r0 - set to 0 32 - * r1 - corrupted 27 + * Flush the whole I-cache. 28 + * 29 + * ARM1136 erratum 411920 - Invalidate Instruction Cache operation can fail. 30 + * This erratum is present in 1136, 1156 and 1176. It does not affect the 31 + * MPCore. 32 + * 33 + * Registers: 34 + * r0 - set to 0 35 + * r1 - corrupted 33 36 */ 34 - ENTRY(v6_icache_inval_all) 37 + ENTRY(v6_flush_icache_all) 35 38 mov r0, #0 39 + #ifdef CONFIG_ARM_ERRATA_411920 36 40 mrs r1, cpsr 37 41 cpsid ifa @ disable interrupts 38 42 mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache ··· 47 43 .rept 11 @ ARM Ltd recommends at least 48 44 nop @ 11 NOPs 49 45 .endr 50 - mov pc, lr 46 + #else 47 + mcr p15, 0, r0, c7, c5, 0 @ invalidate I-cache 51 48 #endif 49 + mov pc, lr 50 + ENDPROC(v6_flush_icache_all) 52 51 53 52 /* 54 53 * v6_flush_cache_all() ··· 67 60 #ifndef CONFIG_ARM_ERRATA_411920 68 61 mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate 69 62 #else 70 - b v6_icache_inval_all 63 + b v6_flush_icache_all 71 64 #endif 72 65 #else 73 66 mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate ··· 145 138 #ifndef CONFIG_ARM_ERRATA_411920 146 139 mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate 147 140 #else 148 - b v6_icache_inval_all 141 + b v6_flush_icache_all 149 142 #endif 150 143 #else 151 144 mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB ··· 319 312 320 313 .type v6_cache_fns, #object 321 314 ENTRY(v6_cache_fns) 315 + .long v6_flush_icache_all 322 316 .long v6_flush_kern_cache_all 323 317 .long v6_flush_user_cache_all 324 318 .long v6_flush_user_cache_range
+16
arch/arm/mm/cache-v7.S
··· 18 18 #include "proc-macros.S" 19 19 20 20 /* 21 + * v7_flush_icache_all() 22 + * 23 + * Flush the whole I-cache. 24 + * 25 + * Registers: 26 + * r0 - set to 0 27 + */ 28 + ENTRY(v7_flush_icache_all) 29 + mov r0, #0 30 + ALT_SMP(mcr p15, 0, r0, c7, c1, 0) @ invalidate I-cache inner shareable 31 + ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate 32 + mov pc, lr 33 + ENDPROC(v7_flush_icache_all) 34 + 35 + /* 21 36 * v7_flush_dcache_all() 22 37 * 23 38 * Flush the whole D-cache. ··· 318 303 319 304 .type v7_cache_fns, #object 320 305 ENTRY(v7_cache_fns) 306 + .long v7_flush_icache_all 321 307 .long v7_flush_kern_cache_all 322 308 .long v7_flush_user_cache_all 323 309 .long v7_flush_user_cache_range