From 3272a4aadc4c91f1f9518cf6638e7e81f9ac0336 Mon Sep 17 00:00:00 2001 From: Michal Wilczynski Date: Mon, 10 Jul 2023 17:03:30 +0300 Subject: ACPI: processor: Move processor_physically_present() to acpi_processor.c Since _PDC method is deprecated and a preferred method of communicating OSPM processor power management capabilities is _OSC, there is a need to move function checking whether processor is present as this logic is not _PDC specific. Move processor_physically_present() to acpi_processor.c. No intentional functional impact. Suggested-by: Rafael J. Wysocki Signed-off-by: Michal Wilczynski [ rjw: Subject and changelog edits ] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_processor.c | 52 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) (limited to 'drivers/acpi/acpi_processor.c') diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index f9aa02cac6d1..ebb4efd3d0aa 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -21,6 +22,8 @@ #include +#include + #include "internal.h" DEFINE_PER_CPU(struct acpi_processor *, processors); @@ -508,7 +511,54 @@ static void acpi_processor_remove(struct acpi_device *device) } #endif /* CONFIG_ACPI_HOTPLUG_CPU */ -#ifdef CONFIG_X86 +#ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC +bool __init processor_physically_present(acpi_handle handle) +{ + int cpuid, type; + u32 acpi_id; + acpi_status status; + acpi_object_type acpi_type; + unsigned long long tmp; + union acpi_object object = {}; + struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; + + status = acpi_get_type(handle, &acpi_type); + if (ACPI_FAILURE(status)) + return false; + + switch (acpi_type) { + case ACPI_TYPE_PROCESSOR: + status = acpi_evaluate_object(handle, NULL, NULL, &buffer); + if (ACPI_FAILURE(status)) + return false; + acpi_id = object.processor.proc_id; + break; + case ACPI_TYPE_DEVICE: + status = acpi_evaluate_integer(handle, METHOD_NAME__UID, + NULL, &tmp); + if (ACPI_FAILURE(status)) + return false; + acpi_id = tmp; + break; + default: + return false; + } + + if (xen_initial_domain()) + /* + * When running as a Xen dom0 the number of processors Linux + * sees can be different from the real number of processors on + * the system, and we still need to execute _PDC or _OSC for + * all of them. + */ + return xen_processor_present(acpi_id); + + type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0; + cpuid = acpi_get_cpuid(handle, type, acpi_id); + + return !invalid_logical_cpuid(cpuid); +} + static bool acpi_hwp_native_thermal_lvt_set; static acpi_status __init acpi_hwp_native_thermal_lvt_osc(acpi_handle handle, u32 lvl, -- cgit v1.2.3 From 5ba30be7fd6e3fdff1e0b01f24173a5e6a3183b2 Mon Sep 17 00:00:00 2001 From: Michal Wilczynski Date: Mon, 10 Jul 2023 17:03:35 +0300 Subject: ACPI: processor: Introduce acpi_processor_osc() The processor _OSC method is already used for a workaround introduced in commit a21211672c9a ("ACPI / processor: Request native thermal interrupt handling via _OSC"), but in accordance with ACPI 6.5 (and earlier), it should be used for negotiating all of the processor capabilities instead of _PDC (which has been deprecated since ACPI 3.0 and got removed from ACPI 6.5 entirely). Create a new callback function called acpi_processor_osc() to be invoked for every processor object and processor device in the ACPI namespace, in analogy with the already existing acpi_hwp_native_thermal_lvt_osc(). Make this function implement the workaround mentioned above and convey all of the OSPM processor support information to the platform firmware by setting all of the appropriate processor capabilities bits before evaluating _OSC for the given processor. For this purpose, make it call arch_acpi_set_proc_cap_bits() and modify the latter to set ACPI_PROC_CAP_COLLAB_PROC_PERF along with the other processor capabilities bits. Suggested-by: Rafael J. Wysocki Signed-off-by: Michal Wilczynski Reviewed-by: Andy Shevchenko [ rjw: Subject and changelog edits, whitespace fixup ] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_processor.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'drivers/acpi/acpi_processor.c') diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index ebb4efd3d0aa..163bd3d52acd 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -559,13 +559,41 @@ bool __init processor_physically_present(acpi_handle handle) return !invalid_logical_cpuid(cpuid); } +/* vendor specific UUID indicating an Intel platform */ +static u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953"; static bool acpi_hwp_native_thermal_lvt_set; + +static acpi_status __init acpi_processor_osc(acpi_handle handle, u32 lvl, + void *context, void **rv) +{ + u32 capbuf[2] = {}; + struct acpi_osc_context osc_context = { + .uuid_str = sb_uuid_str, + .rev = 1, + .cap.length = 8, + .cap.pointer = capbuf, + }; + acpi_status status; + + if (!processor_physically_present(handle)) + return AE_OK; + + arch_acpi_set_proc_cap_bits(&capbuf[OSC_SUPPORT_DWORD]); + + status = acpi_run_osc(handle, &osc_context); + if (ACPI_FAILURE(status)) + return status; + + kfree(osc_context.ret.pointer); + + return AE_OK; +} + static acpi_status __init acpi_hwp_native_thermal_lvt_osc(acpi_handle handle, u32 lvl, void *context, void **rv) { - u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953"; u32 capbuf[2]; struct acpi_osc_context osc_context = { .uuid_str = sb_uuid_str, -- cgit v1.2.3 From 95272641338a32734792fe4b261001847b11ed80 Mon Sep 17 00:00:00 2001 From: Michal Wilczynski Date: Mon, 10 Jul 2023 17:03:36 +0300 Subject: ACPI: processor: Use _OSC to convey OSPM processor support information Change acpi_early_processor_osc() to return a value in case of a failure and make it static. Also make it run acpi_processor_osc() for every processor object or processor device found in the ACPI Namespace (previously, its only purpose was to work around platform firmware defects on Skylake systems). Introduce a new function called acpi_early_processor_control_setup() that will invoke acpi_early_processor_osc() first in order to convey the OS processor support information to the platform firmware and if that fails, it will fall back to using _PDC. Suggested-by: Rafael J. Wysocki Signed-off-by: Michal Wilczynski Reviewed-by: Andy Shevchenko [ rjw: Subject and changelog edits, change function return value to bool, add missing 'static', change messages ] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_processor.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) (limited to 'drivers/acpi/acpi_processor.c') diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 163bd3d52acd..8f4d70ae694f 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -624,16 +624,33 @@ static acpi_status __init acpi_hwp_native_thermal_lvt_osc(acpi_handle handle, return AE_OK; } -void __init acpi_early_processor_osc(void) +static bool __init acpi_early_processor_osc(void) { - if (boot_cpu_has(X86_FEATURE_HWP)) { - acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - acpi_hwp_native_thermal_lvt_osc, - NULL, NULL, NULL); - acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, - acpi_hwp_native_thermal_lvt_osc, - NULL, NULL); + acpi_status status; + + acpi_proc_quirk_mwait_check(); + + status = acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, acpi_processor_osc, NULL, + NULL, NULL); + if (ACPI_FAILURE(status)) + return false; + + status = acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, acpi_processor_osc, + NULL, NULL); + if (ACPI_FAILURE(status)) + return false; + + return true; +} + +void __init acpi_early_processor_control_setup(void) +{ + if (acpi_early_processor_osc()) { + pr_info("_OSC evaluated successfully\n"); + } else { + pr_info("_OSC evaluation failed, trying _PDC\n"); + acpi_early_processor_set_pdc(); } } #endif -- cgit v1.2.3 From 11e7bf5629fa6a78b72a2b755c0a8f0bbd512593 Mon Sep 17 00:00:00 2001 From: Michal Wilczynski Date: Mon, 10 Jul 2023 17:03:37 +0300 Subject: ACPI: processor: Remove acpi_hwp_native_thermal_lvt_osc() The workaround for buggy skylake BIOSes is now implemented in acpi_processor_osc() and acpi_hwp_native_thermal_lvt_osc() has no callers, so drop it. Suggested-by: Rafael J. Wysocki Signed-off-by: Michal Wilczynski Reviewed-by: Andy Shevchenko [ rjw: Subject and changelog edits ] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_processor.c | 36 ------------------------------------ 1 file changed, 36 deletions(-) (limited to 'drivers/acpi/acpi_processor.c') diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 8f4d70ae694f..9e35b8d8d334 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -561,7 +561,6 @@ bool __init processor_physically_present(acpi_handle handle) /* vendor specific UUID indicating an Intel platform */ static u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953"; -static bool acpi_hwp_native_thermal_lvt_set; static acpi_status __init acpi_processor_osc(acpi_handle handle, u32 lvl, void *context, void **rv) @@ -589,41 +588,6 @@ static acpi_status __init acpi_processor_osc(acpi_handle handle, u32 lvl, return AE_OK; } -static acpi_status __init acpi_hwp_native_thermal_lvt_osc(acpi_handle handle, - u32 lvl, - void *context, - void **rv) -{ - u32 capbuf[2]; - struct acpi_osc_context osc_context = { - .uuid_str = sb_uuid_str, - .rev = 1, - .cap.length = 8, - .cap.pointer = capbuf, - }; - - if (acpi_hwp_native_thermal_lvt_set) - return AE_CTRL_TERMINATE; - - capbuf[0] = 0x0000; - capbuf[1] = 0x1000; /* set bit 12 */ - - if (ACPI_SUCCESS(acpi_run_osc(handle, &osc_context))) { - if (osc_context.ret.pointer && osc_context.ret.length > 1) { - u32 *capbuf_ret = osc_context.ret.pointer; - - if (capbuf_ret[1] & 0x1000) { - acpi_handle_info(handle, - "_OSC native thermal LVT Acked\n"); - acpi_hwp_native_thermal_lvt_set = true; - } - } - kfree(osc_context.ret.pointer); - } - - return AE_OK; -} - static bool __init acpi_early_processor_osc(void) { acpi_status status; -- cgit v1.2.3 From 003e0694fcd3d51ee2d55dafb2def501f9965cbd Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 19 Jul 2023 18:02:44 +0200 Subject: ACPI: processor: Refine messages in acpi_early_processor_control_setup() The source and meaning of the messages printed by acpi_early_processor_control_setup() is unclear, so add a pr_fmt() definition to acpi_processor.c and expand the messages to make it clear that they are about CPUs. Signed-off-by: Rafael J. Wysocki Reviewed-by: Michal Wilczynski --- drivers/acpi/acpi_processor.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/acpi/acpi_processor.c') diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 9e35b8d8d334..c711db8a9c33 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -9,6 +9,7 @@ * Copyright (C) 2013, Intel Corporation * Rafael J. Wysocki */ +#define pr_fmt(fmt) "ACPI: " fmt #include #include @@ -611,9 +612,9 @@ static bool __init acpi_early_processor_osc(void) void __init acpi_early_processor_control_setup(void) { if (acpi_early_processor_osc()) { - pr_info("_OSC evaluated successfully\n"); + pr_info("_OSC evaluated successfully for all CPUs\n"); } else { - pr_info("_OSC evaluation failed, trying _PDC\n"); + pr_info("_OSC evaluation for CPUs failed, trying _PDC\n"); acpi_early_processor_set_pdc(); } } -- cgit v1.2.3