From: Anton Blanchard <anton@samba.org>

It turns out there are more issues with our VPA code:

1. vpa_init doesnt report errors when it fails.  This was masking a bug
   where the VPA spanned 2 pages and phyp failed to register it.

2. We call idle_setup before we initialise the boot cpus vpa.  This
   means we never select the shared processor idle loop.

3. We dont call vpa_init on UP kernels.

Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/ppc64/kernel/pSeries_lpar.c   |   16 ++++++++++++++++
 25-akpm/arch/ppc64/kernel/pSeries_setup.c  |    3 +++
 25-akpm/arch/ppc64/kernel/pSeries_smp.c    |   10 ----------
 25-akpm/arch/ppc64/kernel/setup.c          |    4 ++--
 25-akpm/arch/ppc64/kernel/smp.c            |    2 --
 25-akpm/include/asm-ppc64/plpar_wrappers.h |    8 +++++---
 6 files changed, 26 insertions(+), 17 deletions(-)

diff -puN arch/ppc64/kernel/pSeries_lpar.c~ppc64-pseries-shared-processor-fixes arch/ppc64/kernel/pSeries_lpar.c
--- 25/arch/ppc64/kernel/pSeries_lpar.c~ppc64-pseries-shared-processor-fixes	Thu Dec  9 14:41:38 2004
+++ 25-akpm/arch/ppc64/kernel/pSeries_lpar.c	Thu Dec  9 14:41:38 2004
@@ -259,6 +259,22 @@ out:
 	return found;
 }
 
+void vpa_init(int cpu)
+{
+	int hwcpu = get_hard_smp_processor_id(cpu);
+	unsigned long vpa = (unsigned long)&(paca[cpu].lppaca);
+	long ret;
+	unsigned long flags;
+
+	/* Register the Virtual Processor Area (VPA) */
+	flags = 1UL << (63 - 18);
+	ret = register_vpa(flags, hwcpu, __pa(vpa));
+
+	if (ret)
+		printk(KERN_ERR "WARNING: vpa_init: VPA registration for "
+				"cpu %d (hw %d) of area %lx returns %ld\n",
+				cpu, hwcpu, __pa(vpa), ret);
+}
 
 long pSeries_lpar_hpte_insert(unsigned long hpte_group,
 			      unsigned long va, unsigned long prpn,
diff -puN arch/ppc64/kernel/pSeries_setup.c~ppc64-pseries-shared-processor-fixes arch/ppc64/kernel/pSeries_setup.c
--- 25/arch/ppc64/kernel/pSeries_setup.c~ppc64-pseries-shared-processor-fixes	Thu Dec  9 14:41:38 2004
+++ 25-akpm/arch/ppc64/kernel/pSeries_setup.c	Thu Dec  9 14:41:38 2004
@@ -234,6 +234,9 @@ static void __init pSeries_setup_arch(vo
 #endif
 
 	pSeries_nvram_init();
+
+	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
+		vpa_init(boot_cpuid);
 }
 
 static int __init pSeries_init_panel(void)
diff -puN arch/ppc64/kernel/pSeries_smp.c~ppc64-pseries-shared-processor-fixes arch/ppc64/kernel/pSeries_smp.c
--- 25/arch/ppc64/kernel/pSeries_smp.c~ppc64-pseries-shared-processor-fixes	Thu Dec  9 14:41:38 2004
+++ 25-akpm/arch/ppc64/kernel/pSeries_smp.c	Thu Dec  9 14:41:38 2004
@@ -59,16 +59,6 @@
 
 extern void pseries_secondary_smp_init(unsigned long); 
 
-static void vpa_init(int cpu)
-{
-	unsigned long flags, pcpu = get_hard_smp_processor_id(cpu);
-
-	/* Register the Virtual Processor Area (VPA) */
-	flags = 1UL << (63 - 18);
-	register_vpa(flags, pcpu, __pa((unsigned long)&(paca[cpu].lppaca)));
-}
-
-
 /* Get state of physical CPU.
  * Return codes:
  *	0	- The processor is in the RTAS stopped state
diff -puN arch/ppc64/kernel/setup.c~ppc64-pseries-shared-processor-fixes arch/ppc64/kernel/setup.c
--- 25/arch/ppc64/kernel/setup.c~ppc64-pseries-shared-processor-fixes	Thu Dec  9 14:41:38 2004
+++ 25-akpm/arch/ppc64/kernel/setup.c	Thu Dec  9 14:41:38 2004
@@ -1020,11 +1020,11 @@ void __init setup_arch(char **cmdline_p)
 	/* set up the bootmem stuff with available memory */
 	do_init_bootmem();
 
+	ppc_md.setup_arch();
+
 	/* Select the correct idle loop for the platform. */
 	idle_setup();
 
-	ppc_md.setup_arch();
-
 	paging_init();
 	ppc64_boot_msg(0x15, "Setup Done");
 }
diff -puN arch/ppc64/kernel/smp.c~ppc64-pseries-shared-processor-fixes arch/ppc64/kernel/smp.c
--- 25/arch/ppc64/kernel/smp.c~ppc64-pseries-shared-processor-fixes	Thu Dec  9 14:41:38 2004
+++ 25-akpm/arch/ppc64/kernel/smp.c	Thu Dec  9 14:41:38 2004
@@ -76,8 +76,6 @@ extern unsigned char stab_array[];
 
 extern int cpu_idle(void *unused);
 void smp_call_function_interrupt(void);
-extern long register_vpa(unsigned long flags, unsigned long proc,
-			 unsigned long vpa);
 
 int smt_enabled_at_boot = 1;
 
diff -puN include/asm-ppc64/plpar_wrappers.h~ppc64-pseries-shared-processor-fixes include/asm-ppc64/plpar_wrappers.h
--- 25/include/asm-ppc64/plpar_wrappers.h~ppc64-pseries-shared-processor-fixes	Thu Dec  9 14:41:38 2004
+++ 25-akpm/include/asm-ppc64/plpar_wrappers.h	Thu Dec  9 14:41:38 2004
@@ -22,12 +22,14 @@ static inline long cede_processor(void)
 	return(0); 
 }
 
-static inline long register_vpa(unsigned long flags, unsigned long proc, unsigned long vpa)
+static inline long register_vpa(unsigned long flags, unsigned long proc,
+				unsigned long vpa)
 {
-	plpar_hcall_norets(H_REGISTER_VPA, flags, proc, vpa);
-	return(0); 
+	return plpar_hcall_norets(H_REGISTER_VPA, flags, proc, vpa);
 }
 
+void vpa_init(int cpu);
+
 static inline long plpar_pte_remove(unsigned long flags,
 				    unsigned long ptex,
 				    unsigned long avpn,
_