arch/i386/kernel/apic.c                     |   60 +++++++++++++++++++++
 arch/i386/kernel/apm.c                      |    9 ---
 arch/i386/kernel/dmi_scan.c                 |   27 ---------
 arch/i386/kernel/io_apic.c                  |    2 
 arch/i386/kernel/reboot.c                   |   78 ++++++++++++----------------
 arch/i386/kernel/smp.c                      |   26 ---------
 include/asm-i386/apic.h                     |   13 ++++
 include/asm-i386/mach-default/mach_reboot.h |    2 
 include/linux/reboot.h                      |    7 +-
 kernel/panic.c                              |    2 
 kernel/sys.c                                |    4 -
 11 files changed, 116 insertions(+), 114 deletions(-)

diff -puN arch/i386/kernel/apic.c~reboot_on_bsp arch/i386/kernel/apic.c
--- 25/arch/i386/kernel/apic.c~reboot_on_bsp	2003-05-13 00:48:34.000000000 -0700
+++ 25-akpm/arch/i386/kernel/apic.c	2003-05-13 00:48:36.000000000 -0700
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/mc146818rtc.h>
 #include <linux/kernel_stat.h>
+#include <linux/reboot.h>
 
 #include <asm/atomic.h>
 #include <asm/smp.h>
@@ -37,6 +38,7 @@
 #include <mach_apic.h>
 
 #include "io_ports.h"
+#include "mach_reboot.h"
 
 void __init apic_intr_init(void)
 {
@@ -1116,6 +1118,64 @@ asmlinkage void smp_error_interrupt(void
 	irq_exit();
 }
 
+
+struct stop_apics {
+	NORET_TYPE void (*rest)(void *info) ATTRIB_NORET;
+	void *info;
+	int reboot_cpu_id;
+};
+
+static void cpu_stop_apics(void *ptr)
+{
+	struct stop_apics *arg = ptr;
+	if (smp_processor_id() != arg->reboot_cpu_id) {
+		local_irq_disable();
+		disable_local_APIC();
+		stop_this_cpu();
+	}
+	local_irq_disable();
+	disable_local_APIC();
+	local_irq_enable();
+
+#if defined(CONFIG_X86_IO_APIC)
+	if (smp_found_config) {
+		disable_IO_APIC();
+	}
+#endif
+	disconnect_bsp_APIC();
+	arg->rest(arg->info);
+}
+
+void stop_apics(NORET_TYPE void(*rest)(void *)ATTRIB_NORET, void *info)
+{
+	/* By resetting the APIC's we disable the nmi watchdog */
+	extern int reboot_cpu;
+	struct stop_apics arg;
+	
+ 	/* The boot cpu is always logical cpu 0 */
+	arg.rest = rest;
+	arg.info = info;
+	arg.reboot_cpu_id = 0;
+	
+	/* See if there has been give a command line override .
+	 */
+	if ((reboot_cpu != -1) && cpu_possible(reboot_cpu)) {
+		arg.reboot_cpu_id = reboot_cpu;
+	}
+
+	/* Make certain the the cpu I'm rebooting on is online */
+	if (!cpu_online(arg.reboot_cpu_id)) {
+		arg.reboot_cpu_id = smp_processor_id();
+	}
+	/* If we aren't in interrupt context use the scheduler,
+	 * so rest will not be called in an interrupt context either.
+	 */
+	if (!in_interrupt()) {
+		set_cpus_allowed(current, 1 << arg.reboot_cpu_id);
+	}
+	on_each_cpu(cpu_stop_apics, &arg, 1, 0);
+}
+
 /*
  * This initializes the IO-APIC and APIC hardware if this is
  * a UP kernel.
diff -puN arch/i386/kernel/apm.c~reboot_on_bsp arch/i386/kernel/apm.c
--- 25/arch/i386/kernel/apm.c~reboot_on_bsp	2003-05-13 00:48:34.000000000 -0700
+++ 25-akpm/arch/i386/kernel/apm.c	2003-05-13 00:48:34.000000000 -0700
@@ -912,17 +912,8 @@ static void apm_power_off(void)
 	/*
 	 * This may be called on an SMP machine.
 	 */
-#ifdef CONFIG_SMP
-	/* Some bioses don't like being called from CPU != 0 */
-	if (smp_processor_id() != 0) {
-		set_cpus_allowed(current, 1 << 0);
-		if (unlikely(smp_processor_id() != 0))
-			BUG();
-	}
-#endif
 	if (apm_info.realmode_power_off)
 	{
-		(void)apm_save_cpus();
 		machine_real_restart(po_bios_call, sizeof(po_bios_call));
 	}
 	else
diff -puN arch/i386/kernel/dmi_scan.c~reboot_on_bsp arch/i386/kernel/dmi_scan.c
--- 25/arch/i386/kernel/dmi_scan.c~reboot_on_bsp	2003-05-13 00:48:34.000000000 -0700
+++ 25-akpm/arch/i386/kernel/dmi_scan.c	2003-05-13 00:48:34.000000000 -0700
@@ -220,31 +220,6 @@ static __init int set_bios_reboot(struct
 	return 0;
 }
 
-/*
- * Some machines require the "reboot=s"  commandline option, this quirk makes that automatic.
- */
-static __init int set_smp_reboot(struct dmi_blacklist *d)
-{
-#ifdef CONFIG_SMP
-	extern int reboot_smp;
-	if (reboot_smp == 0)
-	{
-		reboot_smp = 1;
-		printk(KERN_INFO "%s series board detected. Selecting SMP-method for reboots.\n", d->ident);
-	}
-#endif
-	return 0;
-}
-
-/*
- * Some machines require the "reboot=b,s"  commandline option, this quirk makes that automatic.
- */
-static __init int set_smp_bios_reboot(struct dmi_blacklist *d)
-{
-	set_smp_reboot(d);
-	set_bios_reboot(d);
-	return 0;
-}
 
 /*
  * Some bioses have a broken protected mode poweroff and need to use realmode
@@ -562,7 +537,7 @@ static __initdata struct dmi_blacklist d
 			MATCH(DMI_BIOS_VERSION, "4.60 PGMA"),
 			MATCH(DMI_BIOS_DATE, "134526184"), NO_MATCH
 			} },
-	{ set_smp_bios_reboot, "Dell PowerEdge 1300", {	/* Handle problems with rebooting on Dell 1300's */
+	{ set_bios_reboot, "Dell PowerEdge 1300", {	/* Handle problems with rebooting on Dell 1300's */
 			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
 			MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
 			NO_MATCH, NO_MATCH
diff -puN arch/i386/kernel/io_apic.c~reboot_on_bsp arch/i386/kernel/io_apic.c
--- 25/arch/i386/kernel/io_apic.c~reboot_on_bsp	2003-05-13 00:48:34.000000000 -0700
+++ 25-akpm/arch/i386/kernel/io_apic.c	2003-05-13 00:48:34.000000000 -0700
@@ -1556,8 +1556,6 @@ void disable_IO_APIC(void)
 	 * Clear the IO-APIC before rebooting:
 	 */
 	clear_IO_APIC();
-
-	disconnect_bsp_APIC();
 }
 
 /*
diff -puN arch/i386/kernel/reboot.c~reboot_on_bsp arch/i386/kernel/reboot.c
--- 25/arch/i386/kernel/reboot.c~reboot_on_bsp	2003-05-13 00:48:34.000000000 -0700
+++ 25-akpm/arch/i386/kernel/reboot.c	2003-05-13 00:48:34.000000000 -0700
@@ -8,6 +8,7 @@
 #include <linux/interrupt.h>
 #include <linux/mc146818rtc.h>
 #include <asm/uaccess.h>
+#include <asm/apic.h>
 #include "mach_reboot.h"
 
 /*
@@ -19,9 +20,8 @@ static long no_idt[2];
 static int reboot_mode;
 int reboot_thru_bios;
 
+int reboot_cpu = -1;	  /* specifies the internal linux cpu id, not the apicid */
 #ifdef CONFIG_SMP
-int reboot_smp = 0;
-static int reboot_cpu = -1;
 /* shamelessly grabbed from lib/vsprintf.c for readability */
 #define is_digit(c)	((c) >= '0' && (c) <= '9')
 #endif
@@ -43,12 +43,14 @@ static int __init reboot_setup(char *str
 			break;
 #ifdef CONFIG_SMP
 		case 's': /* "smp" reboot by executing reset on BSP or other CPU*/
-			reboot_smp = 1;
 			if (is_digit(*(str+1))) {
 				reboot_cpu = (int) (*(str+1) - '0');
 				if (is_digit(*(str+2))) 
 					reboot_cpu = reboot_cpu*10 + (int)(*(str+2) - '0');
 			}
+			if ((reboot_cpu < -1) || (reboot_cpu >= NR_CPUS)) {
+				reboot_cpu = -1;
+			}
 				/* we will leave sorting out the final value 
 				when we are ready to reboot, since we might not
  				have set up boot_cpu_id or smp_num_cpu */
@@ -65,6 +67,20 @@ static int __init reboot_setup(char *str
 
 __setup("reboot=", reboot_setup);
 
+
+void stop_this_cpu(void)
+{
+	/*
+	 * Remove this CPU:
+	 */
+#if CONFIG_SMP
+	clear_bit(smp_processor_id(), &cpu_online_map);
+#endif
+	if (cpu_data[smp_processor_id()].hlt_works_ok)
+		for(;;) __asm__("hlt");
+	for (;;);
+}
+
 /* The following code and data reboots the machine by switching to real
    mode and jumping to the BIOS reset entry point, as if the CPU has
    really been reset.  The previous version asked the keyboard
@@ -213,45 +229,8 @@ void machine_real_restart(unsigned char 
 				: "i" ((void *) (0x1000 - sizeof (real_mode_switch) - 100)));
 }
 
-void machine_restart(char * __unused)
+static void machine_restart_1(void * __unused)
 {
-#ifdef CONFIG_SMP
-	int cpuid;
-	
-	cpuid = GET_APIC_ID(apic_read(APIC_ID));
-
-	if (reboot_smp) {
-
-		/* check to see if reboot_cpu is valid 
-		   if its not, default to the BSP */
-		if ((reboot_cpu == -1) ||  
-		      (reboot_cpu > (NR_CPUS -1))  || 
-		      !(phys_cpu_present_map & (1<<cpuid))) 
-			reboot_cpu = boot_cpu_physical_apicid;
-
-		reboot_smp = 0;  /* use this as a flag to only go through this once*/
-		/* re-run this function on the other CPUs
-		   it will fall though this section since we have 
-		   cleared reboot_smp, and do the reboot if it is the
-		   correct CPU, otherwise it halts. */
-		if (reboot_cpu != cpuid)
-			smp_call_function((void *)machine_restart , NULL, 1, 0);
-	}
-
-	/* if reboot_cpu is still -1, then we want a tradional reboot, 
-	   and if we are not running on the reboot_cpu,, halt */
-	if ((reboot_cpu != -1) && (cpuid != reboot_cpu)) {
-		for (;;)
-		__asm__ __volatile__ ("hlt");
-	}
-	/*
-	 * Stop all CPUs and turn off local APICs and the IO-APIC, so
-	 * other OSs see a clean IRQ state.
-	 */
-	smp_send_stop();
-	disable_IO_APIC();
-#endif
-
 	if(!reboot_thru_bios) {
 		/* rebooting needs to touch the page at absolute addr 0 */
 		*((unsigned short *)__va(0x472)) = reboot_mode;
@@ -265,14 +244,27 @@ void machine_restart(char * __unused)
 
 	machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
 }
+void machine_restart(char * __unused)
+{
+	stop_apics(machine_restart_1, 0);
+}
 
+static void machine_halt_1(void * __unused)
+{
+	stop_this_cpu();
+}
 void machine_halt(void)
 {
+	stop_apics(machine_halt_1, 0);
 }
 
-void machine_power_off(void)
+static void machine_power_off_1(void * __unused)
 {
 	if (pm_power_off)
 		pm_power_off();
+	stop_this_cpu();
+}
+void machine_power_off(void)
+{
+	stop_apics(machine_power_off_1, 0);
 }
-
diff -puN arch/i386/kernel/smp.c~reboot_on_bsp arch/i386/kernel/smp.c
--- 25/arch/i386/kernel/smp.c~reboot_on_bsp	2003-05-13 00:48:34.000000000 -0700
+++ 25-akpm/arch/i386/kernel/smp.c	2003-05-13 00:48:34.000000000 -0700
@@ -549,32 +549,6 @@ int smp_call_function (void (*func) (voi
 	return 0;
 }
 
-static void stop_this_cpu (void * dummy)
-{
-	/*
-	 * Remove this CPU:
-	 */
-	clear_bit(smp_processor_id(), &cpu_online_map);
-	local_irq_disable();
-	disable_local_APIC();
-	if (cpu_data[smp_processor_id()].hlt_works_ok)
-		for(;;) __asm__("hlt");
-	for (;;);
-}
-
-/*
- * this function calls the 'stop' function on all other CPUs in the system.
- */
-
-void smp_send_stop(void)
-{
-	smp_call_function(stop_this_cpu, NULL, 1, 0);
-
-	local_irq_disable();
-	disable_local_APIC();
-	local_irq_enable();
-}
-
 /*
  * Reschedule call back. Nothing to do,
  * all the work is done automatically when
diff -puN include/asm-i386/apic.h~reboot_on_bsp include/asm-i386/apic.h
--- 25/include/asm-i386/apic.h~reboot_on_bsp	2003-05-13 00:48:34.000000000 -0700
+++ 25-akpm/include/asm-i386/apic.h	2003-05-13 00:48:34.000000000 -0700
@@ -3,6 +3,7 @@
 
 #include <linux/config.h>
 #include <linux/pm.h>
+#include <linux/linkage.h>
 #include <asm/fixmap.h>
 #include <asm/apicdef.h>
 #include <asm/system.h>
@@ -99,6 +100,18 @@ extern unsigned int nmi_watchdog;
 #define NMI_LOCAL_APIC	2
 #define NMI_INVALID	3
 
+extern NORET_TYPE void 
+stop_apics(NORET_TYPE void (*rest)(void *info) ATTRIB_NORET, void *info) 
+ATTRIB_NORET;
+#else
+static inline NORET_TYPE void 
+stop_apics(NORET_TYPE void (*rest)(void *info) ATTRIB_NORET, void *info)
+ATTRIB_NORET;
+static inline void 
+stop_apics(NORET_TYPE void (*rest)(void *info) ATTRIB_NORET, void *info)
+{
+	rest(info); 
+}
 #endif /* CONFIG_X86_LOCAL_APIC */
 
 extern int phys_proc_id[NR_CPUS];
diff -puN include/asm-i386/mach-default/mach_reboot.h~reboot_on_bsp include/asm-i386/mach-default/mach_reboot.h
--- 25/include/asm-i386/mach-default/mach_reboot.h~reboot_on_bsp	2003-05-13 00:48:34.000000000 -0700
+++ 25-akpm/include/asm-i386/mach-default/mach_reboot.h	2003-05-13 00:48:34.000000000 -0700
@@ -27,4 +27,6 @@ static inline void mach_reboot(void)
 	}
 }
 
+void stop_this_cpu(void);
+
 #endif /* !_MACH_REBOOT_H */
diff -puN include/linux/reboot.h~reboot_on_bsp include/linux/reboot.h
--- 25/include/linux/reboot.h~reboot_on_bsp	2003-05-13 00:48:34.000000000 -0700
+++ 25-akpm/include/linux/reboot.h	2003-05-13 00:48:34.000000000 -0700
@@ -35,6 +35,7 @@
 #ifdef __KERNEL__
 
 #include <linux/notifier.h>
+#include <linux/linkage.h>
 
 extern int register_reboot_notifier(struct notifier_block *);
 extern int unregister_reboot_notifier(struct notifier_block *);
@@ -44,9 +45,9 @@ extern int unregister_reboot_notifier(st
  * Architecture-specific implementations of sys_reboot commands.
  */
 
-extern void machine_restart(char *cmd);
-extern void machine_halt(void);
-extern void machine_power_off(void);
+NORET_TYPE void machine_restart(char *cmd) ATTRIB_NORET;
+NORET_TYPE void machine_halt(void) ATTRIB_NORET;
+NORET_TYPE void machine_power_off(void) ATTRIB_NORET;
 
 #endif
 
diff -puN kernel/panic.c~reboot_on_bsp kernel/panic.c
--- 25/kernel/panic.c~reboot_on_bsp	2003-05-13 00:48:34.000000000 -0700
+++ 25-akpm/kernel/panic.c	2003-05-13 00:48:34.000000000 -0700
@@ -63,7 +63,7 @@ NORET_TYPE void panic(const char * fmt, 
 		sys_sync();
 	bust_spinlocks(0);
 
-#ifdef CONFIG_SMP
+#if defined(CONFIG_SMP) && !defined(__i386__)
 	smp_send_stop();
 #endif
 
diff -puN kernel/sys.c~reboot_on_bsp kernel/sys.c
--- 25/kernel/sys.c~reboot_on_bsp	2003-05-13 00:48:34.000000000 -0700
+++ 25-akpm/kernel/sys.c	2003-05-13 00:48:34.000000000 -0700
@@ -415,8 +415,6 @@ asmlinkage long sys_reboot(int magic1, i
 		device_shutdown();
 		printk(KERN_EMERG "System halted.\n");
 		machine_halt();
-		unlock_kernel();
-		do_exit(0);
 		break;
 
 	case LINUX_REBOOT_CMD_POWER_OFF:
@@ -425,8 +423,6 @@ asmlinkage long sys_reboot(int magic1, i
 		device_shutdown();
 		printk(KERN_EMERG "Power down.\n");
 		machine_power_off();
-		unlock_kernel();
-		do_exit(0);
 		break;
 
 	case LINUX_REBOOT_CMD_RESTART2:

_