diff options
Diffstat (limited to 'arch/x86_64/kernel/smpboot.c')
-rw-r--r-- | arch/x86_64/kernel/smpboot.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 62c2e747af58..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; |
@@ -753,14 +754,16 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta | |||
753 | } | 754 | } |
754 | 755 | ||
755 | struct create_idle { | 756 | struct create_idle { |
757 | struct work_struct work; | ||
756 | struct task_struct *idle; | 758 | struct task_struct *idle; |
757 | struct completion done; | 759 | struct completion done; |
758 | int cpu; | 760 | int cpu; |
759 | }; | 761 | }; |
760 | 762 | ||
761 | void do_fork_idle(void *_c_idle) | 763 | void do_fork_idle(struct work_struct *work) |
762 | { | 764 | { |
763 | struct create_idle *c_idle = _c_idle; | 765 | struct create_idle *c_idle = |
766 | container_of(work, struct create_idle, work); | ||
764 | 767 | ||
765 | c_idle->idle = fork_idle(c_idle->cpu); | 768 | c_idle->idle = fork_idle(c_idle->cpu); |
766 | complete(&c_idle->done); | 769 | complete(&c_idle->done); |
@@ -775,10 +778,10 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid) | |||
775 | int timeout; | 778 | int timeout; |
776 | unsigned long start_rip; | 779 | unsigned long start_rip; |
777 | struct create_idle c_idle = { | 780 | struct create_idle c_idle = { |
781 | .work = __WORK_INITIALIZER(c_idle.work, do_fork_idle), | ||
778 | .cpu = cpu, | 782 | .cpu = cpu, |
779 | .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), | 783 | .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), |
780 | }; | 784 | }; |
781 | DECLARE_WORK(work, do_fork_idle, &c_idle); | ||
782 | 785 | ||
783 | /* allocate memory for gdts of secondary cpus. Hotplug is considered */ | 786 | /* allocate memory for gdts of secondary cpus. Hotplug is considered */ |
784 | if (!cpu_gdt_descr[cpu].address && | 787 | if (!cpu_gdt_descr[cpu].address && |
@@ -825,9 +828,9 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid) | |||
825 | * thread. | 828 | * thread. |
826 | */ | 829 | */ |
827 | if (!keventd_up() || current_is_keventd()) | 830 | if (!keventd_up() || current_is_keventd()) |
828 | work.func(work.data); | 831 | c_idle.work.func(&c_idle.work); |
829 | else { | 832 | else { |
830 | schedule_work(&work); | 833 | schedule_work(&c_idle.work); |
831 | wait_for_completion(&c_idle.done); | 834 | wait_for_completion(&c_idle.done); |
832 | } | 835 | } |
833 | 836 | ||
@@ -1167,6 +1170,13 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
1167 | 1170 | ||
1168 | while (!cpu_isset(cpu, cpu_online_map)) | 1171 | while (!cpu_isset(cpu, cpu_online_map)) |
1169 | 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 | |||
1170 | err = 0; | 1180 | err = 0; |
1171 | 1181 | ||
1172 | return err; | 1182 | return err; |