ppc64: Add SMP support for PowerMac G5

parent 66d6b683
...@@ -62,7 +62,7 @@ cpumask_t cpu_present_at_boot = CPU_MASK_NONE; ...@@ -62,7 +62,7 @@ cpumask_t cpu_present_at_boot = CPU_MASK_NONE;
EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(cpu_online_map);
EXPORT_SYMBOL(cpu_possible_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]; static volatile unsigned int cpu_callin_map[NR_CPUS];
...@@ -76,6 +76,8 @@ extern long register_vpa(unsigned long flags, unsigned long proc, ...@@ -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)) #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 #ifdef CONFIG_PPC_ISERIES
static unsigned long iSeries_smp_message[NR_CPUS]; static unsigned long iSeries_smp_message[NR_CPUS];
...@@ -175,21 +177,23 @@ static void __devinit smp_iSeries_setup_cpu(int nr) ...@@ -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. */ /* This is called very early. */
void __init smp_init_iSeries(void) void __init smp_init_iSeries(void)
{ {
smp_ops = &ppc_md.smp_ops; smp_ops = &iSeries_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;
systemcfg->processorCount = smp_iSeries_numProcs(); systemcfg->processorCount = smp_iSeries_numProcs();
} }
#endif #endif
#ifdef CONFIG_PPC_PSERIES #ifdef CONFIG_PPC_PSERIES
static void void smp_openpic_message_pass(int target, int msg, unsigned long data, int wait)
smp_openpic_message_pass(int target, int msg, unsigned long data, int wait)
{ {
/* make sure we're sending something that translates to an IPI */ /* make sure we're sending something that translates to an IPI */
if ( msg > 0x3 ){ if ( msg > 0x3 ){
...@@ -233,8 +237,7 @@ static void __devinit smp_openpic_setup_cpu(int cpu) ...@@ -233,8 +237,7 @@ static void __devinit smp_openpic_setup_cpu(int cpu)
do_openpic_setup_cpu(); do_openpic_setup_cpu();
} }
static void static void smp_pSeries_kick_cpu(int nr)
smp_kick_cpu(int nr)
{ {
/* Verify we have a Paca for processor nr */ /* Verify we have a Paca for processor nr */
if ( ( nr <= 0 ) || if ( ( nr <= 0 ) ||
...@@ -283,8 +286,7 @@ void vpa_init(int cpu) ...@@ -283,8 +286,7 @@ void vpa_init(int cpu)
register_vpa(flags, cpu, __pa((unsigned long)&(paca[cpu].xLpPaca))); register_vpa(flags, cpu, __pa((unsigned long)&(paca[cpu].xLpPaca)));
} }
static void static void smp_xics_message_pass(int target, int msg, unsigned long data, int wait)
smp_xics_message_pass(int target, int msg, unsigned long data, int wait)
{ {
int i; int i;
...@@ -351,27 +353,34 @@ static void __devinit pSeries_take_timebase(void) ...@@ -351,27 +353,34 @@ static void __devinit pSeries_take_timebase(void)
spin_unlock(&timebase_lock); 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 */ /* This is called very early */
void __init smp_init_pSeries(void) void __init smp_init_pSeries(void)
{ {
smp_ops = &ppc_md.smp_ops;
if (naca->interrupt_controller == IC_OPEN_PIC) { if (naca->interrupt_controller == IC_OPEN_PIC)
smp_ops->message_pass = smp_openpic_message_pass; smp_ops = &pSeries_openpic_smp_ops;
smp_ops->probe = smp_openpic_probe; else
smp_ops->setup_cpu = smp_openpic_setup_cpu; smp_ops = &pSeries_xics_smp_ops;
} else {
smp_ops->message_pass = smp_xics_message_pass;
smp_ops->probe = smp_xics_probe;
smp_ops->setup_cpu = smp_xics_setup_cpu;
}
/* Non-lpar has additional take/give timebase */
if (systemcfg->platform == PLATFORM_PSERIES) { if (systemcfg->platform == PLATFORM_PSERIES) {
smp_ops->give_timebase = pSeries_give_timebase; smp_ops->give_timebase = pSeries_give_timebase;
smp_ops->take_timebase = pSeries_take_timebase; smp_ops->take_timebase = pSeries_take_timebase;
} }
smp_ops->kick_cpu = smp_kick_cpu;
} }
#endif #endif
...@@ -606,6 +615,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus) ...@@ -606,6 +615,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
#endif #endif
max_cpus = smp_ops->probe(); max_cpus = smp_ops->probe();
/* Backup CPU 0 state if necessary */
__save_cpu_setup();
smp_space_timers(max_cpus); smp_space_timers(max_cpus);
} }
......
...@@ -106,10 +106,6 @@ struct machdep_calls { ...@@ -106,10 +106,6 @@ struct machdep_calls {
*/ */
long (*feature_call)(unsigned int feature, ...); 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; extern struct machdep_calls ppc_md;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment