
From: Rusty Russell <rusty@rustcorp.com.au>

1) Check for cpuids >= NR_CPUS in prom_hold_cpus: we previously
   overflowed arrays when this happened, and checking it here ensures
   that it doesn't happen elsewhere.  Still move processors to
   secondary_hold (out of OF), but we won't release them.

2) smp_iSeries_message_pass and smp_xics_message_pass don't need to
   iterate if given a specific CPU: cleanup and fix.

3) kick_cpu variants don't need to check cpu range (caller is screwed
   anyway if this happened): replaced with BUG_ON for now.

4) smp_openpic_probe and smp_xics_probe can use cpus_weight(): it's
   faster and simpler.

5) User for_each_cpu/for_each_online_cpu as appropriate. 


---

 arch/ppc64/kernel/prom.c |   14 +++++-
 arch/ppc64/kernel/smp.c  |  107 +++++++++++++++++++++--------------------------
 arch/ppc64/kernel/xics.c |    4 -
 3 files changed, 62 insertions(+), 63 deletions(-)

diff -puN arch/ppc64/kernel/prom.c~ppc64-cpu-spinup-fixes arch/ppc64/kernel/prom.c
--- 25/arch/ppc64/kernel/prom.c~ppc64-cpu-spinup-fixes	2004-02-21 20:58:24.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/prom.c	2004-02-21 20:58:24.000000000 -0800
@@ -30,6 +30,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
+#include <linux/stringify.h>
 #include <linux/delay.h>
 #include <asm/prom.h>
 #include <asm/rtas.h>
@@ -1073,6 +1074,10 @@ prom_hold_cpus(unsigned long mem)
 
 			if (*acknowledge == cpuid) {
 				prom_print(RELOC("ok\n"));
+				/* We have to get every CPU out of OF,
+				 * even if we never start it. */
+				if (cpuid >= NR_CPUS)
+					goto next;
 #ifdef CONFIG_SMP
 				/* Set the number of active processors. */
 				_systemcfg->processorCount++;
@@ -1099,9 +1104,12 @@ prom_hold_cpus(unsigned long mem)
 			cpu_set(cpuid, RELOC(cpu_present_at_boot));
 		}
 
+	next:
 		/* Init paca for secondary threads.   They start later. */
 		for (i=1; i < cpu_threads; i++) {
 			cpuid++;
+			if (cpuid >= NR_CPUS)
+				continue;
 			_xPaca[cpuid].xHwProcNum = interrupt_server[i];
 			prom_print_hex(interrupt_server[i]);
 			prom_print(RELOC(" : preparing thread ... "));
@@ -1146,7 +1154,11 @@ prom_hold_cpus(unsigned long mem)
 		prom_print(RELOC("Processor is not HMT capable\n"));
 	}
 #endif
-	
+
+	if (cpuid >= NR_CPUS)
+		prom_print(RELOC("WARNING: maximum CPUs (" __stringify(NR_CPUS)
+				 ") exceeded: ignoring extras\n"));
+
 #ifdef DEBUG_PROM
 	prom_print(RELOC("prom_hold_cpus: end...\n"));
 #endif
diff -puN arch/ppc64/kernel/smp.c~ppc64-cpu-spinup-fixes arch/ppc64/kernel/smp.c
--- 25/arch/ppc64/kernel/smp.c~ppc64-cpu-spinup-fixes	2004-02-21 20:58:24.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/smp.c	2004-02-21 20:58:24.000000000 -0800
@@ -95,20 +95,25 @@ void iSeries_smp_message_recv( struct pt
 			smp_message_recv( msg, regs );
 }
 
-static void smp_iSeries_message_pass(int target, int msg, unsigned long data, int wait)
+static inline void smp_iSeries_do_message(int cpu, int msg)
+{
+	set_bit(msg, &iSeries_smp_message[cpu]);
+	HvCall_sendIPI(&(paca[cpu]));
+}
+
+static void
+smp_iSeries_message_pass(int target, int msg, long data, int wait)
 {
 	int i;
 
-	for (i = 0; i < NR_CPUS; ++i) {
-		if (!cpu_online(i))
-			continue;
-
-		if ((target == MSG_ALL) || 
-		    (target == i) || 
-		    ((target == MSG_ALL_BUT_SELF) &&
-		     (i != smp_processor_id())) ) {
-			set_bit(msg, &iSeries_smp_message[i]);
-			HvCall_sendIPI(&(paca[i]));
+	if (target < NR_CPUS)
+		smp_iSeries_do_message(target, msg);
+	else {
+		for_each_online_cpu(i) {
+			if (target == MSG_ALL_BUT_SELF
+			    && i == smp_processor_id())
+				continue;
+			smp_iSeries_do_message(i, msg);
 		}
 	}
 }
@@ -151,21 +156,14 @@ static int smp_iSeries_probe(void)
 static void smp_iSeries_kick_cpu(int nr)
 {
 	struct ItLpPaca * lpPaca;
-	/* Verify we have a Paca for processor nr */
-	if ( ( nr <= 0 ) ||
-	     ( nr >= NR_CPUS ) )
-		return;
+
+	BUG_ON(nr < 0 || nr >= NR_CPUS);
+
 	/* Verify that our partition has a processor nr */
 	lpPaca = paca[nr].xLpPacaPtr;
-	if ( lpPaca->xDynProcStatus >= 2 )
+	if (lpPaca->xDynProcStatus >= 2)
 		return;
 
-	/* The information for processor bringup must
-	 * be written out to main store before we release
-	 * the processor.
-	 */
-	mb();
-
 	/* The processor is currently spinning, waiting
 	 * for the xProcStart field to become non-zero
 	 * After we set xProcStart, the processor will
@@ -219,13 +217,9 @@ void smp_openpic_message_pass(int target
 
 static int __init smp_openpic_probe(void)
 {
-	int i;
-	int nr_cpus = 0;
+	int nr_cpus;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (cpu_possible(i))
-			nr_cpus++;
-	}
+	nr_cpus = cpus_weight(cpu_possible_map);
 
 	if (nr_cpus > 1)
 		openpic_request_IPIs();
@@ -240,16 +234,7 @@ static void __devinit smp_openpic_setup_
 
 static void smp_pSeries_kick_cpu(int nr)
 {
-	/* Verify we have a Paca for processor nr */
-	if ( ( nr <= 0 ) ||
-	     ( nr >= NR_CPUS ) )
-		return;
-
-	/* The information for processor bringup must
-	 * be written out to main store before we release
-	 * the processor.
-	 */
-	mb();
+	BUG_ON(nr < 0 || nr >= NR_CPUS);
 
 	/* The processor is currently spinning, waiting
 	 * for the xProcStart field to become non-zero
@@ -266,8 +251,8 @@ static void __init smp_space_timers(unsi
 	unsigned long offset = tb_ticks_per_jiffy / max_cpus;
 	unsigned long previous_tb = paca[boot_cpuid].next_jiffy_update_tb;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (cpu_possible(i) && i != boot_cpuid) {
+	for_each_cpu(i) {
+		if (i != boot_cpuid) {
 			paca[i].next_jiffy_update_tb =
 				previous_tb + offset;
 			previous_tb = paca[i].next_jiffy_update_tb;
@@ -287,20 +272,25 @@ void vpa_init(int cpu)
 	register_vpa(flags, cpu, __pa((unsigned long)&(paca[cpu].xLpPaca))); 
 }
 
+static inline void smp_xics_do_message(int cpu, int msg)
+{
+	set_bit(msg, &xics_ipi_message[cpu].value);
+	mb();
+	xics_cause_IPI(cpu);
+}
+
 static void smp_xics_message_pass(int target, int msg, unsigned long data, int wait)
 {
-	int i;
+	unsigned int i;
 
-	for (i = 0; i < NR_CPUS; ++i) {
-		if (!cpu_online(i))
-			continue;
-
-		if (target == MSG_ALL || target == i
-		    || (target == MSG_ALL_BUT_SELF
-			&& i != smp_processor_id())) {
-			set_bit(msg, &xics_ipi_message[i].value);
-			mb();
-			xics_cause_IPI(i);
+	if (target < NR_CPUS) {
+		smp_xics_do_message(target, msg);
+	} else {
+		for_each_online_cpu(i) {
+			if (target == MSG_ALL_BUT_SELF
+			    && i == smp_processor_id())
+				continue;
+			smp_xics_do_message(i, msg);
 		}
 	}
 }
@@ -309,18 +299,11 @@ extern void xics_request_IPIs(void);
 
 static int __init smp_xics_probe(void)
 {
-	int i;
-	int nr_cpus = 0;
-
-	for (i = 0; i < NR_CPUS; i++) {
-		if (cpu_possible(i))
-			nr_cpus++;
-	}
 #ifdef CONFIG_SMP
 	xics_request_IPIs();
 #endif
 
-	return nr_cpus;
+	return cpus_weight(cpu_possible_map);
 }
 
 static void __devinit smp_xics_setup_cpu(int cpu)
@@ -660,6 +643,12 @@ int __devinit __cpu_up(unsigned int cpu)
 	paca[cpu].xCurrent = (u64)p;
 	current_set[cpu] = p->thread_info;
 
+	/* The information for processor bringup must
+	 * be written out to main store before we release
+	 * the processor.
+	 */
+	mb();
+
 	/* wake up cpus */
 	smp_ops->kick_cpu(cpu);
 
diff -puN arch/ppc64/kernel/xics.c~ppc64-cpu-spinup-fixes arch/ppc64/kernel/xics.c
--- 25/arch/ppc64/kernel/xics.c~ppc64-cpu-spinup-fixes	2004-02-21 20:58:24.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/xics.c	2004-02-21 20:58:24.000000000 -0800
@@ -475,9 +475,7 @@ nextnode:
 
 	if (systemcfg->platform == PLATFORM_PSERIES) {
 #ifdef CONFIG_SMP
-		for (i = 0; i < NR_CPUS; ++i) {
-			if (!cpu_possible(i))
-				continue;
+		for_each_cpu(i) {
 			xics_per_cpu[i] = __ioremap((ulong)inodes[get_hard_smp_processor_id(i)].addr, 
 						    (ulong)inodes[get_hard_smp_processor_id(i)].size,
 						    _PAGE_NO_CACHE);

_
