From: jbeulich@novell.com
Subject: eliminate REBOOT_VECTOR
Patch-mainline: n/a

We can do without it, and can that way save one event channel per CPU
(i.e. a significant number when having many CPUs, given that there are
only 1024/4096 of them on 32-/64-bit).

--- head-2010-04-15.orig/arch/x86/include/asm/hw_irq.h	2010-03-24 16:00:05.000000000 +0100
+++ head-2010-04-15/arch/x86/include/asm/hw_irq.h	2010-03-30 17:14:57.000000000 +0200
@@ -137,7 +137,6 @@ extern asmlinkage void smp_invalidate_in
 extern irqreturn_t smp_reschedule_interrupt(int, void *);
 extern irqreturn_t smp_call_function_interrupt(int, void *);
 extern irqreturn_t smp_call_function_single_interrupt(int, void *);
-extern irqreturn_t smp_reboot_interrupt(int, void *);
 #endif
 #endif
 
--- head-2010-04-15.orig/arch/x86/include/mach-xen/asm/irq_vectors.h	2010-03-29 18:11:31.000000000 +0200
+++ head-2010-04-15/arch/x86/include/mach-xen/asm/irq_vectors.h	2010-03-30 17:15:14.000000000 +0200
@@ -12,8 +12,7 @@
 #define CALL_FUNCTION_VECTOR		1
 #define CALL_FUNC_SINGLE_VECTOR		2
 #define SPIN_UNLOCK_VECTOR		3
-#define REBOOT_VECTOR			4
-#define NR_IPIS				5
+#define NR_IPIS				4
 
 /*
  * The maximum number of vectors supported by i386 processors
--- head-2010-04-15.orig/arch/x86/kernel/smp-xen.c	2010-04-15 10:48:32.000000000 +0200
+++ head-2010-04-15/arch/x86/kernel/smp-xen.c	2010-04-15 11:43:22.000000000 +0200
@@ -29,6 +29,9 @@
 #include <asm/proto.h>
 #include <asm/ipi.h>
 #include <xen/evtchn.h>
+
+static unsigned int __read_mostly reboot = NR_CPUS;
+
 /*
  *	Some notes on x86 processor bugs affecting SMP operation:
  *
@@ -132,19 +135,6 @@ void xen_send_call_func_ipi(const struct
 	xen_send_IPI_mask_allbutself(mask, CALL_FUNCTION_VECTOR);
 }
 
-/*
- * this function calls the 'stop' function on all other CPUs in the system.
- */
-
-irqreturn_t smp_reboot_interrupt(int irq, void *dev_id)
-{
-	irq_enter();
-	stop_this_cpu(NULL);
-	irq_exit();
-
-	return IRQ_HANDLED;
-}
-
 void xen_smp_send_stop(void)
 {
 	unsigned long flags;
@@ -159,8 +149,10 @@ void xen_smp_send_stop(void)
 	 * (this implies we cannot stop CPUs spinning with irq off
 	 * currently)
 	 */
+	reboot = raw_smp_processor_id();
+	wmb();
 	if (num_online_cpus() > 1) {
-		xen_send_IPI_allbutself(REBOOT_VECTOR);
+		xen_send_IPI_allbutself(RESCHEDULE_VECTOR);
 
 		/* Don't wait longer than a second */
 		wait = USEC_PER_SEC;
@@ -180,7 +172,13 @@ void xen_smp_send_stop(void)
  */
 irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id)
 {
-	inc_irq_stat(irq_resched_count);
+	if (likely(reboot >= NR_CPUS) || reboot == raw_smp_processor_id())
+		inc_irq_stat(irq_resched_count);
+	else {
+		irq_enter();
+		stop_this_cpu(NULL);
+		irq_exit();
+	}
 	return IRQ_HANDLED;
 }
 
--- head-2010-04-15.orig/drivers/xen/core/smpboot.c	2010-03-25 14:39:15.000000000 +0100
+++ head-2010-04-15/drivers/xen/core/smpboot.c	2010-04-15 11:43:29.000000000 +0200
@@ -44,7 +44,6 @@ EXPORT_PER_CPU_SYMBOL(cpu_info);
 static int __read_mostly resched_irq = -1;
 static int __read_mostly callfunc_irq = -1;
 static int __read_mostly call1func_irq = -1;
-static int __read_mostly reboot_irq = -1;
 
 #ifdef CONFIG_X86_LOCAL_APIC
 #define set_cpu_to_apicid(cpu, apicid) (per_cpu(x86_cpu_to_apicid, cpu) = (apicid))
@@ -118,10 +117,6 @@ static int __cpuinit xen_smp_intr_init(u
 		.handler = smp_call_function_single_interrupt,
 		.flags   = IRQF_DISABLED,
 		.name    = "call1func"
-	}, reboot_action = {
-		.handler = smp_reboot_interrupt,
-		.flags   = IRQF_DISABLED,
-		.name    = "reboot"
 	};
 	int rc;
 
@@ -155,19 +150,9 @@ static int __cpuinit xen_smp_intr_init(u
 	else
 		BUG_ON(call1func_irq != rc);
 
-	rc = bind_ipi_to_irqaction(REBOOT_VECTOR,
-				   cpu,
-				   &reboot_action);
-	if (rc < 0)
-		goto unbind_call1;
-	if (reboot_irq < 0)
-		reboot_irq = rc;
-	else
-		BUG_ON(reboot_irq != rc);
-
 	rc = xen_spinlock_init(cpu);
 	if (rc < 0)
-		goto unbind_reboot;
+		goto unbind_call1;
 
 	if ((cpu != 0) && ((rc = local_setup_timer(cpu)) != 0))
 		goto fail;
@@ -176,8 +161,6 @@ static int __cpuinit xen_smp_intr_init(u
 
  fail:
 	xen_spinlock_cleanup(cpu);
- unbind_reboot:
-	unbind_from_per_cpu_irq(reboot_irq, cpu, NULL);
  unbind_call1:
 	unbind_from_per_cpu_irq(call1func_irq, cpu, NULL);
  unbind_call:
@@ -196,7 +179,6 @@ static void __cpuinit xen_smp_intr_exit(
 	unbind_from_per_cpu_irq(resched_irq, cpu, NULL);
 	unbind_from_per_cpu_irq(callfunc_irq, cpu, NULL);
 	unbind_from_per_cpu_irq(call1func_irq, cpu, NULL);
-	unbind_from_per_cpu_irq(reboot_irq, cpu, NULL);
 	xen_spinlock_cleanup(cpu);
 }
 #endif
