diff options
author | Huacai Chen <chenhc@lemote.com> | 2013-04-06 22:14:14 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-04-08 16:10:40 -0400 |
commit | 6f389a8f1dd22a24f3d9afc2812b30d639e94625 (patch) | |
tree | 8b175282bdf49043dc57711e121ee603be8cb188 /kernel/sys.c | |
parent | ec376a2ab97ec3be52ca282dc6ac102e805d1005 (diff) |
PM / reboot: call syscore_shutdown() after disable_nonboot_cpus()
As commit 40dc166c (PM / Core: Introduce struct syscore_ops for core
subsystems PM) say, syscore_ops operations should be carried with one
CPU on-line and interrupts disabled. However, after commit f96972f2d
(kernel/sys.c: call disable_nonboot_cpus() in kernel_restart()),
syscore_shutdown() is called before disable_nonboot_cpus(), so break
the rules. We have a MIPS machine with a 8259A PIC, and there is an
external timer (HPET) linked at 8259A. Since 8259A has been shutdown
too early (by syscore_shutdown()), disable_nonboot_cpus() runs without
timer interrupt, so it hangs and reboot fails. This patch call
syscore_shutdown() a little later (after disable_nonboot_cpus()) to
avoid reboot failure, this is the same way as poweroff does.
For consistency, add disable_nonboot_cpus() to kernel_halt().
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'kernel/sys.c')
-rw-r--r-- | kernel/sys.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index 39c9c4a2949f..0da73cf73e60 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -324,7 +324,6 @@ void kernel_restart_prepare(char *cmd) | |||
324 | system_state = SYSTEM_RESTART; | 324 | system_state = SYSTEM_RESTART; |
325 | usermodehelper_disable(); | 325 | usermodehelper_disable(); |
326 | device_shutdown(); | 326 | device_shutdown(); |
327 | syscore_shutdown(); | ||
328 | } | 327 | } |
329 | 328 | ||
330 | /** | 329 | /** |
@@ -370,6 +369,7 @@ void kernel_restart(char *cmd) | |||
370 | { | 369 | { |
371 | kernel_restart_prepare(cmd); | 370 | kernel_restart_prepare(cmd); |
372 | disable_nonboot_cpus(); | 371 | disable_nonboot_cpus(); |
372 | syscore_shutdown(); | ||
373 | if (!cmd) | 373 | if (!cmd) |
374 | printk(KERN_EMERG "Restarting system.\n"); | 374 | printk(KERN_EMERG "Restarting system.\n"); |
375 | else | 375 | else |
@@ -395,6 +395,7 @@ static void kernel_shutdown_prepare(enum system_states state) | |||
395 | void kernel_halt(void) | 395 | void kernel_halt(void) |
396 | { | 396 | { |
397 | kernel_shutdown_prepare(SYSTEM_HALT); | 397 | kernel_shutdown_prepare(SYSTEM_HALT); |
398 | disable_nonboot_cpus(); | ||
398 | syscore_shutdown(); | 399 | syscore_shutdown(); |
399 | printk(KERN_EMERG "System halted.\n"); | 400 | printk(KERN_EMERG "System halted.\n"); |
400 | kmsg_dump(KMSG_DUMP_HALT); | 401 | kmsg_dump(KMSG_DUMP_HALT); |