Преглед на файлове

[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>
Ashok Raj преди 19 години
родител
ревизия
34f361ade2
променени са 4 файла, в които са добавени 20 реда и са изтрити 27 реда
  1. 18 15
      arch/i386/kernel/smpboot.c
  2. 1 8
      drivers/base/cpu.c
  3. 0 1
      include/linux/cpu.h
  4. 1 3
      kernel/power/smp.c

+ 18 - 15
arch/i386/kernel/smpboot.c

@@ -1003,7 +1003,6 @@ void cpu_exit_clear(void)
 
 
 	cpu_clear(cpu, cpu_callout_map);
 	cpu_clear(cpu, cpu_callout_map);
 	cpu_clear(cpu, cpu_callin_map);
 	cpu_clear(cpu, cpu_callin_map);
-	cpu_clear(cpu, cpu_present_map);
 
 
 	cpu_clear(cpu, smp_commenced_mask);
 	cpu_clear(cpu, smp_commenced_mask);
 	unmap_cpu_to_logical_apicid(cpu);
 	unmap_cpu_to_logical_apicid(cpu);
@@ -1015,31 +1014,20 @@ struct warm_boot_cpu_info {
 	int cpu;
 	int cpu;
 };
 };
 
 
-static void __devinit do_warm_boot_cpu(void *p)
+static void __cpuinit do_warm_boot_cpu(void *p)
 {
 {
 	struct warm_boot_cpu_info *info = p;
 	struct warm_boot_cpu_info *info = p;
 	do_boot_cpu(info->apicid, info->cpu);
 	do_boot_cpu(info->apicid, info->cpu);
 	complete(info->complete);
 	complete(info->complete);
 }
 }
 
 
-int __devinit smp_prepare_cpu(int cpu)
+static int __cpuinit __smp_prepare_cpu(int cpu)
 {
 {
 	DECLARE_COMPLETION(done);
 	DECLARE_COMPLETION(done);
 	struct warm_boot_cpu_info info;
 	struct warm_boot_cpu_info info;
 	struct work_struct task;
 	struct work_struct task;
 	int	apicid, ret;
 	int	apicid, ret;
 
 
-	lock_cpu_hotplug();
-
-	/*
-	 * On x86, CPU0 is never offlined.  Trying to bring up an
-	 * already-booted CPU will hang.  So check for that case.
-	 */
-	if (cpu_online(cpu)) {
-		ret = -EINVAL;
-		goto exit;
-	}
-
 	apicid = x86_cpu_to_apicid[cpu];
 	apicid = x86_cpu_to_apicid[cpu];
 	if (apicid == BAD_APICID) {
 	if (apicid == BAD_APICID) {
 		ret = -ENODEV;
 		ret = -ENODEV;
@@ -1064,7 +1052,6 @@ int __devinit smp_prepare_cpu(int cpu)
 	zap_low_mappings();
 	zap_low_mappings();
 	ret = 0;
 	ret = 0;
 exit:
 exit:
-	unlock_cpu_hotplug();
 	return ret;
 	return ret;
 }
 }
 #endif
 #endif
@@ -1392,6 +1379,22 @@ void __cpu_die(unsigned int cpu)
 
 
 int __devinit __cpu_up(unsigned int cpu)
 int __devinit __cpu_up(unsigned int cpu)
 {
 {
+#ifdef CONFIG_HOTPLUG_CPU
+	int ret=0;
+
+	/*
+	 * We do warm boot only on cpus that had booted earlier
+	 * Otherwise cold boot is all handled from smp_boot_cpus().
+	 * cpu_callin_map is set during AP kickstart process. Its reset
+	 * when a cpu is taken offline from cpu_exit_clear().
+	 */
+	if (!cpu_isset(cpu, cpu_callin_map))
+		ret = __smp_prepare_cpu(cpu);
+
+	if (ret)
+		return -EIO;
+#endif
+
 	/* In case one didn't come up */
 	/* In case one didn't come up */
 	if (!cpu_isset(cpu, cpu_callin_map)) {
 	if (!cpu_isset(cpu, cpu_callin_map)) {
 		printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu);
 		printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu);

+ 1 - 8
drivers/base/cpu.c

@@ -19,11 +19,6 @@ EXPORT_SYMBOL(cpu_sysdev_class);
 static struct sys_device *cpu_sys_devices[NR_CPUS];
 static struct sys_device *cpu_sys_devices[NR_CPUS];
 
 
 #ifdef CONFIG_HOTPLUG_CPU
 #ifdef CONFIG_HOTPLUG_CPU
-int __attribute__((weak)) smp_prepare_cpu (int cpu)
-{
-	return 0;
-}
-
 static ssize_t show_online(struct sys_device *dev, char *buf)
 static ssize_t show_online(struct sys_device *dev, char *buf)
 {
 {
 	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
 	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,
 			kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
 			kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
 		break;
 		break;
 	case '1':
 	case '1':
-		ret = smp_prepare_cpu(cpu->sysdev.id);
-		if (!ret)
-			ret = cpu_up(cpu->sysdev.id);
+		ret = cpu_up(cpu->sysdev.id);
 		if (!ret)
 		if (!ret)
 			kobject_uevent(&dev->kobj, KOBJ_ONLINE);
 			kobject_uevent(&dev->kobj, KOBJ_ONLINE);
 		break;
 		break;

+ 0 - 1
include/linux/cpu.h

@@ -74,7 +74,6 @@ extern int lock_cpu_hotplug_interruptible(void);
 	register_cpu_notifier(&fn##_nb);			\
 	register_cpu_notifier(&fn##_nb);			\
 }
 }
 int cpu_down(unsigned int cpu);
 int cpu_down(unsigned int cpu);
-extern int __attribute__((weak)) smp_prepare_cpu(int cpu);
 #define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
 #define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
 #else
 #else
 #define lock_cpu_hotplug()	do { } while (0)
 #define lock_cpu_hotplug()	do { } while (0)

+ 1 - 3
kernel/power/smp.c

@@ -49,9 +49,7 @@ void enable_nonboot_cpus(void)
 
 
 	printk("Thawing cpus ...\n");
 	printk("Thawing cpus ...\n");
 	for_each_cpu_mask(cpu, frozen_cpus) {
 	for_each_cpu_mask(cpu, frozen_cpus) {
-		error = smp_prepare_cpu(cpu);
-		if (!error)
-			error = cpu_up(cpu);
+		error = cpu_up(cpu);
 		if (!error) {
 		if (!error) {
 			printk("CPU%d is up\n", cpu);
 			printk("CPU%d is up\n", cpu);
 			continue;
 			continue;