diff options
author | Ashok Raj <ashok.raj@intel.com> | 2006-03-25 06:08:18 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-25 11:23:01 -0500 |
commit | 34f361ade2fb4a869f6a7714d01c04ce4cfa75d9 (patch) | |
tree | a250999fc386ddbfe3c92e4d8ffdcf2d3393134a | |
parent | f1a1c2dc2a956c375b432d2a9a28e52ba9d81c7c (diff) |
[PATCH] Check if cpu can be onlined before calling smp_prepare_cpu()
- Moved check for online cpu out of smp_prepare_cpu()
- Moved default declaration of smp_prepare_cpu() to kernel/cpu.c
- Removed lock_cpu_hotplug() from smp_prepare_cpu() to around it, since
its called from cpu_up() as well now.
- Removed clearing from cpu_present_map during cpu_offline as it breaks
using cpu_up() directly during a subsequent online operation.
Signed-off-by: Ashok Raj <ashok.raj@intel.com>
Cc: Srivatsa Vaddagiri <vatsa@in.ibm.com>
Cc: "Li, Shaohua" <shaohua.li@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/i386/kernel/smpboot.c | 33 | ||||
-rw-r--r-- | drivers/base/cpu.c | 9 | ||||
-rw-r--r-- | include/linux/cpu.h | 1 | ||||
-rw-r--r-- | kernel/power/smp.c | 4 |
4 files changed, 20 insertions, 27 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); |
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 29f3d7504da1..dd712b24ec91 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
@@ -19,11 +19,6 @@ EXPORT_SYMBOL(cpu_sysdev_class); | |||
19 | static struct sys_device *cpu_sys_devices[NR_CPUS]; | 19 | static struct sys_device *cpu_sys_devices[NR_CPUS]; |
20 | 20 | ||
21 | #ifdef CONFIG_HOTPLUG_CPU | 21 | #ifdef CONFIG_HOTPLUG_CPU |
22 | int __attribute__((weak)) smp_prepare_cpu (int cpu) | ||
23 | { | ||
24 | return 0; | ||
25 | } | ||
26 | |||
27 | static ssize_t show_online(struct sys_device *dev, char *buf) | 22 | static ssize_t show_online(struct sys_device *dev, char *buf) |
28 | { | 23 | { |
29 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); | 24 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); |
@@ -44,9 +39,7 @@ static ssize_t store_online(struct sys_device *dev, const char *buf, | |||
44 | kobject_uevent(&dev->kobj, KOBJ_OFFLINE); | 39 | kobject_uevent(&dev->kobj, KOBJ_OFFLINE); |
45 | break; | 40 | break; |
46 | case '1': | 41 | case '1': |
47 | ret = smp_prepare_cpu(cpu->sysdev.id); | 42 | ret = cpu_up(cpu->sysdev.id); |
48 | if (!ret) | ||
49 | ret = cpu_up(cpu->sysdev.id); | ||
50 | if (!ret) | 43 | if (!ret) |
51 | kobject_uevent(&dev->kobj, KOBJ_ONLINE); | 44 | kobject_uevent(&dev->kobj, KOBJ_ONLINE); |
52 | break; | 45 | break; |
diff --git a/include/linux/cpu.h b/include/linux/cpu.h index d612b89dce33..08d50c53aab4 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h | |||
@@ -74,7 +74,6 @@ extern int lock_cpu_hotplug_interruptible(void); | |||
74 | register_cpu_notifier(&fn##_nb); \ | 74 | register_cpu_notifier(&fn##_nb); \ |
75 | } | 75 | } |
76 | int cpu_down(unsigned int cpu); | 76 | int cpu_down(unsigned int cpu); |
77 | extern int __attribute__((weak)) smp_prepare_cpu(int cpu); | ||
78 | #define cpu_is_offline(cpu) unlikely(!cpu_online(cpu)) | 77 | #define cpu_is_offline(cpu) unlikely(!cpu_online(cpu)) |
79 | #else | 78 | #else |
80 | #define lock_cpu_hotplug() do { } while (0) | 79 | #define lock_cpu_hotplug() do { } while (0) |
diff --git a/kernel/power/smp.c b/kernel/power/smp.c index 911fc62b8225..5957312b2d68 100644 --- a/kernel/power/smp.c +++ b/kernel/power/smp.c | |||
@@ -49,9 +49,7 @@ void enable_nonboot_cpus(void) | |||
49 | 49 | ||
50 | printk("Thawing cpus ...\n"); | 50 | printk("Thawing cpus ...\n"); |
51 | for_each_cpu_mask(cpu, frozen_cpus) { | 51 | for_each_cpu_mask(cpu, frozen_cpus) { |
52 | error = smp_prepare_cpu(cpu); | 52 | error = cpu_up(cpu); |
53 | if (!error) | ||
54 | error = cpu_up(cpu); | ||
55 | if (!error) { | 53 | if (!error) { |
56 | printk("CPU%d is up\n", cpu); | 54 | printk("CPU%d is up\n", cpu); |
57 | continue; | 55 | continue; |