aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/smpboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel/smpboot.c')
-rw-r--r--arch/ia64/kernel/smpboot.c81
1 files changed, 50 insertions, 31 deletions
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 5318f0cbfc26..ca1536db3394 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -9,6 +9,7 @@
9 * 02/07/31 David Mosberger <davidm@hpl.hp.com> Switch over to hotplug-CPU boot-sequence. 9 * 02/07/31 David Mosberger <davidm@hpl.hp.com> Switch over to hotplug-CPU boot-sequence.
10 * smp_boot_cpus()/smp_commence() is replaced by 10 * smp_boot_cpus()/smp_commence() is replaced by
11 * smp_prepare_cpus()/__cpu_up()/smp_cpus_done(). 11 * smp_prepare_cpus()/__cpu_up()/smp_cpus_done().
12 * 04/06/21 Ashok Raj <ashok.raj@intel.com> Added CPU Hotplug Support
12 */ 13 */
13#include <linux/config.h> 14#include <linux/config.h>
14 15
@@ -58,6 +59,37 @@
58#define Dprintk(x...) 59#define Dprintk(x...)
59#endif 60#endif
60 61
62#ifdef CONFIG_HOTPLUG_CPU
63/*
64 * Store all idle threads, this can be reused instead of creating
65 * a new thread. Also avoids complicated thread destroy functionality
66 * for idle threads.
67 */
68struct task_struct *idle_thread_array[NR_CPUS];
69
70/*
71 * Global array allocated for NR_CPUS at boot time
72 */
73struct sal_to_os_boot sal_boot_rendez_state[NR_CPUS];
74
75/*
76 * start_ap in head.S uses this to store current booting cpu
77 * info.
78 */
79struct sal_to_os_boot *sal_state_for_booting_cpu = &sal_boot_rendez_state[0];
80
81#define set_brendez_area(x) (sal_state_for_booting_cpu = &sal_boot_rendez_state[(x)]);
82
83#define get_idle_for_cpu(x) (idle_thread_array[(x)])
84#define set_idle_for_cpu(x,p) (idle_thread_array[(x)] = (p))
85
86#else
87
88#define get_idle_for_cpu(x) (NULL)
89#define set_idle_for_cpu(x,p)
90#define set_brendez_area(x)
91#endif
92
61 93
62/* 94/*
63 * ITC synchronization related stuff: 95 * ITC synchronization related stuff:
@@ -345,7 +377,6 @@ start_secondary (void *unused)
345{ 377{
346 /* Early console may use I/O ports */ 378 /* Early console may use I/O ports */
347 ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase)); 379 ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
348
349 Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id()); 380 Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id());
350 efi_map_pal_code(); 381 efi_map_pal_code();
351 cpu_init(); 382 cpu_init();
@@ -384,6 +415,13 @@ do_boot_cpu (int sapicid, int cpu)
384 .done = COMPLETION_INITIALIZER(c_idle.done), 415 .done = COMPLETION_INITIALIZER(c_idle.done),
385 }; 416 };
386 DECLARE_WORK(work, do_fork_idle, &c_idle); 417 DECLARE_WORK(work, do_fork_idle, &c_idle);
418
419 c_idle.idle = get_idle_for_cpu(cpu);
420 if (c_idle.idle) {
421 init_idle(c_idle.idle, cpu);
422 goto do_rest;
423 }
424
387 /* 425 /*
388 * We can't use kernel_thread since we must avoid to reschedule the child. 426 * We can't use kernel_thread since we must avoid to reschedule the child.
389 */ 427 */
@@ -396,10 +434,15 @@ do_boot_cpu (int sapicid, int cpu)
396 434
397 if (IS_ERR(c_idle.idle)) 435 if (IS_ERR(c_idle.idle))
398 panic("failed fork for CPU %d", cpu); 436 panic("failed fork for CPU %d", cpu);
437
438 set_idle_for_cpu(cpu, c_idle.idle);
439
440do_rest:
399 task_for_booting_cpu = c_idle.idle; 441 task_for_booting_cpu = c_idle.idle;
400 442
401 Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid); 443 Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
402 444
445 set_brendez_area(cpu);
403 platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0); 446 platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);
404 447
405 /* 448 /*
@@ -555,16 +598,6 @@ void __devinit smp_prepare_boot_cpu(void)
555#ifdef CONFIG_HOTPLUG_CPU 598#ifdef CONFIG_HOTPLUG_CPU
556extern void fixup_irqs(void); 599extern void fixup_irqs(void);
557/* must be called with cpucontrol mutex held */ 600/* must be called with cpucontrol mutex held */
558static int __devinit cpu_enable(unsigned int cpu)
559{
560 per_cpu(cpu_state,cpu) = CPU_UP_PREPARE;
561 wmb();
562
563 while (!cpu_online(cpu))
564 cpu_relax();
565 return 0;
566}
567
568int __cpu_disable(void) 601int __cpu_disable(void)
569{ 602{
570 int cpu = smp_processor_id(); 603 int cpu = smp_processor_id();
@@ -577,7 +610,7 @@ int __cpu_disable(void)
577 610
578 fixup_irqs(); 611 fixup_irqs();
579 local_flush_tlb_all(); 612 local_flush_tlb_all();
580 printk ("Disabled cpu %u\n", smp_processor_id()); 613 cpu_clear(cpu, cpu_callin_map);
581 return 0; 614 return 0;
582} 615}
583 616
@@ -589,12 +622,7 @@ void __cpu_die(unsigned int cpu)
589 /* They ack this in play_dead by setting CPU_DEAD */ 622 /* They ack this in play_dead by setting CPU_DEAD */
590 if (per_cpu(cpu_state, cpu) == CPU_DEAD) 623 if (per_cpu(cpu_state, cpu) == CPU_DEAD)
591 { 624 {
592 /* 625 printk ("CPU %d is now offline\n", cpu);
593 * TBD: Enable this when physical removal
594 * or when we put the processor is put in
595 * SAL_BOOT_RENDEZ mode
596 * cpu_clear(cpu, cpu_callin_map);
597 */
598 return; 626 return;
599 } 627 }
600 msleep(100); 628 msleep(100);
@@ -602,11 +630,6 @@ void __cpu_die(unsigned int cpu)
602 printk(KERN_ERR "CPU %u didn't die...\n", cpu); 630 printk(KERN_ERR "CPU %u didn't die...\n", cpu);
603} 631}
604#else /* !CONFIG_HOTPLUG_CPU */ 632#else /* !CONFIG_HOTPLUG_CPU */
605static int __devinit cpu_enable(unsigned int cpu)
606{
607 return 0;
608}
609
610int __cpu_disable(void) 633int __cpu_disable(void)
611{ 634{
612 return -ENOSYS; 635 return -ENOSYS;
@@ -648,16 +671,12 @@ __cpu_up (unsigned int cpu)
648 return -EINVAL; 671 return -EINVAL;
649 672
650 /* 673 /*
651 * Already booted.. just enable and get outa idle lool 674 * Already booted cpu? not valid anymore since we dont
675 * do idle loop tightspin anymore.
652 */ 676 */
653 if (cpu_isset(cpu, cpu_callin_map)) 677 if (cpu_isset(cpu, cpu_callin_map))
654 { 678 return -EINVAL;
655 cpu_enable(cpu); 679
656 local_irq_enable();
657 while (!cpu_isset(cpu, cpu_online_map))
658 mb();
659 return 0;
660 }
661 /* Processor goes to start_secondary(), sets online flag */ 680 /* Processor goes to start_secondary(), sets online flag */
662 ret = do_boot_cpu(sapicid, cpu); 681 ret = do_boot_cpu(sapicid, cpu);
663 if (ret < 0) 682 if (ret < 0)