aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/reboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/reboot.c')
-rw-r--r--arch/i386/kernel/reboot.c98
1 files changed, 35 insertions, 63 deletions
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
index 6dc27eb70ee7..c71fef31dc47 100644
--- a/arch/i386/kernel/reboot.c
+++ b/arch/i386/kernel/reboot.c
@@ -2,6 +2,7 @@
2 * linux/arch/i386/kernel/reboot.c 2 * linux/arch/i386/kernel/reboot.c
3 */ 3 */
4 4
5#include <linux/config.h>
5#include <linux/mm.h> 6#include <linux/mm.h>
6#include <linux/module.h> 7#include <linux/module.h>
7#include <linux/delay.h> 8#include <linux/delay.h>
@@ -19,12 +20,12 @@
19 * Power off function, if any 20 * Power off function, if any
20 */ 21 */
21void (*pm_power_off)(void); 22void (*pm_power_off)(void);
23EXPORT_SYMBOL(pm_power_off);
22 24
23static int reboot_mode; 25static int reboot_mode;
24static int reboot_thru_bios; 26static int reboot_thru_bios;
25 27
26#ifdef CONFIG_SMP 28#ifdef CONFIG_SMP
27int reboot_smp = 0;
28static int reboot_cpu = -1; 29static int reboot_cpu = -1;
29/* shamelessly grabbed from lib/vsprintf.c for readability */ 30/* shamelessly grabbed from lib/vsprintf.c for readability */
30#define is_digit(c) ((c) >= '0' && (c) <= '9') 31#define is_digit(c) ((c) >= '0' && (c) <= '9')
@@ -47,7 +48,6 @@ static int __init reboot_setup(char *str)
47 break; 48 break;
48#ifdef CONFIG_SMP 49#ifdef CONFIG_SMP
49 case 's': /* "smp" reboot by executing reset on BSP or other CPU*/ 50 case 's': /* "smp" reboot by executing reset on BSP or other CPU*/
50 reboot_smp = 1;
51 if (is_digit(*(str+1))) { 51 if (is_digit(*(str+1))) {
52 reboot_cpu = (int) (*(str+1) - '0'); 52 reboot_cpu = (int) (*(str+1) - '0');
53 if (is_digit(*(str+2))) 53 if (is_digit(*(str+2)))
@@ -86,33 +86,9 @@ static int __init set_bios_reboot(struct dmi_system_id *d)
86 return 0; 86 return 0;
87} 87}
88 88
89/*
90 * Some machines require the "reboot=s" commandline option, this quirk makes that automatic.
91 */
92static int __init set_smp_reboot(struct dmi_system_id *d)
93{
94#ifdef CONFIG_SMP
95 if (!reboot_smp) {
96 reboot_smp = 1;
97 printk(KERN_INFO "%s series board detected. Selecting SMP-method for reboots.\n", d->ident);
98 }
99#endif
100 return 0;
101}
102
103/*
104 * Some machines require the "reboot=b,s" commandline option, this quirk makes that automatic.
105 */
106static int __init set_smp_bios_reboot(struct dmi_system_id *d)
107{
108 set_smp_reboot(d);
109 set_bios_reboot(d);
110 return 0;
111}
112
113static struct dmi_system_id __initdata reboot_dmi_table[] = { 89static struct dmi_system_id __initdata reboot_dmi_table[] = {
114 { /* Handle problems with rebooting on Dell 1300's */ 90 { /* Handle problems with rebooting on Dell 1300's */
115 .callback = set_smp_bios_reboot, 91 .callback = set_bios_reboot,
116 .ident = "Dell PowerEdge 1300", 92 .ident = "Dell PowerEdge 1300",
117 .matches = { 93 .matches = {
118 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), 94 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
@@ -295,42 +271,36 @@ void machine_real_restart(unsigned char *code, int length)
295 : 271 :
296 : "i" ((void *) (0x1000 - sizeof (real_mode_switch) - 100))); 272 : "i" ((void *) (0x1000 - sizeof (real_mode_switch) - 100)));
297} 273}
274#ifdef CONFIG_APM_MODULE
275EXPORT_SYMBOL(machine_real_restart);
276#endif
298 277
299void machine_restart(char * __unused) 278void machine_shutdown(void)
300{ 279{
301#ifdef CONFIG_SMP 280#ifdef CONFIG_SMP
302 int cpuid; 281 int reboot_cpu_id;
303 282
304 cpuid = GET_APIC_ID(apic_read(APIC_ID)); 283 /* The boot cpu is always logical cpu 0 */
305 284 reboot_cpu_id = 0;
306 if (reboot_smp) { 285
307 286 /* See if there has been given a command line override */
308 /* check to see if reboot_cpu is valid 287 if ((reboot_cpu != -1) && (reboot_cpu < NR_CPUS) &&
309 if its not, default to the BSP */ 288 cpu_isset(reboot_cpu, cpu_online_map)) {
310 if ((reboot_cpu == -1) || 289 reboot_cpu_id = reboot_cpu;
311 (reboot_cpu > (NR_CPUS -1)) ||
312 !physid_isset(cpuid, phys_cpu_present_map))
313 reboot_cpu = boot_cpu_physical_apicid;
314
315 reboot_smp = 0; /* use this as a flag to only go through this once*/
316 /* re-run this function on the other CPUs
317 it will fall though this section since we have
318 cleared reboot_smp, and do the reboot if it is the
319 correct CPU, otherwise it halts. */
320 if (reboot_cpu != cpuid)
321 smp_call_function((void *)machine_restart , NULL, 1, 0);
322 } 290 }
323 291
324 /* if reboot_cpu is still -1, then we want a tradional reboot, 292 /* Make certain the cpu I'm rebooting on is online */
325 and if we are not running on the reboot_cpu,, halt */ 293 if (!cpu_isset(reboot_cpu_id, cpu_online_map)) {
326 if ((reboot_cpu != -1) && (cpuid != reboot_cpu)) { 294 reboot_cpu_id = smp_processor_id();
327 for (;;)
328 __asm__ __volatile__ ("hlt");
329 } 295 }
330 /* 296
331 * Stop all CPUs and turn off local APICs and the IO-APIC, so 297 /* Make certain I only run on the appropriate processor */
332 * other OSs see a clean IRQ state. 298 set_cpus_allowed(current, cpumask_of_cpu(reboot_cpu_id));
299
300 /* O.K. Now that I'm on the appropriate processor, stop
301 * all of the others, and disable their local APICs.
333 */ 302 */
303
334 smp_send_stop(); 304 smp_send_stop();
335#endif /* CONFIG_SMP */ 305#endif /* CONFIG_SMP */
336 306
@@ -339,7 +309,10 @@ void machine_restart(char * __unused)
339#ifdef CONFIG_X86_IO_APIC 309#ifdef CONFIG_X86_IO_APIC
340 disable_IO_APIC(); 310 disable_IO_APIC();
341#endif 311#endif
312}
342 313
314void machine_emergency_restart(void)
315{
343 if (!reboot_thru_bios) { 316 if (!reboot_thru_bios) {
344 if (efi_enabled) { 317 if (efi_enabled) {
345 efi.reset_system(EFI_RESET_COLD, EFI_SUCCESS, 0, NULL); 318 efi.reset_system(EFI_RESET_COLD, EFI_SUCCESS, 0, NULL);
@@ -362,23 +335,22 @@ void machine_restart(char * __unused)
362 machine_real_restart(jump_to_bios, sizeof(jump_to_bios)); 335 machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
363} 336}
364 337
365EXPORT_SYMBOL(machine_restart); 338void machine_restart(char * __unused)
339{
340 machine_shutdown();
341 machine_emergency_restart();
342}
366 343
367void machine_halt(void) 344void machine_halt(void)
368{ 345{
369} 346}
370 347
371EXPORT_SYMBOL(machine_halt);
372
373void machine_power_off(void) 348void machine_power_off(void)
374{ 349{
375 lapic_shutdown(); 350 machine_shutdown();
376 351
377 if (efi_enabled)
378 efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
379 if (pm_power_off) 352 if (pm_power_off)
380 pm_power_off(); 353 pm_power_off();
381} 354}
382 355
383EXPORT_SYMBOL(machine_power_off);
384 356