When called acpi_processor_remove() unconditionally make a CPU not-present and unregisters it.
To add support for AML events where the CPU has become disabled, but remains present, the _STA method should be checked before calling acpi_processor_remove().
Rename acpi_processor_remove() acpi_processor_remove_possible(), and check the _STA before calling.
Adding the function prototype for arch_unregister_cpu() allows the preprocessor guards to be removed.
Signed-off-by: James Morse james.morse@arm.com --- drivers/acpi/acpi_processor.c | 31 +++++++++++++++++++++++++------ include/linux/cpu.h | 1 + 2 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 30a03c2cb464..66b695ca7945 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -410,13 +410,12 @@ static int acpi_processor_add(struct acpi_device *device, return result; }
-#ifdef CONFIG_ACPI_HOTPLUG_PRESENT_CPU /* Removal */ -static void acpi_processor_remove(struct acpi_device *device) +static void acpi_processor_make_not_present(struct acpi_device *device) { struct acpi_processor *pr;
- if (!device || !acpi_driver_data(device)) + if (!IS_ENABLED(CONFIG_ACPI_HOTPLUG_PRESENT_CPU)) return;
pr = acpi_driver_data(device); @@ -454,7 +453,29 @@ static void acpi_processor_remove(struct acpi_device *device) free_cpumask_var(pr->throttling.shared_cpu_map); kfree(pr); } -#endif /* CONFIG_ACPI_HOTPLUG_PRESENT_CPU */ + +static void acpi_processor_remove(struct acpi_device *device) +{ + struct acpi_processor *pr; + unsigned long long sta; + acpi_status status; + + if (!device) + return; + + pr = acpi_driver_data(device); + if (!pr || pr->id >= nr_cpu_ids || invalid_phys_cpuid(pr->phys_id)) + return; + + status = acpi_evaluate_integer(pr->handle, "_STA", NULL, &sta); + if (ACPI_FAILURE(status)) + return; + + if (cpu_present(pr->id) && !(sta & ACPI_STA_DEVICE_PRESENT)) { + acpi_processor_make_not_present(device); + return; + } +}
#ifdef CONFIG_X86 static bool acpi_hwp_native_thermal_lvt_set; @@ -523,9 +544,7 @@ static const struct acpi_device_id processor_device_ids[] = { static struct acpi_scan_handler processor_handler = { .ids = processor_device_ids, .attach = acpi_processor_add, -#ifdef CONFIG_ACPI_HOTPLUG_PRESENT_CPU .detach = acpi_processor_remove, -#endif .hotplug = { .enabled = true, }, diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 86e79e702325..f6f198a3972b 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -76,6 +76,7 @@ struct device *cpu_device_create(struct device *parent, void *drvdata, const struct attribute_group **groups, const char *fmt, ...); extern int arch_register_cpu(int cpu); +extern void arch_unregister_cpu(int cpu); #ifdef CONFIG_HOTPLUG_CPU extern void unregister_cpu(struct cpu *cpu); extern ssize_t arch_cpu_probe(const char *, size_t);