[ppc64] setup_cpu must be called on boot cpu
 
setup_cpu was being called for the boot cpu after all other cpus
had been spun up. The init thread can sleep during secondary cpu
spinup (eg migration thread init) and sometimes the init thread
would switch to another cpu at this time. The end result was setup_cpu
was called twice on one cpu and never on the boot cpu.

The original fix called setup_cpu on the boot cpu before all others but
that wont work for G5, so we now use cpu affinity calls to enforce it.


---

 arch/ppc64/kernel/smp.c |   49 +++++++++++++++++++++++++++++++++---------------
 1 files changed, 34 insertions(+), 15 deletions(-)

diff -puN arch/ppc64/kernel/smp.c~ppc64-setup_cpu arch/ppc64/kernel/smp.c
--- 25/arch/ppc64/kernel/smp.c~ppc64-setup_cpu	2004-01-13 23:23:13.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/smp.c	2004-01-13 23:23:13.000000000 -0800
@@ -235,6 +235,11 @@ static int __init smp_openpic_probe(void
 	return nr_cpus;
 }
 
+static void __devinit smp_openpic_setup_cpu(int cpu)
+{
+	do_openpic_setup_cpu();
+}
+
 static void
 smp_kick_cpu(int nr)
 {
@@ -285,16 +290,6 @@ void vpa_init(int cpu)
 	register_vpa(flags, cpu, __pa((unsigned long)&(paca[cpu].xLpPaca))); 
 }
 
-static void __devinit pSeries_setup_cpu(int cpu)
-{
-	if (OpenPIC_Addr) {
-		do_openpic_setup_cpu();
-	} else {
-		if (cpu != boot_cpuid)
-			xics_setup_cpu();
-	}
-}
-
 static void
 smp_xics_message_pass(int target, int msg, unsigned long data, int wait)
 {
@@ -332,6 +327,12 @@ static int __init smp_xics_probe(void)
 	return nr_cpus;
 }
 
+static void __devinit smp_xics_setup_cpu(int cpu)
+{
+	if (cpu != boot_cpuid)
+		xics_setup_cpu();
+}
+
 static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED;
 static unsigned long timebase = 0;
 
@@ -365,9 +366,11 @@ void __init smp_init_pSeries(void)
 	if (naca->interrupt_controller == IC_OPEN_PIC) {
 		smp_ops->message_pass	= smp_openpic_message_pass;
 		smp_ops->probe		= smp_openpic_probe;
+		smp_ops->setup_cpu	= smp_openpic_setup_cpu;
 	} else {
 		smp_ops->message_pass	= smp_xics_message_pass;
 		smp_ops->probe		= smp_xics_probe;
+		smp_ops->setup_cpu	= smp_xics_setup_cpu;
 	}
 
 	if (systemcfg->platform == PLATFORM_PSERIES) {
@@ -376,7 +379,6 @@ void __init smp_init_pSeries(void)
 	}
 
 	smp_ops->kick_cpu = smp_kick_cpu;
-	smp_ops->setup_cpu = pSeries_setup_cpu;
 }
 #endif
 
@@ -580,11 +582,17 @@ static void __devinit smp_store_cpu_info
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
+	/* 
+	 * setup_cpu may need to be called on the boot cpu. We havent
+	 * spun any cpus up but lets be paranoid.
+	 */
+	BUG_ON(boot_cpuid != smp_processor_id());
+
 	/* Fixup boot cpu */
-	smp_store_cpu_info(smp_processor_id());
-	cpu_callin_map[smp_processor_id()] = 1;
-	paca[smp_processor_id()].prof_counter = 1;
-	paca[smp_processor_id()].prof_multiplier = 1;
+	smp_store_cpu_info(boot_cpuid);
+	cpu_callin_map[boot_cpuid] = 1;
+	paca[boot_cpuid].prof_counter = 1;
+	paca[boot_cpuid].prof_multiplier = 1;
 
 	/*
 	 * XXX very rough. 
@@ -709,8 +717,19 @@ int setup_profiling_timer(unsigned int m
 
 void __init smp_cpus_done(unsigned int max_cpus)
 {
+	cpumask_t old_mask;
+
+	/* We want the setup_cpu() here to be called from CPU 0, but our
+	 * init thread may have been "borrowed" by another CPU in the meantime
+	 * se we pin us down to CPU 0 for a short while
+	 */
+	old_mask = current->cpus_allowed;
+	set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid));
+	
 	smp_ops->setup_cpu(boot_cpuid);
 
 	/* XXX fix this, xics currently relies on it - Anton */
 	smp_threads_ready = 1;
+
+	set_cpus_allowed(current, old_mask);
 }

_