diff options
author | Tony Luck <tony.luck@intel.com> | 2006-03-21 11:16:21 -0500 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2006-03-21 11:16:21 -0500 |
commit | 536ea4e4198eeaa5a73fb734ea675e621609bb7e (patch) | |
tree | 321384a2233413d7df5f00b3356116c8b05ef08d /arch/ia64/kernel/smpboot.c | |
parent | 7705a8792b0fc82fd7d4dd923724606bbfd9fb20 (diff) | |
parent | b88e926584bf100bc23f5e76b7b674d4257edcb0 (diff) |
Pull bsp-removal into release branch
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 b681ef34a86e..c4b633b36dab 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 | /* |
@@ -635,6 +687,47 @@ remove_siblinginfo(int cpu) | |||
635 | } | 687 | } |
636 | 688 | ||
637 | extern void fixup_irqs(void); | 689 | extern void fixup_irqs(void); |
690 | |||
691 | int migrate_platform_irqs(unsigned int cpu) | ||
692 | { | ||
693 | int new_cpei_cpu; | ||
694 | irq_desc_t *desc = NULL; | ||
695 | cpumask_t mask; | ||
696 | int retval = 0; | ||
697 | |||
698 | /* | ||
699 | * dont permit CPEI target to removed. | ||
700 | */ | ||
701 | if (cpe_vector > 0 && is_cpu_cpei_target(cpu)) { | ||
702 | printk ("CPU (%d) is CPEI Target\n", cpu); | ||
703 | if (can_cpei_retarget()) { | ||
704 | /* | ||
705 | * Now re-target the CPEI to a different processor | ||
706 | */ | ||
707 | new_cpei_cpu = any_online_cpu(cpu_online_map); | ||
708 | mask = cpumask_of_cpu(new_cpei_cpu); | ||
709 | set_cpei_target_cpu(new_cpei_cpu); | ||
710 | desc = irq_descp(ia64_cpe_irq); | ||
711 | /* | ||
712 | * Switch for now, immediatly, we need to do fake intr | ||
713 | * as other interrupts, but need to study CPEI behaviour with | ||
714 | * polling before making changes. | ||
715 | */ | ||
716 | if (desc) { | ||
717 | desc->handler->disable(ia64_cpe_irq); | ||
718 | desc->handler->set_affinity(ia64_cpe_irq, mask); | ||
719 | desc->handler->enable(ia64_cpe_irq); | ||
720 | printk ("Re-targetting CPEI to cpu %d\n", new_cpei_cpu); | ||
721 | } | ||
722 | } | ||
723 | if (!desc) { | ||
724 | printk ("Unable to retarget CPEI, offline cpu [%d] failed\n", cpu); | ||
725 | retval = -EBUSY; | ||
726 | } | ||
727 | } | ||
728 | return retval; | ||
729 | } | ||
730 | |||
638 | /* must be called with cpucontrol mutex held */ | 731 | /* must be called with cpucontrol mutex held */ |
639 | int __cpu_disable(void) | 732 | int __cpu_disable(void) |
640 | { | 733 | { |
@@ -643,8 +736,17 @@ int __cpu_disable(void) | |||
643 | /* | 736 | /* |
644 | * dont permit boot processor for now | 737 | * dont permit boot processor for now |
645 | */ | 738 | */ |
646 | if (cpu == 0) | 739 | if (cpu == 0 && !bsp_remove_ok) { |
647 | return -EBUSY; | 740 | printk ("Your platform does not support removal of BSP\n"); |
741 | return (-EBUSY); | ||
742 | } | ||
743 | |||
744 | cpu_clear(cpu, cpu_online_map); | ||
745 | |||
746 | if (migrate_platform_irqs(cpu)) { | ||
747 | cpu_set(cpu, cpu_online_map); | ||
748 | return (-EBUSY); | ||
749 | } | ||
648 | 750 | ||
649 | remove_siblinginfo(cpu); | 751 | remove_siblinginfo(cpu); |
650 | cpu_clear(cpu, cpu_online_map); | 752 | cpu_clear(cpu, cpu_online_map); |