diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2023-08-25 20:40:50 +0200 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2023-08-25 20:40:50 +0200 |
commit | 9bd0c413b90c6517b4a2fbedb74f50df3421b50c (patch) | |
tree | 62ca7c12798a192264d159856e81f6041b6409ea /drivers/acpi | |
parent | e921f8c8dfc2b6aad4e7b4209c411768e2604c98 (diff) | |
parent | f6fcf03ce8a9b8c135cf47f4978617bdf2829711 (diff) |
Merge branch 'acpi-processor'
Merge ACPI processor driver changes for 6.6-rc1:
- Support obtaining physical CPU ID from MADT on LoongArch (Bibo Mao).
- Convert ACPI CPU initialization to using _OSC instead of _PDC that
has been depreceted since 2018 and dropped from the specification in
ACPI 6.5 (Michal Wilczynski, Rafael Wysocki).
* acpi-processor:
ACPI: processor: LoongArch: Get physical ID from MADT
ACPI: processor: Refine messages in acpi_early_processor_control_setup()
ACPI: processor: Remove acpi_hwp_native_thermal_lvt_osc()
ACPI: processor: Use _OSC to convey OSPM processor support information
ACPI: processor: Introduce acpi_processor_osc()
ACPI: processor: Set CAP_SMP_T_SWCOORD in arch_acpi_set_proc_cap_bits()
ACPI: processor: Clear C_C2C3_FFH and C_C1_FFH in arch_acpi_set_proc_cap_bits()
ACPI: processor: Rename ACPI_PDC symbols
ACPI: processor: Refactor arch_acpi_set_pdc_bits()
ACPI: processor: Move processor_physically_present() to acpi_processor.c
ACPI: processor: Move MWAIT quirk out of acpi_processor.c
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/acpi_processor.c | 124 | ||||
-rw-r--r-- | drivers/acpi/bus.c | 5 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 10 | ||||
-rw-r--r-- | drivers/acpi/processor_core.c | 29 | ||||
-rw-r--r-- | drivers/acpi/processor_pdc.c | 97 | ||||
-rw-r--r-- | drivers/acpi/x86/utils.c | 35 |
6 files changed, 163 insertions, 137 deletions
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index f9aa02cac6d1..c711db8a9c33 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -9,9 +9,11 @@ * Copyright (C) 2013, Intel Corporation * Rafael J. Wysocki <rafael.j.wysocki@intel.com> */ +#define pr_fmt(fmt) "ACPI: " fmt #include <linux/acpi.h> #include <linux/device.h> +#include <linux/dmi.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> @@ -21,6 +23,8 @@ #include <asm/cpu.h> +#include <xen/xen.h> + #include "internal.h" DEFINE_PER_CPU(struct acpi_processor *, processors); @@ -508,54 +512,110 @@ static void acpi_processor_remove(struct acpi_device *device) } #endif /* CONFIG_ACPI_HOTPLUG_CPU */ -#ifdef CONFIG_X86 -static bool acpi_hwp_native_thermal_lvt_set; -static acpi_status __init acpi_hwp_native_thermal_lvt_osc(acpi_handle handle, - u32 lvl, - void *context, - void **rv) +#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); +} + +/* vendor specific UUID indicating an Intel platform */ +static u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953"; + +static acpi_status __init acpi_processor_osc(acpi_handle handle, u32 lvl, + void *context, void **rv) { - u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953"; - u32 capbuf[2]; + 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 (acpi_hwp_native_thermal_lvt_set) - return AE_CTRL_TERMINATE; + if (!processor_physically_present(handle)) + return AE_OK; - capbuf[0] = 0x0000; - capbuf[1] = 0x1000; /* set bit 12 */ + arch_acpi_set_proc_cap_bits(&capbuf[OSC_SUPPORT_DWORD]); - 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; + status = acpi_run_osc(handle, &osc_context); + if (ACPI_FAILURE(status)) + return status; - 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); - } + kfree(osc_context.ret.pointer); 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 for all CPUs\n"); + } else { + pr_info("_OSC evaluation for CPUs failed, trying _PDC\n"); + acpi_early_processor_set_pdc(); } } #endif diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 0168b3a556b6..f41dda2d3493 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1322,9 +1322,6 @@ static int __init acpi_bus_init(void) goto error1; } - /* Set capability bits for _OSC under processor scope */ - acpi_early_processor_osc(); - /* * _OSC method may exist in module level code, * so it must be run after ACPI_FULL_INITIALIZATION @@ -1340,7 +1337,7 @@ static int __init acpi_bus_init(void) acpi_sysfs_init(); - acpi_early_processor_set_pdc(); + acpi_early_processor_control_setup(); /* * Maybe EC region is required at bus_scan/acpi_get_devices. So it diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index f4148dc50b9c..ced8224d7472 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -152,15 +152,13 @@ int acpi_wakeup_device_init(void); Processor -------------------------------------------------------------------------- */ #ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC +void acpi_early_processor_control_setup(void); void acpi_early_processor_set_pdc(void); -#else -static inline void acpi_early_processor_set_pdc(void) {} -#endif -#ifdef CONFIG_X86 -void acpi_early_processor_osc(void); +void acpi_proc_quirk_mwait_check(void); +bool processor_physically_present(acpi_handle handle); #else -static inline void acpi_early_processor_osc(void) {} +static inline void acpi_early_processor_control_setup(void) {} #endif /* -------------------------------------------------------------------------- diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index d6606a9f2da6..7dd6dbaa98c3 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -132,6 +132,30 @@ static int map_rintc_hartid(struct acpi_subtable_header *entry, return -EINVAL; } +/* + * Retrieve LoongArch CPU physical id + */ +static int map_core_pic_id(struct acpi_subtable_header *entry, + int device_declaration, u32 acpi_id, phys_cpuid_t *phys_id) +{ + struct acpi_madt_core_pic *core_pic = + container_of(entry, struct acpi_madt_core_pic, header); + + if (!(core_pic->flags & ACPI_MADT_ENABLED)) + return -ENODEV; + + /* device_declaration means Device object in DSDT, in LoongArch + * system, logical processor acpi_id is required in _UID property + * of DSDT table, so we should check device_declaration here + */ + if (device_declaration && (core_pic->processor_id == acpi_id)) { + *phys_id = core_pic->core_id; + return 0; + } + + return -EINVAL; +} + static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt, int type, u32 acpi_id) { @@ -165,6 +189,9 @@ static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt, } else if (header->type == ACPI_MADT_TYPE_RINTC) { if (!map_rintc_hartid(header, type, acpi_id, &phys_id)) break; + } else if (header->type == ACPI_MADT_TYPE_CORE_PIC) { + if (!map_core_pic_id(header, type, acpi_id, &phys_id)) + break; } entry += header->length; } @@ -216,6 +243,8 @@ static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id) map_x2apic_id(header, type, acpi_id, &phys_id); else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) map_gicc_mpidr(header, type, acpi_id, &phys_id); + else if (header->type == ACPI_MADT_TYPE_CORE_PIC) + map_core_pic_id(header, type, acpi_id, &phys_id); exit: kfree(buffer.pointer); diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 18fb04523f93..1a8591e9a9bf 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -9,71 +9,19 @@ #define pr_fmt(fmt) "ACPI: " fmt -#include <linux/dmi.h> #include <linux/slab.h> #include <linux/acpi.h> #include <acpi/processor.h> -#include <xen/xen.h> - #include "internal.h" -static 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 = { 0 }; - 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, "_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 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 void acpi_set_pdc_bits(u32 *buf) { buf[0] = ACPI_PDC_REVISION_ID; buf[1] = 1; - /* Enable coordination with firmware's _TSD info */ - buf[2] = ACPI_PDC_SMP_T_SWCOORD; - /* Twiddle arch-specific bits needed for _PDC */ - arch_acpi_set_pdc_bits(buf); + arch_acpi_set_proc_cap_bits(&buf[2]); } static struct acpi_object_list *acpi_processor_alloc_pdc(void) @@ -123,20 +71,6 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) { acpi_status status = AE_OK; - if (boot_option_idle_override == IDLE_NOMWAIT) { - /* - * If mwait is disabled for CPU C-states, the C2C3_FFH access - * mode will be disabled in the parameter of _PDC object. - * Of course C1_FFH access mode will also be disabled. - */ - union acpi_object *obj; - u32 *buffer = NULL; - - obj = pdc_in->pointer; - buffer = (u32 *)(obj->buffer.pointer); - buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); - - } status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL); if (ACPI_FAILURE(status)) @@ -174,36 +108,9 @@ early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } -static int __init set_no_mwait(const struct dmi_system_id *id) -{ - pr_notice("%s detected - disabling mwait for CPU C-states\n", - id->ident); - boot_option_idle_override = IDLE_NOMWAIT; - return 0; -} - -static const struct dmi_system_id processor_idle_dmi_table[] __initconst = { - { - set_no_mwait, "Extensa 5220", { - DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), - DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, - {}, -}; - -static void __init processor_dmi_check(void) -{ - /* - * Check whether the system is DMI table. If yes, OSPM - * should not use mwait for CPU-states. - */ - dmi_check_system(processor_idle_dmi_table); -} - void __init acpi_early_processor_set_pdc(void) { - processor_dmi_check(); + acpi_proc_quirk_mwait_check(); acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index c2b925f8cd4e..63d834dd3811 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -518,3 +518,38 @@ bool acpi_quirk_skip_acpi_ac_and_battery(void) return false; } EXPORT_SYMBOL_GPL(acpi_quirk_skip_acpi_ac_and_battery); + +/* This section provides a workaround for a specific x86 system + * which requires disabling of mwait to work correctly. + */ +static int __init acpi_proc_quirk_set_no_mwait(const struct dmi_system_id *id) +{ + pr_notice("%s detected - disabling mwait for CPU C-states\n", + id->ident); + boot_option_idle_override = IDLE_NOMWAIT; + return 0; +} + +static const struct dmi_system_id acpi_proc_quirk_mwait_dmi_table[] __initconst = { + { + .callback = acpi_proc_quirk_set_no_mwait, + .ident = "Extensa 5220", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), + DMI_MATCH(DMI_BOARD_NAME, "Columbia"), + }, + .driver_data = NULL, + }, + {} +}; + +void __init acpi_proc_quirk_mwait_check(void) +{ + /* + * Check whether the system is DMI table. If yes, OSPM + * should not use mwait for CPU-states. + */ + dmi_check_system(acpi_proc_quirk_mwait_dmi_table); +} |