aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/smpboot.c
diff options
context:
space:
mode:
authorAshok Raj <ashok.raj@intel.com>2005-04-22 17:44:40 -0400
committerTony Luck <tony.luck@intel.com>2005-04-22 17:44:40 -0400
commitb8d8b883e6f029e99c35c88f853501740e322131 (patch)
tree391f2ade8823149f217991eb02911bf3dacce050 /arch/ia64/kernel/smpboot.c
parent7130667107cd3ab9d6802b69bab63c7d22f20bd4 (diff)
[IA64] cpu hotplug: return offlined cpus to SAL
This patch is required to support cpu removal for IPF systems. Existing code just fakes the real offline by keeping it run the idle thread, and polling for the bit to re-appear in the cpu_state to get out of the idle loop. For the cpu-offline to work correctly, we need to pass control of this CPU back to SAL so it can continue in the boot-rendez mode. This gives the SAL control to not pick this cpu as the monarch processor for global MCA events, and addition does not wait for this cpu to checkin with SAL for global MCA events as well. The handoff is implemented as documented in SAL specification section 3.2.5.1 "OS_BOOT_RENDEZ to SAL return State" Signed-off-by: Ashok Raj <ashok.raj@intel.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
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 5318f0cbfc2..ca1536db339 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)