diff options
author | Dave Jones <davej@redhat.com> | 2006-12-12 17:41:41 -0500 |
---|---|---|
committer | Dave Jones <davej@redhat.com> | 2006-12-12 17:41:41 -0500 |
commit | c4366889dda8110247be59ca41fddb82951a8c26 (patch) | |
tree | 705c1a996bed8fd48ce94ff33ec9fd00f9b94875 /arch/x86_64/kernel/smpboot.c | |
parent | db2fb9db5735cc532fd4fc55e94b9a3c3750378e (diff) | |
parent | e1036502e5263851259d147771226161e5ccc85a (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.c | 27 |
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 */ |
65 | int smp_num_siblings = 1; | 66 | int 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 | ||
751 | struct create_idle { | 756 | struct 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 | ||
757 | void do_fork_idle(void *_c_idle) | 763 | void 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; |