aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/reboot.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2005-06-25 17:57:55 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-25 19:24:49 -0400
commitdd2a13054ffc25783a74afb5e4a0f2115e45f9cd (patch)
tree731e3d72e158f9c8a7e19247e6b3f1a409c7b0ec /arch/i386/kernel/reboot.c
parent50cccc699ed849d31c9e3f7643db33edade20e4e (diff)
[PATCH] kexec: x86: factor out apic shutdown code
Factor out the apic and smp shutdown code from machine_restart so it can be called by in the kexec reboot path as well. By switching to the bootstrap cpu by default on reboot I can delete/simplify some motherboard fixups well. Signed-off-by: Eric Biederman <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386/kernel/reboot.c')
-rw-r--r--arch/i386/kernel/reboot.c82
1 files changed, 26 insertions, 56 deletions
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
index db912209a8d3..b3e584849961 100644
--- a/arch/i386/kernel/reboot.c
+++ b/arch/i386/kernel/reboot.c
@@ -26,7 +26,6 @@ static int reboot_mode;
26static int reboot_thru_bios; 26static int reboot_thru_bios;
27 27
28#ifdef CONFIG_SMP 28#ifdef CONFIG_SMP
29int reboot_smp = 0;
30static int reboot_cpu = -1; 29static int reboot_cpu = -1;
31/* shamelessly grabbed from lib/vsprintf.c for readability */ 30/* shamelessly grabbed from lib/vsprintf.c for readability */
32#define is_digit(c) ((c) >= '0' && (c) <= '9') 31#define is_digit(c) ((c) >= '0' && (c) <= '9')
@@ -49,7 +48,6 @@ static int __init reboot_setup(char *str)
49 break; 48 break;
50#ifdef CONFIG_SMP 49#ifdef CONFIG_SMP
51 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*/
52 reboot_smp = 1;
53 if (is_digit(*(str+1))) { 51 if (is_digit(*(str+1))) {
54 reboot_cpu = (int) (*(str+1) - '0'); 52 reboot_cpu = (int) (*(str+1) - '0');
55 if (is_digit(*(str+2))) 53 if (is_digit(*(str+2)))
@@ -88,33 +86,9 @@ static int __init set_bios_reboot(struct dmi_system_id *d)
88 return 0; 86 return 0;
89} 87}
90 88
91/*
92 * Some machines require the "reboot=s" commandline option, this quirk makes that automatic.
93 */
94static int __init set_smp_reboot(struct dmi_system_id *d)
95{
96#ifdef CONFIG_SMP
97 if (!reboot_smp) {
98 reboot_smp = 1;
99 printk(KERN_INFO "%s series board detected. Selecting SMP-method for reboots.\n", d->ident);
100 }
101#endif
102 return 0;
103}
104
105/*
106 * Some machines require the "reboot=b,s" commandline option, this quirk makes that automatic.
107 */
108static int __init set_smp_bios_reboot(struct dmi_system_id *d)
109{
110 set_smp_reboot(d);
111 set_bios_reboot(d);
112 return 0;
113}
114
115static struct dmi_system_id __initdata reboot_dmi_table[] = { 89static struct dmi_system_id __initdata reboot_dmi_table[] = {
116 { /* Handle problems with rebooting on Dell 1300's */ 90 { /* Handle problems with rebooting on Dell 1300's */
117 .callback = set_smp_bios_reboot, 91 .callback = set_bios_reboot,
118 .ident = "Dell PowerEdge 1300", 92 .ident = "Dell PowerEdge 1300",
119 .matches = { 93 .matches = {
120 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), 94 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
@@ -301,41 +275,32 @@ void machine_real_restart(unsigned char *code, int length)
301EXPORT_SYMBOL(machine_real_restart); 275EXPORT_SYMBOL(machine_real_restart);
302#endif 276#endif
303 277
304void machine_restart(char * __unused) 278void machine_shutdown(void)
305{ 279{
306#ifdef CONFIG_SMP 280#ifdef CONFIG_SMP
307 int cpuid; 281 int reboot_cpu_id;
308 282
309 cpuid = GET_APIC_ID(apic_read(APIC_ID)); 283 /* The boot cpu is always logical cpu 0 */
310 284 reboot_cpu_id = 0;
311 if (reboot_smp) { 285
312 286 /* See if there has been given a command line override */
313 /* check to see if reboot_cpu is valid 287 if ((reboot_cpu_id != -1) && (reboot_cpu < NR_CPUS) &&
314 if its not, default to the BSP */ 288 cpu_isset(reboot_cpu, cpu_online_map)) {
315 if ((reboot_cpu == -1) || 289 reboot_cpu_id = reboot_cpu;
316 (reboot_cpu > (NR_CPUS -1)) ||
317 !physid_isset(cpuid, phys_cpu_present_map))
318 reboot_cpu = boot_cpu_physical_apicid;
319
320 reboot_smp = 0; /* use this as a flag to only go through this once*/
321 /* re-run this function on the other CPUs
322 it will fall though this section since we have
323 cleared reboot_smp, and do the reboot if it is the
324 correct CPU, otherwise it halts. */
325 if (reboot_cpu != cpuid)
326 smp_call_function((void *)machine_restart , NULL, 1, 0);
327 } 290 }
328 291
329 /* if reboot_cpu is still -1, then we want a tradional reboot, 292 /* Make certain the cpu I'm rebooting on is online */
330 and if we are not running on the reboot_cpu,, halt */ 293 if (!cpu_isset(reboot_cpu_id, cpu_online_map)) {
331 if ((reboot_cpu != -1) && (cpuid != reboot_cpu)) { 294 reboot_cpu_id = smp_processor_id();
332 for (;;)
333 __asm__ __volatile__ ("hlt");
334 } 295 }
335 /* 296
336 * Stop all CPUs and turn off local APICs and the IO-APIC, so 297 /* Make certain I only run on the appropriate processor */
337 * 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.
338 */ 302 */
303
339 smp_send_stop(); 304 smp_send_stop();
340#endif /* CONFIG_SMP */ 305#endif /* CONFIG_SMP */
341 306
@@ -344,6 +309,11 @@ void machine_restart(char * __unused)
344#ifdef CONFIG_X86_IO_APIC 309#ifdef CONFIG_X86_IO_APIC
345 disable_IO_APIC(); 310 disable_IO_APIC();
346#endif 311#endif
312}
313
314void machine_restart(char * __unused)
315{
316 machine_shutdown();
347 317
348 if (!reboot_thru_bios) { 318 if (!reboot_thru_bios) {
349 if (efi_enabled) { 319 if (efi_enabled) {