]> git.hungrycats.org Git - linux/commitdiff
ppc64: Add SMP support for PowerMac G5
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 13 Feb 2004 02:43:20 +0000 (13:43 +1100)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 13 Feb 2004 02:43:20 +0000 (13:43 +1100)
arch/ppc64/kernel/smp.c
include/asm-ppc64/machdep.h

index 101441d0adc74d74b777aed0e062361c2de2f02f..36746aefb1d2936832336ee6e1c132a7f5b60781 100644 (file)
@@ -62,7 +62,7 @@ cpumask_t cpu_present_at_boot = CPU_MASK_NONE;
 EXPORT_SYMBOL(cpu_online_map);
 EXPORT_SYMBOL(cpu_possible_map);
 
-static struct smp_ops_t *smp_ops;
+struct smp_ops_t *smp_ops;
 
 static volatile unsigned int cpu_callin_map[NR_CPUS];
 
@@ -76,6 +76,8 @@ extern long register_vpa(unsigned long flags, unsigned long proc,
 
 #define smp_message_pass(t,m,d,w) smp_ops->message_pass((t),(m),(d),(w))
 
+/* Low level assembly function used to backup CPU 0 state */
+extern void __save_cpu_setup(void);
 #ifdef CONFIG_PPC_ISERIES
 static unsigned long iSeries_smp_message[NR_CPUS];
 
@@ -175,21 +177,23 @@ static void __devinit smp_iSeries_setup_cpu(int nr)
 {
 }
 
+static struct smp_ops_t iSeries_smp_ops = {
+       .message_pass = smp_iSeries_message_pass,
+       .probe        = smp_iSeries_probe,
+       .kick_cpu     = smp_iSeries_kick_cpu,
+       .setup_cpu    = smp_iSeries_setup_cpu,
+};
+
 /* This is called very early. */
 void __init smp_init_iSeries(void)
 {
-       smp_ops = &ppc_md.smp_ops;
-       smp_ops->message_pass = smp_iSeries_message_pass;
-       smp_ops->probe        = smp_iSeries_probe;
-       smp_ops->kick_cpu     = smp_iSeries_kick_cpu;
-       smp_ops->setup_cpu    = smp_iSeries_setup_cpu;
+       smp_ops = &iSeries_smp_ops;
        systemcfg->processorCount       = smp_iSeries_numProcs();
 }
 #endif
 
 #ifdef CONFIG_PPC_PSERIES
-static void
-smp_openpic_message_pass(int target, int msg, unsigned long data, int wait)
+void smp_openpic_message_pass(int target, int msg, unsigned long data, int wait)
 {
        /* make sure we're sending something that translates to an IPI */
        if ( msg > 0x3 ){
@@ -233,8 +237,7 @@ static void __devinit smp_openpic_setup_cpu(int cpu)
        do_openpic_setup_cpu();
 }
 
-static void
-smp_kick_cpu(int nr)
+static void smp_pSeries_kick_cpu(int nr)
 {
        /* Verify we have a Paca for processor nr */
        if ( ( nr <= 0 ) ||
@@ -283,8 +286,7 @@ void vpa_init(int cpu)
        register_vpa(flags, cpu, __pa((unsigned long)&(paca[cpu].xLpPaca))); 
 }
 
-static void
-smp_xics_message_pass(int target, int msg, unsigned long data, int wait)
+static void smp_xics_message_pass(int target, int msg, unsigned long data, int wait)
 {
        int i;
 
@@ -351,27 +353,34 @@ static void __devinit pSeries_take_timebase(void)
        spin_unlock(&timebase_lock);
 }
 
+static struct smp_ops_t pSeries_openpic_smp_ops = {
+       .message_pass   = smp_openpic_message_pass,
+       .probe          = smp_openpic_probe,
+       .kick_cpu       = smp_pSeries_kick_cpu,
+       .setup_cpu      = smp_openpic_setup_cpu,
+};
+
+static struct smp_ops_t pSeries_xics_smp_ops = {
+       .message_pass   = smp_xics_message_pass,
+       .probe          = smp_xics_probe,
+       .kick_cpu       = smp_pSeries_kick_cpu,
+       .setup_cpu      = smp_xics_setup_cpu,
+};
+
 /* This is called very early */
 void __init smp_init_pSeries(void)
 {
-       smp_ops = &ppc_md.smp_ops;
 
-       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 (naca->interrupt_controller == IC_OPEN_PIC)
+               smp_ops = &pSeries_openpic_smp_ops;
+       else
+               smp_ops = &pSeries_xics_smp_ops;
 
+       /* Non-lpar has additional take/give timebase */
        if (systemcfg->platform == PLATFORM_PSERIES) {
                smp_ops->give_timebase = pSeries_give_timebase;
                smp_ops->take_timebase = pSeries_take_timebase;
        }
-
-       smp_ops->kick_cpu = smp_kick_cpu;
 }
 #endif
 
@@ -606,6 +615,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 #endif
 
        max_cpus = smp_ops->probe();
+       /* Backup CPU 0 state if necessary */
+       __save_cpu_setup();
+
        smp_space_timers(max_cpus);
 }
 
index 456633c66f8808213763aed9de36d433579482e1..513ea51cd3581d38c17399257bd9faa2c554d6cd 100644 (file)
@@ -106,10 +106,6 @@ struct machdep_calls {
         */
        long            (*feature_call)(unsigned int feature, ...);
 
-#ifdef CONFIG_SMP
-       /* functions for dealing with other cpus */
-       struct smp_ops_t smp_ops;
-#endif /* CONFIG_SMP */
 };
 
 extern struct machdep_calls ppc_md;