@@ -226,6 +226,24 @@ static int acpi_processor_make_present(struct acpi_processor *pr)
return ret;
}
+static int acpi_processor_make_enabled(struct acpi_processor *pr)
+{
+ int ret;
+
+ if (invalid_phys_cpuid(pr->phys_id))
+ return -ENODEV;
+
+ cpus_write_lock();
+ ret = arch_register_cpu(pr->id);
+ cpus_write_unlock();
+
+ if (ret)
+ return ret;
+
+ pr_info("CPU%d has been hot-added (onlined)\n", pr->id);
+ return 0;
+}
+
static int acpi_processor_get_info(struct acpi_device *device)
{
union acpi_object object = { 0 };
@@ -319,7 +337,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
*/
if (!invalid_logical_cpuid(pr->id) && cpu_present(pr->id) &&
!get_cpu_device(pr->id)) {
- int ret = arch_register_cpu(pr->id);
+ int ret = acpi_processor_make_enabled(pr);
if (ret)
return ret;
@@ -463,6 +481,27 @@ static int acpi_processor_add(struct acpi_device *device,
return result;
}
+static void acpi_processor_make_not_enabled(struct acpi_device *device)
+{
+ struct acpi_processor *pr;
+
+ pr = acpi_driver_data(device);
+ if (pr->id >= nr_cpu_ids)
+ goto out;
+
+ device_release_driver(pr->dev);
+ per_cpu(processor_device_array, pr->id) = NULL;
+ per_cpu(processors, pr->id) = NULL;
+ cpus_write_lock();
+ arch_unregister_cpu(pr->id);
+ cpus_write_unlock();
+
+ try_offline_node(cpu_to_node(pr->id));
+out:
+ free_cpumask_var(pr->throttling.shared_cpu_map);
+ kfree(pr);
+}
+
/* Removal */
static void acpi_processor_make_not_present(struct acpi_device *device)
{
@@ -515,7 +554,7 @@ static void acpi_processor_post_eject(struct acpi_device *device)
unsigned long long sta;
acpi_status status;
- if (!device)
+ if (!IS_ENABLED(CONFIG_HOTPLUG_CPU) || !device)
return;
pr = acpi_driver_data(device);
@@ -530,6 +569,9 @@ static void acpi_processor_post_eject(struct acpi_device *device)
acpi_processor_make_not_present(device);
return;
}
+
+ if (cpu_present(pr->id) && !(sta & ACPI_STA_DEVICE_ENABLED))
+ acpi_processor_make_not_enabled(device);
}
#ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC