aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel/pSeries_smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc64/kernel/pSeries_smp.c')
-rw-r--r--arch/ppc64/kernel/pSeries_smp.c69
1 files changed, 64 insertions, 5 deletions
diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
index 4203bd020c82..30154140f7e2 100644
--- a/arch/ppc64/kernel/pSeries_smp.c
+++ b/arch/ppc64/kernel/pSeries_smp.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * SMP support for pSeries machines. 2 * SMP support for pSeries and BPA machines.
3 * 3 *
4 * Dave Engebretsen, Peter Bergner, and 4 * Dave Engebretsen, Peter Bergner, and
5 * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com 5 * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
@@ -47,6 +47,7 @@
47#include <asm/pSeries_reconfig.h> 47#include <asm/pSeries_reconfig.h>
48 48
49#include "mpic.h" 49#include "mpic.h"
50#include "bpa_iic.h"
50 51
51#ifdef DEBUG 52#ifdef DEBUG
52#define DBG(fmt...) udbg_printf(fmt) 53#define DBG(fmt...) udbg_printf(fmt)
@@ -286,6 +287,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
286 return 1; 287 return 1;
287} 288}
288 289
290#ifdef CONFIG_XICS
289static inline void smp_xics_do_message(int cpu, int msg) 291static inline void smp_xics_do_message(int cpu, int msg)
290{ 292{
291 set_bit(msg, &xics_ipi_message[cpu].value); 293 set_bit(msg, &xics_ipi_message[cpu].value);
@@ -327,6 +329,37 @@ static void __devinit smp_xics_setup_cpu(int cpu)
327 cpu_clear(cpu, of_spin_map); 329 cpu_clear(cpu, of_spin_map);
328 330
329} 331}
332#endif /* CONFIG_XICS */
333#ifdef CONFIG_BPA_IIC
334static void smp_iic_message_pass(int target, int msg)
335{
336 unsigned int i;
337
338 if (target < NR_CPUS) {
339 iic_cause_IPI(target, msg);
340 } else {
341 for_each_online_cpu(i) {
342 if (target == MSG_ALL_BUT_SELF
343 && i == smp_processor_id())
344 continue;
345 iic_cause_IPI(i, msg);
346 }
347 }
348}
349
350static int __init smp_iic_probe(void)
351{
352 iic_request_IPIs();
353
354 return cpus_weight(cpu_possible_map);
355}
356
357static void __devinit smp_iic_setup_cpu(int cpu)
358{
359 if (cpu != boot_cpuid)
360 iic_setup_cpu();
361}
362#endif /* CONFIG_BPA_IIC */
330 363
331static DEFINE_SPINLOCK(timebase_lock); 364static DEFINE_SPINLOCK(timebase_lock);
332static unsigned long timebase = 0; 365static unsigned long timebase = 0;
@@ -381,14 +414,15 @@ static int smp_pSeries_cpu_bootable(unsigned int nr)
381 414
382 return 1; 415 return 1;
383} 416}
384 417#ifdef CONFIG_MPIC
385static struct smp_ops_t pSeries_mpic_smp_ops = { 418static struct smp_ops_t pSeries_mpic_smp_ops = {
386 .message_pass = smp_mpic_message_pass, 419 .message_pass = smp_mpic_message_pass,
387 .probe = smp_mpic_probe, 420 .probe = smp_mpic_probe,
388 .kick_cpu = smp_pSeries_kick_cpu, 421 .kick_cpu = smp_pSeries_kick_cpu,
389 .setup_cpu = smp_mpic_setup_cpu, 422 .setup_cpu = smp_mpic_setup_cpu,
390}; 423};
391 424#endif
425#ifdef CONFIG_XICS
392static struct smp_ops_t pSeries_xics_smp_ops = { 426static struct smp_ops_t pSeries_xics_smp_ops = {
393 .message_pass = smp_xics_message_pass, 427 .message_pass = smp_xics_message_pass,
394 .probe = smp_xics_probe, 428 .probe = smp_xics_probe,
@@ -396,6 +430,16 @@ static struct smp_ops_t pSeries_xics_smp_ops = {
396 .setup_cpu = smp_xics_setup_cpu, 430 .setup_cpu = smp_xics_setup_cpu,
397 .cpu_bootable = smp_pSeries_cpu_bootable, 431 .cpu_bootable = smp_pSeries_cpu_bootable,
398}; 432};
433#endif
434#ifdef CONFIG_BPA_IIC
435static struct smp_ops_t bpa_iic_smp_ops = {
436 .message_pass = smp_iic_message_pass,
437 .probe = smp_iic_probe,
438 .kick_cpu = smp_pSeries_kick_cpu,
439 .setup_cpu = smp_iic_setup_cpu,
440 .cpu_bootable = smp_pSeries_cpu_bootable,
441};
442#endif
399 443
400/* This is called very early */ 444/* This is called very early */
401void __init smp_init_pSeries(void) 445void __init smp_init_pSeries(void)
@@ -404,10 +448,25 @@ void __init smp_init_pSeries(void)
404 448
405 DBG(" -> smp_init_pSeries()\n"); 449 DBG(" -> smp_init_pSeries()\n");
406 450
407 if (ppc64_interrupt_controller == IC_OPEN_PIC) 451 switch (ppc64_interrupt_controller) {
452#ifdef CONFIG_MPIC
453 case IC_OPEN_PIC:
408 smp_ops = &pSeries_mpic_smp_ops; 454 smp_ops = &pSeries_mpic_smp_ops;
409 else 455 break;
456#endif
457#ifdef CONFIG_XICS
458 case IC_PPC_XIC:
410 smp_ops = &pSeries_xics_smp_ops; 459 smp_ops = &pSeries_xics_smp_ops;
460 break;
461#endif
462#ifdef CONFIG_BPA_IIC
463 case IC_BPA_IIC:
464 smp_ops = &bpa_iic_smp_ops;
465 break;
466#endif
467 default:
468 panic("Invalid interrupt controller");
469 }
411 470
412#ifdef CONFIG_HOTPLUG_CPU 471#ifdef CONFIG_HOTPLUG_CPU
413 smp_ops->cpu_disable = pSeries_cpu_disable; 472 smp_ops->cpu_disable = pSeries_cpu_disable;