diff options
author | Ashok Raj <ashok.raj@intel.com> | 2005-11-11 17:32:40 -0500 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2006-01-05 13:24:20 -0500 |
commit | ff741906ad3cf4b8ca1a958acb013a97a6381ca2 (patch) | |
tree | 66a4c2dbacd4c10015824a6789f9206693003092 /arch/ia64/kernel/smpboot.c | |
parent | db9edfd7e339ca4113153d887e782dd05be5a9eb (diff) |
[IA64] support for cpu0 removal
here is the BSP removal support for IA64. Its pretty much the same thing that
was released a while back, but has your feedback incorporated.
- Removed CONFIG_BSP_REMOVE_WORKAROUND and associated cmdline param
- Fixed compile issue with sn2/zx1 due to a undefined fix_b0_for_bsp
- some formatting nits (whitespace etc)
This has been tested on tiger and long back by alex on hp systems as well.
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.c | 114 |
1 files changed, 108 insertions, 6 deletions
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 8f44e7d2df66..e9d37bf67d69 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c | |||
@@ -70,6 +70,12 @@ | |||
70 | #endif | 70 | #endif |
71 | 71 | ||
72 | #ifdef CONFIG_HOTPLUG_CPU | 72 | #ifdef CONFIG_HOTPLUG_CPU |
73 | #ifdef CONFIG_PERMIT_BSP_REMOVE | ||
74 | #define bsp_remove_ok 1 | ||
75 | #else | ||
76 | #define bsp_remove_ok 0 | ||
77 | #endif | ||
78 | |||
73 | /* | 79 | /* |
74 | * Store all idle threads, this can be reused instead of creating | 80 | * Store all idle threads, this can be reused instead of creating |
75 | * a new thread. Also avoids complicated thread destroy functionality | 81 | * a new thread. Also avoids complicated thread destroy functionality |
@@ -104,7 +110,7 @@ struct sal_to_os_boot *sal_state_for_booting_cpu = &sal_boot_rendez_state[0]; | |||
104 | /* | 110 | /* |
105 | * ITC synchronization related stuff: | 111 | * ITC synchronization related stuff: |
106 | */ | 112 | */ |
107 | #define MASTER 0 | 113 | #define MASTER (0) |
108 | #define SLAVE (SMP_CACHE_BYTES/8) | 114 | #define SLAVE (SMP_CACHE_BYTES/8) |
109 | 115 | ||
110 | #define NUM_ROUNDS 64 /* magic value */ | 116 | #define NUM_ROUNDS 64 /* magic value */ |
@@ -151,6 +157,27 @@ char __initdata no_int_routing; | |||
151 | 157 | ||
152 | unsigned char smp_int_redirect; /* are INT and IPI redirectable by the chipset? */ | 158 | unsigned char smp_int_redirect; /* are INT and IPI redirectable by the chipset? */ |
153 | 159 | ||
160 | #ifdef CONFIG_FORCE_CPEI_RETARGET | ||
161 | #define CPEI_OVERRIDE_DEFAULT (1) | ||
162 | #else | ||
163 | #define CPEI_OVERRIDE_DEFAULT (0) | ||
164 | #endif | ||
165 | |||
166 | unsigned int force_cpei_retarget = CPEI_OVERRIDE_DEFAULT; | ||
167 | |||
168 | static int __init | ||
169 | cmdl_force_cpei(char *str) | ||
170 | { | ||
171 | int value=0; | ||
172 | |||
173 | get_option (&str, &value); | ||
174 | force_cpei_retarget = value; | ||
175 | |||
176 | return 1; | ||
177 | } | ||
178 | |||
179 | __setup("force_cpei=", cmdl_force_cpei); | ||
180 | |||
154 | static int __init | 181 | static int __init |
155 | nointroute (char *str) | 182 | nointroute (char *str) |
156 | { | 183 | { |
@@ -161,6 +188,27 @@ nointroute (char *str) | |||
161 | 188 | ||
162 | __setup("nointroute", nointroute); | 189 | __setup("nointroute", nointroute); |
163 | 190 | ||
191 | static void fix_b0_for_bsp(void) | ||
192 | { | ||
193 | #ifdef CONFIG_HOTPLUG_CPU | ||
194 | int cpuid; | ||
195 | static int fix_bsp_b0 = 1; | ||
196 | |||
197 | cpuid = smp_processor_id(); | ||
198 | |||
199 | /* | ||
200 | * Cache the b0 value on the first AP that comes up | ||
201 | */ | ||
202 | if (!(fix_bsp_b0 && cpuid)) | ||
203 | return; | ||
204 | |||
205 | sal_boot_rendez_state[0].br[0] = sal_boot_rendez_state[cpuid].br[0]; | ||
206 | printk ("Fixed BSP b0 value from CPU %d\n", cpuid); | ||
207 | |||
208 | fix_bsp_b0 = 0; | ||
209 | #endif | ||
210 | } | ||
211 | |||
164 | void | 212 | void |
165 | sync_master (void *arg) | 213 | sync_master (void *arg) |
166 | { | 214 | { |
@@ -327,8 +375,9 @@ smp_setup_percpu_timer (void) | |||
327 | static void __devinit | 375 | static void __devinit |
328 | smp_callin (void) | 376 | smp_callin (void) |
329 | { | 377 | { |
330 | int cpuid, phys_id; | 378 | int cpuid, phys_id, itc_master; |
331 | extern void ia64_init_itm(void); | 379 | extern void ia64_init_itm(void); |
380 | extern volatile int time_keeper_id; | ||
332 | 381 | ||
333 | #ifdef CONFIG_PERFMON | 382 | #ifdef CONFIG_PERFMON |
334 | extern void pfm_init_percpu(void); | 383 | extern void pfm_init_percpu(void); |
@@ -336,6 +385,7 @@ smp_callin (void) | |||
336 | 385 | ||
337 | cpuid = smp_processor_id(); | 386 | cpuid = smp_processor_id(); |
338 | phys_id = hard_smp_processor_id(); | 387 | phys_id = hard_smp_processor_id(); |
388 | itc_master = time_keeper_id; | ||
339 | 389 | ||
340 | if (cpu_online(cpuid)) { | 390 | if (cpu_online(cpuid)) { |
341 | printk(KERN_ERR "huh, phys CPU#0x%x, CPU#0x%x already present??\n", | 391 | printk(KERN_ERR "huh, phys CPU#0x%x, CPU#0x%x already present??\n", |
@@ -343,6 +393,8 @@ smp_callin (void) | |||
343 | BUG(); | 393 | BUG(); |
344 | } | 394 | } |
345 | 395 | ||
396 | fix_b0_for_bsp(); | ||
397 | |||
346 | lock_ipi_calllock(); | 398 | lock_ipi_calllock(); |
347 | cpu_set(cpuid, cpu_online_map); | 399 | cpu_set(cpuid, cpu_online_map); |
348 | unlock_ipi_calllock(); | 400 | unlock_ipi_calllock(); |
@@ -365,8 +417,8 @@ smp_callin (void) | |||
365 | * calls spin_unlock_bh(), which calls spin_unlock_bh(), which calls | 417 | * calls spin_unlock_bh(), which calls spin_unlock_bh(), which calls |
366 | * local_bh_enable(), which bugs out if irqs are not enabled... | 418 | * local_bh_enable(), which bugs out if irqs are not enabled... |
367 | */ | 419 | */ |
368 | Dprintk("Going to syncup ITC with BP.\n"); | 420 | Dprintk("Going to syncup ITC with ITC Master.\n"); |
369 | ia64_sync_itc(0); | 421 | ia64_sync_itc(itc_master); |
370 | } | 422 | } |
371 | 423 | ||
372 | /* | 424 | /* |
@@ -638,6 +690,47 @@ remove_siblinginfo(int cpu) | |||
638 | } | 690 | } |
639 | 691 | ||
640 | extern void fixup_irqs(void); | 692 | extern void fixup_irqs(void); |
693 | |||
694 | int migrate_platform_irqs(unsigned int cpu) | ||
695 | { | ||
696 | int new_cpei_cpu; | ||
697 | irq_desc_t *desc = NULL; | ||
698 | cpumask_t mask; | ||
699 | int retval = 0; | ||
700 | |||
701 | /* | ||
702 | * dont permit CPEI target to removed. | ||
703 | */ | ||
704 | if (cpe_vector > 0 && is_cpu_cpei_target(cpu)) { | ||
705 | printk ("CPU (%d) is CPEI Target\n", cpu); | ||
706 | if (can_cpei_retarget()) { | ||
707 | /* | ||
708 | * Now re-target the CPEI to a different processor | ||
709 | */ | ||
710 | new_cpei_cpu = any_online_cpu(cpu_online_map); | ||
711 | mask = cpumask_of_cpu(new_cpei_cpu); | ||
712 | set_cpei_target_cpu(new_cpei_cpu); | ||
713 | desc = irq_descp(ia64_cpe_irq); | ||
714 | /* | ||
715 | * Switch for now, immediatly, we need to do fake intr | ||
716 | * as other interrupts, but need to study CPEI behaviour with | ||
717 | * polling before making changes. | ||
718 | */ | ||
719 | if (desc) { | ||
720 | desc->handler->disable(ia64_cpe_irq); | ||
721 | desc->handler->set_affinity(ia64_cpe_irq, mask); | ||
722 | desc->handler->enable(ia64_cpe_irq); | ||
723 | printk ("Re-targetting CPEI to cpu %d\n", new_cpei_cpu); | ||
724 | } | ||
725 | } | ||
726 | if (!desc) { | ||
727 | printk ("Unable to retarget CPEI, offline cpu [%d] failed\n", cpu); | ||
728 | retval = -EBUSY; | ||
729 | } | ||
730 | } | ||
731 | return retval; | ||
732 | } | ||
733 | |||
641 | /* must be called with cpucontrol mutex held */ | 734 | /* must be called with cpucontrol mutex held */ |
642 | int __cpu_disable(void) | 735 | int __cpu_disable(void) |
643 | { | 736 | { |
@@ -646,8 +739,17 @@ int __cpu_disable(void) | |||
646 | /* | 739 | /* |
647 | * dont permit boot processor for now | 740 | * dont permit boot processor for now |
648 | */ | 741 | */ |
649 | if (cpu == 0) | 742 | if (cpu == 0 && !bsp_remove_ok) { |
650 | return -EBUSY; | 743 | printk ("Your platform does not support removal of BSP\n"); |
744 | return (-EBUSY); | ||
745 | } | ||
746 | |||
747 | cpu_clear(cpu, cpu_online_map); | ||
748 | |||
749 | if (migrate_platform_irqs(cpu)) { | ||
750 | cpu_set(cpu, cpu_online_map); | ||
751 | return (-EBUSY); | ||
752 | } | ||
651 | 753 | ||
652 | remove_siblinginfo(cpu); | 754 | remove_siblinginfo(cpu); |
653 | cpu_clear(cpu, cpu_online_map); | 755 | cpu_clear(cpu, cpu_online_map); |