diff options
author | James Morse <james.morse@arm.com> | 2021-07-02 16:48:41 +0100 |
---|---|---|
committer | Russell King (Oracle) <rmk+kernel@armlinux.org.uk> | 2023-11-15 10:11:54 +0000 |
commit | 63e9c028c6d81ebed6ae4a119484fe42b37f14a5 (patch) | |
tree | 65f12235de27a60e788f637f98a43aa42be7f0f1 | |
parent | 1b437002fa399efb570e9b0d302fec3ca00bb2a7 (diff) |
ACPI: Check _STA present bit before making CPUs not present
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.morse@arm.com>
---
Changes since RFC v3:
* Move IS_ENABLED(CONFIG_ACPI_HOTPLUG_PRESENT_CPU) into separate patch.
-rw-r--r-- | drivers/acpi/acpi_processor.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 01c460881662..19fceb3ec4e2 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -458,16 +458,13 @@ static int acpi_processor_add(struct acpi_device *device, } /* 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 (!IS_ENABLED(CONFIG_ACPI_HOTPLUG_PRESENT_CPU)) return; - if (!device || !acpi_driver_data(device)) - return; - pr = acpi_driver_data(device); if (pr->id >= nr_cpu_ids) goto out; @@ -504,6 +501,29 @@ static void acpi_processor_post_eject(struct acpi_device *device) kfree(pr); } +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) { |