aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/smpboot.c
diff options
context:
space:
mode:
authorDave Jones <davej@redhat.com>2006-12-12 17:41:41 -0500
committerDave Jones <davej@redhat.com>2006-12-12 17:41:41 -0500
commitc4366889dda8110247be59ca41fddb82951a8c26 (patch)
tree705c1a996bed8fd48ce94ff33ec9fd00f9b94875 /arch/x86_64/kernel/smpboot.c
parentdb2fb9db5735cc532fd4fc55e94b9a3c3750378e (diff)
parente1036502e5263851259d147771226161e5ccc85a (diff)
Merge ../linus
Conflicts: drivers/cpufreq/cpufreq.c
Diffstat (limited to 'arch/x86_64/kernel/smpboot.c')
-rw-r--r--arch/x86_64/kernel/smpboot.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 7b7a6870288a..daf19332f0dd 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -60,6 +60,7 @@
60#include <asm/irq.h> 60#include <asm/irq.h>
61#include <asm/hw_irq.h> 61#include <asm/hw_irq.h>
62#include <asm/numa.h> 62#include <asm/numa.h>
63#include <asm/genapic.h>
63 64
64/* Number of siblings per CPU package */ 65/* Number of siblings per CPU package */
65int smp_num_siblings = 1; 66int smp_num_siblings = 1;
@@ -581,12 +582,16 @@ void __cpuinit start_secondary(void)
581 * smp_call_function(). 582 * smp_call_function().
582 */ 583 */
583 lock_ipi_call_lock(); 584 lock_ipi_call_lock();
585 spin_lock(&vector_lock);
584 586
587 /* Setup the per cpu irq handling data structures */
588 __setup_vector_irq(smp_processor_id());
585 /* 589 /*
586 * Allow the master to continue. 590 * Allow the master to continue.
587 */ 591 */
588 cpu_set(smp_processor_id(), cpu_online_map); 592 cpu_set(smp_processor_id(), cpu_online_map);
589 per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; 593 per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
594 spin_unlock(&vector_lock);
590 unlock_ipi_call_lock(); 595 unlock_ipi_call_lock();
591 596
592 cpu_idle(); 597 cpu_idle();
@@ -749,14 +754,16 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
749} 754}
750 755
751struct create_idle { 756struct create_idle {
757 struct work_struct work;
752 struct task_struct *idle; 758 struct task_struct *idle;
753 struct completion done; 759 struct completion done;
754 int cpu; 760 int cpu;
755}; 761};
756 762
757void do_fork_idle(void *_c_idle) 763void do_fork_idle(struct work_struct *work)
758{ 764{
759 struct create_idle *c_idle = _c_idle; 765 struct create_idle *c_idle =
766 container_of(work, struct create_idle, work);
760 767
761 c_idle->idle = fork_idle(c_idle->cpu); 768 c_idle->idle = fork_idle(c_idle->cpu);
762 complete(&c_idle->done); 769 complete(&c_idle->done);
@@ -771,10 +778,10 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
771 int timeout; 778 int timeout;
772 unsigned long start_rip; 779 unsigned long start_rip;
773 struct create_idle c_idle = { 780 struct create_idle c_idle = {
781 .work = __WORK_INITIALIZER(c_idle.work, do_fork_idle),
774 .cpu = cpu, 782 .cpu = cpu,
775 .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), 783 .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
776 }; 784 };
777 DECLARE_WORK(work, do_fork_idle, &c_idle);
778 785
779 /* allocate memory for gdts of secondary cpus. Hotplug is considered */ 786 /* allocate memory for gdts of secondary cpus. Hotplug is considered */
780 if (!cpu_gdt_descr[cpu].address && 787 if (!cpu_gdt_descr[cpu].address &&
@@ -799,7 +806,6 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
799 cpu, node); 806 cpu, node);
800 } 807 }
801 808
802
803 alternatives_smp_switch(1); 809 alternatives_smp_switch(1);
804 810
805 c_idle.idle = get_idle_for_cpu(cpu); 811 c_idle.idle = get_idle_for_cpu(cpu);
@@ -822,9 +828,9 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
822 * thread. 828 * thread.
823 */ 829 */
824 if (!keventd_up() || current_is_keventd()) 830 if (!keventd_up() || current_is_keventd())
825 work.func(work.data); 831 c_idle.work.func(&c_idle.work);
826 else { 832 else {
827 schedule_work(&work); 833 schedule_work(&c_idle.work);
828 wait_for_completion(&c_idle.done); 834 wait_for_completion(&c_idle.done);
829 } 835 }
830 836
@@ -1164,6 +1170,13 @@ int __cpuinit __cpu_up(unsigned int cpu)
1164 1170
1165 while (!cpu_isset(cpu, cpu_online_map)) 1171 while (!cpu_isset(cpu, cpu_online_map))
1166 cpu_relax(); 1172 cpu_relax();
1173
1174 if (num_online_cpus() > 8 && genapic == &apic_flat) {
1175 printk(KERN_WARNING
1176 "flat APIC routing can't be used with > 8 cpus\n");
1177 BUG();
1178 }
1179
1167 err = 0; 1180 err = 0;
1168 1181
1169 return err; 1182 return err;
@@ -1246,8 +1259,10 @@ int __cpu_disable(void)
1246 local_irq_disable(); 1259 local_irq_disable();
1247 remove_siblinginfo(cpu); 1260 remove_siblinginfo(cpu);
1248 1261
1262 spin_lock(&vector_lock);
1249 /* It's now safe to remove this processor from the online map */ 1263 /* It's now safe to remove this processor from the online map */
1250 cpu_clear(cpu, cpu_online_map); 1264 cpu_clear(cpu, cpu_online_map);
1265 spin_unlock(&vector_lock);
1251 remove_cpu_from_maps(); 1266 remove_cpu_from_maps();
1252 fixup_irqs(cpu_online_map); 1267 fixup_irqs(cpu_online_map);
1253 return 0; 1268 return 0;