diff options
Diffstat (limited to 'arch/arm/kernel/process.c')
| -rw-r--r-- | arch/arm/kernel/process.c | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 282de4826abb..6e8931ccf13e 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
| @@ -184,30 +184,61 @@ int __init reboot_setup(char *str) | |||
| 184 | 184 | ||
| 185 | __setup("reboot=", reboot_setup); | 185 | __setup("reboot=", reboot_setup); |
| 186 | 186 | ||
| 187 | /* | ||
| 188 | * Called by kexec, immediately prior to machine_kexec(). | ||
| 189 | * | ||
| 190 | * This must completely disable all secondary CPUs; simply causing those CPUs | ||
| 191 | * to execute e.g. a RAM-based pin loop is not sufficient. This allows the | ||
| 192 | * kexec'd kernel to use any and all RAM as it sees fit, without having to | ||
| 193 | * avoid any code or data used by any SW CPU pin loop. The CPU hotplug | ||
| 194 | * functionality embodied in disable_nonboot_cpus() to achieve this. | ||
| 195 | */ | ||
| 187 | void machine_shutdown(void) | 196 | void machine_shutdown(void) |
| 188 | { | 197 | { |
| 189 | #ifdef CONFIG_SMP | 198 | disable_nonboot_cpus(); |
| 190 | smp_send_stop(); | ||
| 191 | #endif | ||
| 192 | } | 199 | } |
| 193 | 200 | ||
| 201 | /* | ||
| 202 | * Halting simply requires that the secondary CPUs stop performing any | ||
| 203 | * activity (executing tasks, handling interrupts). smp_send_stop() | ||
| 204 | * achieves this. | ||
| 205 | */ | ||
| 194 | void machine_halt(void) | 206 | void machine_halt(void) |
| 195 | { | 207 | { |
| 196 | machine_shutdown(); | 208 | smp_send_stop(); |
| 209 | |||
| 197 | local_irq_disable(); | 210 | local_irq_disable(); |
| 198 | while (1); | 211 | while (1); |
| 199 | } | 212 | } |
| 200 | 213 | ||
| 214 | /* | ||
| 215 | * Power-off simply requires that the secondary CPUs stop performing any | ||
| 216 | * activity (executing tasks, handling interrupts). smp_send_stop() | ||
| 217 | * achieves this. When the system power is turned off, it will take all CPUs | ||
| 218 | * with it. | ||
| 219 | */ | ||
| 201 | void machine_power_off(void) | 220 | void machine_power_off(void) |
| 202 | { | 221 | { |
| 203 | machine_shutdown(); | 222 | smp_send_stop(); |
| 223 | |||
| 204 | if (pm_power_off) | 224 | if (pm_power_off) |
| 205 | pm_power_off(); | 225 | pm_power_off(); |
| 206 | } | 226 | } |
| 207 | 227 | ||
| 228 | /* | ||
| 229 | * Restart requires that the secondary CPUs stop performing any activity | ||
| 230 | * while the primary CPU resets the system. Systems with a single CPU can | ||
| 231 | * use soft_restart() as their machine descriptor's .restart hook, since that | ||
| 232 | * will cause the only available CPU to reset. Systems with multiple CPUs must | ||
| 233 | * provide a HW restart implementation, to ensure that all CPUs reset at once. | ||
| 234 | * This is required so that any code running after reset on the primary CPU | ||
| 235 | * doesn't have to co-ordinate with other CPUs to ensure they aren't still | ||
| 236 | * executing pre-reset code, and using RAM that the primary CPU's code wishes | ||
| 237 | * to use. Implementing such co-ordination would be essentially impossible. | ||
| 238 | */ | ||
| 208 | void machine_restart(char *cmd) | 239 | void machine_restart(char *cmd) |
| 209 | { | 240 | { |
| 210 | machine_shutdown(); | 241 | smp_send_stop(); |
| 211 | 242 | ||
| 212 | arm_pm_restart(reboot_mode, cmd); | 243 | arm_pm_restart(reboot_mode, cmd); |
| 213 | 244 | ||
