diff options
Diffstat (limited to 'arch/i386/kernel/smpboot.c')
-rw-r--r-- | arch/i386/kernel/smpboot.c | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 4c470e99a742..82371d83bfa9 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c | |||
@@ -1003,7 +1003,6 @@ void cpu_exit_clear(void) | |||
1003 | 1003 | ||
1004 | cpu_clear(cpu, cpu_callout_map); | 1004 | cpu_clear(cpu, cpu_callout_map); |
1005 | cpu_clear(cpu, cpu_callin_map); | 1005 | cpu_clear(cpu, cpu_callin_map); |
1006 | cpu_clear(cpu, cpu_present_map); | ||
1007 | 1006 | ||
1008 | cpu_clear(cpu, smp_commenced_mask); | 1007 | cpu_clear(cpu, smp_commenced_mask); |
1009 | unmap_cpu_to_logical_apicid(cpu); | 1008 | unmap_cpu_to_logical_apicid(cpu); |
@@ -1015,31 +1014,20 @@ struct warm_boot_cpu_info { | |||
1015 | int cpu; | 1014 | int cpu; |
1016 | }; | 1015 | }; |
1017 | 1016 | ||
1018 | static void __devinit do_warm_boot_cpu(void *p) | 1017 | static void __cpuinit do_warm_boot_cpu(void *p) |
1019 | { | 1018 | { |
1020 | struct warm_boot_cpu_info *info = p; | 1019 | struct warm_boot_cpu_info *info = p; |
1021 | do_boot_cpu(info->apicid, info->cpu); | 1020 | do_boot_cpu(info->apicid, info->cpu); |
1022 | complete(info->complete); | 1021 | complete(info->complete); |
1023 | } | 1022 | } |
1024 | 1023 | ||
1025 | int __devinit smp_prepare_cpu(int cpu) | 1024 | static int __cpuinit __smp_prepare_cpu(int cpu) |
1026 | { | 1025 | { |
1027 | DECLARE_COMPLETION(done); | 1026 | DECLARE_COMPLETION(done); |
1028 | struct warm_boot_cpu_info info; | 1027 | struct warm_boot_cpu_info info; |
1029 | struct work_struct task; | 1028 | struct work_struct task; |
1030 | int apicid, ret; | 1029 | int apicid, ret; |
1031 | 1030 | ||
1032 | lock_cpu_hotplug(); | ||
1033 | |||
1034 | /* | ||
1035 | * On x86, CPU0 is never offlined. Trying to bring up an | ||
1036 | * already-booted CPU will hang. So check for that case. | ||
1037 | */ | ||
1038 | if (cpu_online(cpu)) { | ||
1039 | ret = -EINVAL; | ||
1040 | goto exit; | ||
1041 | } | ||
1042 | |||
1043 | apicid = x86_cpu_to_apicid[cpu]; | 1031 | apicid = x86_cpu_to_apicid[cpu]; |
1044 | if (apicid == BAD_APICID) { | 1032 | if (apicid == BAD_APICID) { |
1045 | ret = -ENODEV; | 1033 | ret = -ENODEV; |
@@ -1064,7 +1052,6 @@ int __devinit smp_prepare_cpu(int cpu) | |||
1064 | zap_low_mappings(); | 1052 | zap_low_mappings(); |
1065 | ret = 0; | 1053 | ret = 0; |
1066 | exit: | 1054 | exit: |
1067 | unlock_cpu_hotplug(); | ||
1068 | return ret; | 1055 | return ret; |
1069 | } | 1056 | } |
1070 | #endif | 1057 | #endif |
@@ -1392,6 +1379,22 @@ void __cpu_die(unsigned int cpu) | |||
1392 | 1379 | ||
1393 | int __devinit __cpu_up(unsigned int cpu) | 1380 | int __devinit __cpu_up(unsigned int cpu) |
1394 | { | 1381 | { |
1382 | #ifdef CONFIG_HOTPLUG_CPU | ||
1383 | int ret=0; | ||
1384 | |||
1385 | /* | ||
1386 | * We do warm boot only on cpus that had booted earlier | ||
1387 | * Otherwise cold boot is all handled from smp_boot_cpus(). | ||
1388 | * cpu_callin_map is set during AP kickstart process. Its reset | ||
1389 | * when a cpu is taken offline from cpu_exit_clear(). | ||
1390 | */ | ||
1391 | if (!cpu_isset(cpu, cpu_callin_map)) | ||
1392 | ret = __smp_prepare_cpu(cpu); | ||
1393 | |||
1394 | if (ret) | ||
1395 | return -EIO; | ||
1396 | #endif | ||
1397 | |||
1395 | /* In case one didn't come up */ | 1398 | /* In case one didn't come up */ |
1396 | if (!cpu_isset(cpu, cpu_callin_map)) { | 1399 | if (!cpu_isset(cpu, cpu_callin_map)) { |
1397 | printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu); | 1400 | printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu); |