]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
x86: call machine_shutdown and stop all CPUs in native_machine_halt
authorIvan Vecera <ivecera@redhat.com>
Tue, 11 Nov 2008 13:33:44 +0000 (14:33 +0100)
committerIngo Molnar <mingo@elte.hu>
Tue, 11 Nov 2008 13:50:02 +0000 (14:50 +0100)
Impact: really halt all CPUs on halt

Function machine_halt (resp. native_machine_halt) is empty for x86
architectures. When command 'halt -f' is invoked, the message "System
halted." is displayed but this is not really true because all CPUs are
still running.

There are also similar inconsistencies for other arches (some uses
power-off for halt or forever-loop with IRQs enabled/disabled).

IMO there should be used the same approach for all architectures OR
what does the message "System halted" really mean?

This patch fixes it for x86.

Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/include/asm/apic.h
arch/x86/include/asm/system.h
arch/x86/kernel/process.c
arch/x86/kernel/reboot.c
arch/x86/kernel/smp.c

index 3b1510b4fc5741290d5660bb4c30f34bc70f6371..25caa0738af5f9d99399d3c2f36405bc62d7115b 100644 (file)
@@ -193,6 +193,7 @@ extern u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask);
 static inline void lapic_shutdown(void) { }
 #define local_apic_timer_c2_ok         1
 static inline void init_apic_mappings(void) { }
+static inline void disable_local_APIC(void) { }
 
 #endif /* !CONFIG_X86_LOCAL_APIC */
 
index 2ed3f0f44ff73519a149b37c9bd658a26361c8de..07c3e4048991c757663c3de65338a85259a0cd2a 100644 (file)
@@ -314,6 +314,8 @@ extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
 
 void default_idle(void);
 
+void stop_this_cpu(void *dummy);
+
 /*
  * Force strict CPU ordering.
  * And yes, this is required on UP too when we're talking
index c622772744d86fcb0dcd3e6c46a6de5323508c40..a4da7c4b31294782fe42143a6dcd07c5203bb137 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/pm.h>
 #include <linux/clockchips.h>
 #include <asm/system.h>
+#include <asm/apic.h>
 
 unsigned long idle_halt;
 EXPORT_SYMBOL(idle_halt);
@@ -122,6 +123,21 @@ void default_idle(void)
 EXPORT_SYMBOL(default_idle);
 #endif
 
+void stop_this_cpu(void *dummy)
+{
+       local_irq_disable();
+       /*
+        * Remove this CPU:
+        */
+       cpu_clear(smp_processor_id(), cpu_online_map);
+       disable_local_APIC();
+
+       for (;;) {
+               if (hlt_works(smp_processor_id()))
+                       halt();
+       }
+}
+
 static void do_nothing(void *unused)
 {
 }
index 724adfc63cb9a7b60d6ee5c82efd919fe237f69c..34f8d37ae3c5e8bdebcac7af466036f95f222acb 100644 (file)
@@ -461,6 +461,11 @@ static void native_machine_restart(char *__unused)
 
 static void native_machine_halt(void)
 {
+       /* stop other cpus and apics */
+       machine_shutdown();
+
+       /* stop this cpu */
+       stop_this_cpu(NULL);
 }
 
 static void native_machine_power_off(void)
index 18f9b19f5f8f5d46582b64501d83d11cb4376eb6..3f92b134ab902067c63ed05f51f95eac7dd0de99 100644 (file)
@@ -140,19 +140,6 @@ void native_send_call_func_ipi(cpumask_t mask)
                send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
 }
 
-static void stop_this_cpu(void *dummy)
-{
-       local_irq_disable();
-       /*
-        * Remove this CPU:
-        */
-       cpu_clear(smp_processor_id(), cpu_online_map);
-       disable_local_APIC();
-       if (hlt_works(smp_processor_id()))
-               for (;;) halt();
-       for (;;);
-}
-
 /*
  * this function calls the 'stop' function on all other CPUs in the system.
  */