X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fx86_64%2Fkernel%2Freboot.c;h=57117b8beb2bfd14e7fc51a618f56fff36176826;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=be4b36f762cf42adb461ec5ea51ea75da45e0e02;hpb=cee37fe97739d85991964371c1f3a745c00dd236;p=linux-2.6.git diff --git a/arch/x86_64/kernel/reboot.c b/arch/x86_64/kernel/reboot.c index be4b36f76..57117b8be 100644 --- a/arch/x86_64/kernel/reboot.c +++ b/arch/x86_64/kernel/reboot.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -66,34 +67,6 @@ static int __init reboot_setup(char *str) __setup("reboot=", reboot_setup); -#ifdef CONFIG_SMP -static void smp_halt(void) -{ - int cpuid = safe_smp_processor_id(); - static int first_entry = 1; - - if (reboot_force) - return; - - if (first_entry) { - first_entry = 0; - smp_call_function((void *)machine_restart, NULL, 1, 0); - } - - smp_stop_cpu(); - - /* AP calling this. Just halt */ - if (cpuid != boot_cpu_id) { - for (;;) - asm("hlt"); - } - - /* Wait for all other CPUs to have run smp_stop_cpu */ - while (!cpus_empty(cpu_online_map)) - rep_nop(); -} -#endif - static inline void kb_wait(void) { int i; @@ -103,25 +76,45 @@ static inline void kb_wait(void) break; } -void machine_restart(char * __unused) +void machine_shutdown(void) { - int i; + unsigned long flags; + /* Stop the cpus and apics */ +#ifdef CONFIG_SMP + int reboot_cpu_id; - printk("machine restart\n"); + /* The boot cpu is always logical cpu 0 */ + reboot_cpu_id = 0; -#ifdef CONFIG_SMP - smp_halt(); + /* Make certain the cpu I'm about to reboot on is online */ + if (!cpu_isset(reboot_cpu_id, cpu_online_map)) { + reboot_cpu_id = smp_processor_id(); + } + + /* Make certain I only run on the appropriate processor */ + set_cpus_allowed(current, cpumask_of_cpu(reboot_cpu_id)); + + /* O.K Now that I'm on the appropriate processor, + * stop all of the others. + */ + smp_send_stop(); #endif - if (!reboot_force) { - local_irq_disable(); + local_irq_save(flags); + #ifndef CONFIG_SMP - disable_local_APIC(); + disable_local_APIC(); #endif - disable_IO_APIC(); - local_irq_enable(); - } - + + disable_IO_APIC(); + + local_irq_restore(flags); +} + +void machine_emergency_restart(void) +{ + int i; + /* Tell the BIOS if we want cold or warm reboot */ *((unsigned short *)__va(0x472)) = reboot_mode; @@ -129,7 +122,7 @@ void machine_restart(char * __unused) /* Could also try the reset bit in the Hammer NB */ switch (reboot_type) { case BOOT_KBD: - for (i=0; i<100; i++) { + for (i=0; i<10; i++) { kb_wait(); udelay(50); outb(0xfe,0x64); /* pulse reset low */ @@ -146,18 +139,27 @@ void machine_restart(char * __unused) } } -EXPORT_SYMBOL(machine_restart); +void machine_restart(char * __unused) +{ + printk("machine restart\n"); + + if (!reboot_force) { + machine_shutdown(); + } + machine_emergency_restart(); +} void machine_halt(void) { } -EXPORT_SYMBOL(machine_halt); - void machine_power_off(void) { - if (pm_power_off) + if (pm_power_off) { + if (!reboot_force) { + machine_shutdown(); + } pm_power_off(); + } } -EXPORT_SYMBOL(machine_power_off);