aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorThomas Gleixner <[tglx@linutronix.de]>2010-07-31 11:36:06 -0400
committerSantosh Shilimkar <santosh.shilimkar@ti.com>2010-10-26 02:09:56 -0400
commitae360a78f41164e7f9c4cf846696b5b6d8dae5c8 (patch)
treecb96d4ecbb0c04e7c25a0b08b2dc7f979391a1dc /arch
parent9a6655e49fd98f3748bb80da20705448aad9ee57 (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.h24
-rw-r--r--arch/arm/kernel/machine_kexec.c3
2 files changed, 27 insertions, 0 deletions
diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h
index 25f76bae57ab..fc1900925275 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
56static inline void outer_flush_all(void)
57{
58 if (outer_cache.flush_all)
59 outer_cache.flush_all();
60}
61
62static inline void outer_inv_all(void)
63{
64 if (outer_cache.inv_all)
65 outer_cache.inv_all();
66}
67
68static inline void outer_disable(void)
69{
70 if (outer_cache.disable)
71 outer_cache.disable();
72}
73
53#else 74#else
54 75
55static inline void outer_inv_range(unsigned long start, unsigned long end) 76static 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{ }
59static inline void outer_flush_range(unsigned long start, unsigned long end) 80static inline void outer_flush_range(unsigned long start, unsigned long end)
60{ } 81{ }
82static inline void outer_flush_all(void) { }
83static inline void outer_inv_all(void) { }
84static 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 1fc74cbd1a19..3a8fd5140d7a 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}