From: James Morse <james.mo...@arm.com>

When called acpi_processor_post_eject() 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_post_eject() 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.

After this change CPUs will remain registered and visible to
user-space as offline if buggy firmware triggers an eject-request,
but doesn't clear the corresponding _STA bits after _EJ0 has been
called.

Signed-off-by: James Morse <james.mo...@arm.com>
---
 drivers/acpi/acpi_processor.c | 31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
index b6f5005985c3..19fceb3ec4e2 100644
--- a/drivers/acpi/acpi_processor.c
+++ b/drivers/acpi/acpi_processor.c
@@ -457,13 +457,12 @@ static int acpi_processor_add(struct acpi_device *device,
        return result;
 }
 
-#ifdef CONFIG_ACPI_HOTPLUG_PRESENT_CPU
 /* Removal */
-static void acpi_processor_post_eject(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);
@@ -501,7 +500,29 @@ static void acpi_processor_post_eject(struct acpi_device 
*device)
        free_cpumask_var(pr->throttling.shared_cpu_map);
        kfree(pr);
 }
-#endif /* CONFIG_ACPI_HOTPLUG_PRESENT_CPU */
+
+static void acpi_processor_post_eject(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_ARCH_MIGHT_HAVE_ACPI_PDC
 bool __init processor_physically_present(acpi_handle handle)
@@ -626,9 +647,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
        .post_eject = acpi_processor_post_eject,
-#endif
        .hotplug = {
                .enabled = true,
        },
-- 
2.30.2

Reply via email to