ACPI processor hotplug: Split up acpi_processor_add
Thomas Renninger [Thu, 19 Jan 2012 17:18:42 +0000 (18:18 +0100)]
No functional change.

This is needed because:
When a CPU gets hotplugged, it's totally uninitialized
and offline. cpuinfo_x86 struct (cpu_data(cpu)) is mostly
zero (CPU feature flags, model, family,..).

When a CPU gets hotplugged, struct processor is alloc'd,
some sysfs files are set up but acpi_processor_add()
must not try to access a MSR on this CPU or try to read
out CPU feature,family, etc.

This must be done in acpi_processor_start().
The next patch will delay the call of acpi_processor_start()
for physically hotpluggedcores, to the time when they are onlined
the first time. There it is safe then to access cpu_data(cpu)
cpuinfo_x86 struct or access MSRs which is needed to
set up cpuidle, throttling and other features.

Tested and
Signed-off-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Len Brown <len.brown@intel.com>

drivers/acpi/processor_driver.c

index 0034ede..bec5593 100644 (file)
@@ -440,6 +440,58 @@ static struct notifier_block acpi_cpu_notifier =
            .notifier_call = acpi_cpu_soft_notify,
 };
 
+static int __cpuinit acpi_processor_start(struct acpi_processor *pr)
+{
+       struct acpi_device *device = per_cpu(processor_device_array, pr->id);
+       int result = 0;
+
+#ifdef CONFIG_CPU_FREQ
+       acpi_processor_ppc_has_changed(pr, 0);
+#endif
+       acpi_processor_get_throttling_info(pr);
+       acpi_processor_get_limit_info(pr);
+
+       if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
+               acpi_processor_power_init(pr, device);
+
+       pr->cdev = thermal_cooling_device_register("Processor", device,
+                                                  &processor_cooling_ops);
+       if (IS_ERR(pr->cdev)) {
+               result = PTR_ERR(pr->cdev);
+               goto err_power_exit;
+       }
+
+       dev_dbg(&device->dev, "registered as cooling_device%d\n",
+               pr->cdev->id);
+
+       result = sysfs_create_link(&device->dev.kobj,
+                                  &pr->cdev->device.kobj,
+                                  "thermal_cooling");
+       if (result) {
+               printk(KERN_ERR PREFIX "Create sysfs link\n");
+               goto err_thermal_unregister;
+       }
+       result = sysfs_create_link(&pr->cdev->device.kobj,
+                                  &device->dev.kobj,
+                                  "device");
+       if (result) {
+               printk(KERN_ERR PREFIX "Create sysfs link\n");
+               goto err_remove_sysfs_thermal;
+       }
+
+       return 0;
+
+err_remove_sysfs_thermal:
+       sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
+err_thermal_unregister:
+       thermal_cooling_device_unregister(pr->cdev);
+err_power_exit:
+       acpi_processor_power_exit(pr, device);
+
+       return result;
+}
+
+
 static int __cpuinit acpi_processor_add(struct acpi_device *device)
 {
        struct acpi_processor *pr = NULL;
@@ -494,49 +546,13 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
                result = -EFAULT;
                goto err_free_cpumask;
        }
-
-#ifdef CONFIG_CPU_FREQ
-       acpi_processor_ppc_has_changed(pr, 0);
-#endif
-       acpi_processor_get_throttling_info(pr);
-       acpi_processor_get_limit_info(pr);
-
-       if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
-               acpi_processor_power_init(pr, device);
-
-       pr->cdev = thermal_cooling_device_register("Processor", device,
-                                               &processor_cooling_ops);
-       if (IS_ERR(pr->cdev)) {
-               result = PTR_ERR(pr->cdev);
-               goto err_power_exit;
-       }
-
-       dev_dbg(&device->dev, "registered as cooling_device%d\n",
-                pr->cdev->id);
-
-       result = sysfs_create_link(&device->dev.kobj,
-                                  &pr->cdev->device.kobj,
-                                  "thermal_cooling");
-       if (result) {
-               printk(KERN_ERR PREFIX "Create sysfs link\n");
-               goto err_thermal_unregister;
-       }
-       result = sysfs_create_link(&pr->cdev->device.kobj,
-                                  &device->dev.kobj,
-                                  "device");
-       if (result) {
-               printk(KERN_ERR PREFIX "Create sysfs link\n");
+       result = acpi_processor_start(pr);
+       if (result)
                goto err_remove_sysfs;
-       }
 
        return 0;
 
 err_remove_sysfs:
-       sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
-err_thermal_unregister:
-       thermal_cooling_device_unregister(pr->cdev);
-err_power_exit:
-       acpi_processor_power_exit(pr, device);
        sysfs_remove_link(&device->dev.kobj, "sysdev");
 err_free_cpumask:
        free_cpumask_var(pr->throttling.shared_cpu_map);