diff options
author | Thomas Gleixner <[tglx@linutronix.de]> | 2010-07-31 11:36:06 -0400 |
---|---|---|
committer | Santosh Shilimkar <santosh.shilimkar@ti.com> | 2010-10-26 02:09:56 -0400 |
commit | ae360a78f41164e7f9c4cf846696b5b6d8dae5c8 (patch) | |
tree | cb96d4ecbb0c04e7c25a0b08b2dc7f979391a1dc /arch | |
parent | 9a6655e49fd98f3748bb80da20705448aad9ee57 (diff) |
arm: Disable outer (L2) cache in kexec
kexec does not disable the outer cache before disabling the inner
caches in cpu_proc_fin(). So L2 is enabled across the kexec jump. When
the new kernel enables chaches again, it randomly crashes.
Disabling L2 before calling cpu_proc_fin() cures the problem.
Disabling L2 requires the following new functions: flush_all(),
inv_all() and disable(). Add them to outer_cache_fns and call them
from the kexec code.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Linus Walleij <linus.walleij@stericsson.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/include/asm/outercache.h | 24 | ||||
-rw-r--r-- | arch/arm/kernel/machine_kexec.c | 3 |
2 files changed, 27 insertions, 0 deletions
diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h index 25f76bae57a..fc190092527 100644 --- a/arch/arm/include/asm/outercache.h +++ b/arch/arm/include/asm/outercache.h | |||
@@ -25,6 +25,9 @@ struct outer_cache_fns { | |||
25 | void (*inv_range)(unsigned long, unsigned long); | 25 | void (*inv_range)(unsigned long, unsigned long); |
26 | void (*clean_range)(unsigned long, unsigned long); | 26 | void (*clean_range)(unsigned long, unsigned long); |
27 | void (*flush_range)(unsigned long, unsigned long); | 27 | void (*flush_range)(unsigned long, unsigned long); |
28 | void (*flush_all)(void); | ||
29 | void (*inv_all)(void); | ||
30 | void (*disable)(void); | ||
28 | #ifdef CONFIG_OUTER_CACHE_SYNC | 31 | #ifdef CONFIG_OUTER_CACHE_SYNC |
29 | void (*sync)(void); | 32 | void (*sync)(void); |
30 | #endif | 33 | #endif |
@@ -50,6 +53,24 @@ static inline void outer_flush_range(unsigned long start, unsigned long end) | |||
50 | outer_cache.flush_range(start, end); | 53 | outer_cache.flush_range(start, end); |
51 | } | 54 | } |
52 | 55 | ||
56 | static inline void outer_flush_all(void) | ||
57 | { | ||
58 | if (outer_cache.flush_all) | ||
59 | outer_cache.flush_all(); | ||
60 | } | ||
61 | |||
62 | static inline void outer_inv_all(void) | ||
63 | { | ||
64 | if (outer_cache.inv_all) | ||
65 | outer_cache.inv_all(); | ||
66 | } | ||
67 | |||
68 | static inline void outer_disable(void) | ||
69 | { | ||
70 | if (outer_cache.disable) | ||
71 | outer_cache.disable(); | ||
72 | } | ||
73 | |||
53 | #else | 74 | #else |
54 | 75 | ||
55 | static inline void outer_inv_range(unsigned long start, unsigned long end) | 76 | static inline void outer_inv_range(unsigned long start, unsigned long end) |
@@ -58,6 +79,9 @@ static inline void outer_clean_range(unsigned long start, unsigned long end) | |||
58 | { } | 79 | { } |
59 | static inline void outer_flush_range(unsigned long start, unsigned long end) | 80 | static inline void outer_flush_range(unsigned long start, unsigned long end) |
60 | { } | 81 | { } |
82 | static inline void outer_flush_all(void) { } | ||
83 | static inline void outer_inv_all(void) { } | ||
84 | static inline void outer_disable(void) { } | ||
61 | 85 | ||
62 | #endif | 86 | #endif |
63 | 87 | ||
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 1fc74cbd1a1..3a8fd5140d7 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c | |||
@@ -78,7 +78,10 @@ void machine_kexec(struct kimage *image) | |||
78 | local_fiq_disable(); | 78 | local_fiq_disable(); |
79 | setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/ | 79 | setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/ |
80 | flush_cache_all(); | 80 | flush_cache_all(); |
81 | outer_flush_all(); | ||
82 | outer_disable(); | ||
81 | cpu_proc_fin(); | 83 | cpu_proc_fin(); |
84 | outer_inv_all(); | ||
82 | flush_cache_all(); | 85 | flush_cache_all(); |
83 | cpu_reset(reboot_code_buffer_phys); | 86 | cpu_reset(reboot_code_buffer_phys); |
84 | } | 87 | } |