[PATCH] ppc64: remove firmware features from cpu_spec
[pandora-kernel.git] / arch / ppc64 / kernel / pSeries_smp.c
index fbad349..8312d32 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SMP support for pSeries machines.
+ * SMP support for pSeries and BPA machines.
  *
  * Dave Engebretsen, Peter Bergner, and
  * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
@@ -47,6 +47,7 @@
 #include <asm/pSeries_reconfig.h>
 
 #include "mpic.h"
+#include "bpa_iic.h"
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -92,10 +93,13 @@ static int query_cpu_stopped(unsigned int pcpu)
 
 int pSeries_cpu_disable(void)
 {
+       int cpu = smp_processor_id();
+
+       cpu_clear(cpu, cpu_online_map);
        systemcfg->processorCount--;
 
        /*fix boot_cpuid here*/
-       if (smp_processor_id() == boot_cpuid)
+       if (cpu == boot_cpuid)
                boot_cpuid = any_online_cpu(cpu_online_map);
 
        /* FIXME: abstract this to not be platform specific later on */
@@ -286,6 +290,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
        return 1;
 }
 
+#ifdef CONFIG_XICS
 static inline void smp_xics_do_message(int cpu, int msg)
 {
        set_bit(msg, &xics_ipi_message[cpu].value);
@@ -321,12 +326,43 @@ static void __devinit smp_xics_setup_cpu(int cpu)
        if (cpu != boot_cpuid)
                xics_setup_cpu();
 
-       if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
+       if (ppc64_firmware_features & FW_FEATURE_SPLPAR)
                vpa_init(cpu);
 
        cpu_clear(cpu, of_spin_map);
 
 }
+#endif /* CONFIG_XICS */
+#ifdef CONFIG_BPA_IIC
+static void smp_iic_message_pass(int target, int msg)
+{
+       unsigned int i;
+
+       if (target < NR_CPUS) {
+               iic_cause_IPI(target, msg);
+       } else {
+               for_each_online_cpu(i) {
+                       if (target == MSG_ALL_BUT_SELF
+                           && i == smp_processor_id())
+                               continue;
+                       iic_cause_IPI(i, msg);
+               }
+       }
+}
+
+static int __init smp_iic_probe(void)
+{
+       iic_request_IPIs();
+
+       return cpus_weight(cpu_possible_map);
+}
+
+static void __devinit smp_iic_setup_cpu(int cpu)
+{
+       if (cpu != boot_cpuid)
+               iic_setup_cpu();
+}
+#endif /* CONFIG_BPA_IIC */
 
 static DEFINE_SPINLOCK(timebase_lock);
 static unsigned long timebase = 0;
@@ -375,20 +411,21 @@ static int smp_pSeries_cpu_bootable(unsigned int nr)
         * cpus are assumed to be secondary threads.
         */
        if (system_state < SYSTEM_RUNNING &&
-           cur_cpu_spec->cpu_features & CPU_FTR_SMT &&
+           cpu_has_feature(CPU_FTR_SMT) &&
            !smt_enabled_at_boot && nr % 2 != 0)
                return 0;
 
        return 1;
 }
-
+#ifdef CONFIG_MPIC
 static struct smp_ops_t pSeries_mpic_smp_ops = {
        .message_pass   = smp_mpic_message_pass,
        .probe          = smp_mpic_probe,
        .kick_cpu       = smp_pSeries_kick_cpu,
        .setup_cpu      = smp_mpic_setup_cpu,
 };
-
+#endif
+#ifdef CONFIG_XICS
 static struct smp_ops_t pSeries_xics_smp_ops = {
        .message_pass   = smp_xics_message_pass,
        .probe          = smp_xics_probe,
@@ -396,6 +433,16 @@ static struct smp_ops_t pSeries_xics_smp_ops = {
        .setup_cpu      = smp_xics_setup_cpu,
        .cpu_bootable   = smp_pSeries_cpu_bootable,
 };
+#endif
+#ifdef CONFIG_BPA_IIC
+static struct smp_ops_t bpa_iic_smp_ops = {
+       .message_pass   = smp_iic_message_pass,
+       .probe          = smp_iic_probe,
+       .kick_cpu       = smp_pSeries_kick_cpu,
+       .setup_cpu      = smp_iic_setup_cpu,
+       .cpu_bootable   = smp_pSeries_cpu_bootable,
+};
+#endif
 
 /* This is called very early */
 void __init smp_init_pSeries(void)
@@ -404,10 +451,25 @@ void __init smp_init_pSeries(void)
 
        DBG(" -> smp_init_pSeries()\n");
 
-       if (ppc64_interrupt_controller == IC_OPEN_PIC)
+       switch (ppc64_interrupt_controller) {
+#ifdef CONFIG_MPIC
+       case IC_OPEN_PIC:
                smp_ops = &pSeries_mpic_smp_ops;
-       else
+               break;
+#endif
+#ifdef CONFIG_XICS
+       case IC_PPC_XIC:
                smp_ops = &pSeries_xics_smp_ops;
+               break;
+#endif
+#ifdef CONFIG_BPA_IIC
+       case IC_BPA_IIC:
+               smp_ops = &bpa_iic_smp_ops;
+               break;
+#endif
+       default:
+               panic("Invalid interrupt controller");
+       }
 
 #ifdef CONFIG_HOTPLUG_CPU
        smp_ops->cpu_disable = pSeries_cpu_disable;
@@ -419,8 +481,8 @@ void __init smp_init_pSeries(void)
 #endif
 
        /* Mark threads which are still spinning in hold loops. */
-       if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
-               for_each_present_cpu(i) {
+       if (cpu_has_feature(CPU_FTR_SMT)) {
+               for_each_present_cpu(i) { 
                        if (i % 2 == 0)
                                /*
                                 * Even-numbered logical cpus correspond to
@@ -428,8 +490,9 @@ void __init smp_init_pSeries(void)
                                 */
                                cpu_set(i, of_spin_map);
                }
-       else
+       } else {
                of_spin_map = cpu_present_map;
+       }
 
        cpu_clear(boot_cpuid, of_spin_map);