diff options
Diffstat (limited to 'arch/ppc64/kernel/pSeries_smp.c')
-rw-r--r-- | arch/ppc64/kernel/pSeries_smp.c | 69 |
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 | ||
289 | static inline void smp_xics_do_message(int cpu, int msg) | 291 | static 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 | ||
334 | static 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 | |||
350 | static int __init smp_iic_probe(void) | ||
351 | { | ||
352 | iic_request_IPIs(); | ||
353 | |||
354 | return cpus_weight(cpu_possible_map); | ||
355 | } | ||
356 | |||
357 | static 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 | ||
331 | static DEFINE_SPINLOCK(timebase_lock); | 364 | static DEFINE_SPINLOCK(timebase_lock); |
332 | static unsigned long timebase = 0; | 365 | static 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 | |
385 | static struct smp_ops_t pSeries_mpic_smp_ops = { | 418 | static 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 | ||
392 | static struct smp_ops_t pSeries_xics_smp_ops = { | 426 | static 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 | ||
435 | static 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 */ |
401 | void __init smp_init_pSeries(void) | 445 | void __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; |