summaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-07-26 13:31:27 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-07-27 10:48:43 +0100
commit3d3f78d752bfada5b6041f2f7bd0833d8bdf7a4a (patch)
tree14365f6ef64f10095c3080cdabb9b8cd0a51d671 /arch/arm/kernel
parent5388a6b266e9c3357353332ba0cd5549082887f1 (diff)
ARM: call machine_shutdown() from machine_halt(), etc
x86 calls machine_shutdown() from the various machine_*() calls which take the machine down ready for halting, restarting, etc, and uses this to bring the system safely to a point where those actions can be performed. Such actions are stopping the secondary CPUs. So, change the ARM implementation of these to reflect what x86 does. This solves kexec problems on ARM SMP platforms, where the secondary CPUs were left running across the kexec call. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/machine_kexec.c4
-rw-r--r--arch/arm/kernel/process.c12
-rw-r--r--arch/arm/kernel/smp.c11
3 files changed, 18 insertions, 9 deletions
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index 3b4872c2da8..df5958f6864 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -37,10 +37,6 @@ void machine_kexec_cleanup(struct kimage *image)
{
}
-void machine_shutdown(void)
-{
-}
-
void machine_crash_shutdown(struct pt_regs *regs)
{
}
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index aaf51159203..2e2ec97cc50 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -198,19 +198,29 @@ int __init reboot_setup(char *str)
__setup("reboot=", reboot_setup);
-void machine_halt(void)
+void machine_shutdown(void)
{
+#ifdef CONFIG_SMP
+ smp_send_stop();
+#endif
}
+void machine_halt(void)
+{
+ machine_shutdown();
+ while (1);
+}
void machine_power_off(void)
{
+ machine_shutdown();
if (pm_power_off)
pm_power_off();
}
void machine_restart(char *cmd)
{
+ machine_shutdown();
arm_pm_restart(reboot_mode, cmd);
}
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 0170e248a1d..40dc74f2b27 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -471,10 +471,13 @@ static DEFINE_SPINLOCK(stop_lock);
*/
static void ipi_cpu_stop(unsigned int cpu)
{
- spin_lock(&stop_lock);
- printk(KERN_CRIT "CPU%u: stopping\n", cpu);
- dump_stack();
- spin_unlock(&stop_lock);
+ if (system_state == SYSTEM_BOOTING ||
+ system_state == SYSTEM_RUNNING) {
+ spin_lock(&stop_lock);
+ printk(KERN_CRIT "CPU%u: stopping\n", cpu);
+ dump_stack();
+ spin_unlock(&stop_lock);
+ }
set_cpu_online(cpu, false);