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
This commit is contained in:
Коммит
9bd0c413b9
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
#include <acpi/pdc_intel.h>
|
#include <acpi/proc_cap_intel.h>
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/numa.h>
|
#include <linux/numa.h>
|
||||||
|
@ -69,9 +69,9 @@ extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline bool arch_has_acpi_pdc(void) { return true; }
|
static inline bool arch_has_acpi_pdc(void) { return true; }
|
||||||
static inline void arch_acpi_set_pdc_bits(u32 *buf)
|
static inline void arch_acpi_set_proc_cap_bits(u32 *cap)
|
||||||
{
|
{
|
||||||
buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP;
|
*cap |= ACPI_PROC_CAP_EST_CAPABILITY_SMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI_NUMA
|
#ifdef CONFIG_ACPI_NUMA
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
|
* Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
|
||||||
* Copyright (C) 2001 Patrick Mochel <mochel@osdl.org>
|
* Copyright (C) 2001 Patrick Mochel <mochel@osdl.org>
|
||||||
*/
|
*/
|
||||||
#include <acpi/pdc_intel.h>
|
#include <acpi/proc_cap_intel.h>
|
||||||
|
|
||||||
#include <asm/numa.h>
|
#include <asm/numa.h>
|
||||||
#include <asm/fixmap.h>
|
#include <asm/fixmap.h>
|
||||||
|
@ -102,23 +102,31 @@ static inline bool arch_has_acpi_pdc(void)
|
||||||
c->x86_vendor == X86_VENDOR_CENTAUR);
|
c->x86_vendor == X86_VENDOR_CENTAUR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void arch_acpi_set_pdc_bits(u32 *buf)
|
static inline void arch_acpi_set_proc_cap_bits(u32 *cap)
|
||||||
{
|
{
|
||||||
struct cpuinfo_x86 *c = &cpu_data(0);
|
struct cpuinfo_x86 *c = &cpu_data(0);
|
||||||
|
|
||||||
buf[2] |= ACPI_PDC_C_CAPABILITY_SMP;
|
*cap |= ACPI_PROC_CAP_C_CAPABILITY_SMP;
|
||||||
|
|
||||||
|
/* Enable coordination with firmware's _TSD info */
|
||||||
|
*cap |= ACPI_PROC_CAP_SMP_T_SWCOORD;
|
||||||
|
|
||||||
if (cpu_has(c, X86_FEATURE_EST))
|
if (cpu_has(c, X86_FEATURE_EST))
|
||||||
buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;
|
*cap |= ACPI_PROC_CAP_EST_CAPABILITY_SWSMP;
|
||||||
|
|
||||||
if (cpu_has(c, X86_FEATURE_ACPI))
|
if (cpu_has(c, X86_FEATURE_ACPI))
|
||||||
buf[2] |= ACPI_PDC_T_FFH;
|
*cap |= ACPI_PROC_CAP_T_FFH;
|
||||||
|
|
||||||
|
if (cpu_has(c, X86_FEATURE_HWP))
|
||||||
|
*cap |= ACPI_PROC_CAP_COLLAB_PROC_PERF;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If mwait/monitor is unsupported, C2/C3_FFH will be disabled
|
* If mwait/monitor is unsupported, C_C1_FFH and
|
||||||
|
* C2/C3_FFH will be disabled.
|
||||||
*/
|
*/
|
||||||
if (!cpu_has(c, X86_FEATURE_MWAIT))
|
if (!cpu_has(c, X86_FEATURE_MWAIT) ||
|
||||||
buf[2] &= ~(ACPI_PDC_C_C2C3_FFH);
|
boot_option_idle_override == IDLE_NOMWAIT)
|
||||||
|
*cap &= ~(ACPI_PROC_CAP_C_C1_FFH | ACPI_PROC_CAP_C_C2C3_FFH);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool acpi_has_cpu_in_madt(void)
|
static inline bool acpi_has_cpu_in_madt(void)
|
||||||
|
|
|
@ -79,7 +79,7 @@
|
||||||
#ifdef CONFIG_ACPI
|
#ifdef CONFIG_ACPI
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <asm/acpi.h>
|
#include <asm/acpi.h>
|
||||||
#include <acpi/pdc_intel.h>
|
#include <acpi/proc_cap_intel.h>
|
||||||
#include <acpi/processor.h>
|
#include <acpi/processor.h>
|
||||||
#include <xen/interface/platform.h>
|
#include <xen/interface/platform.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -288,17 +288,17 @@ static bool __init xen_check_mwait(void)
|
||||||
|
|
||||||
native_cpuid(&ax, &bx, &cx, &dx);
|
native_cpuid(&ax, &bx, &cx, &dx);
|
||||||
|
|
||||||
/* Ask the Hypervisor whether to clear ACPI_PDC_C_C2C3_FFH. If so,
|
/* Ask the Hypervisor whether to clear ACPI_PROC_CAP_C_C2C3_FFH. If so,
|
||||||
* don't expose MWAIT_LEAF and let ACPI pick the IOPORT version of C3.
|
* don't expose MWAIT_LEAF and let ACPI pick the IOPORT version of C3.
|
||||||
*/
|
*/
|
||||||
buf[0] = ACPI_PDC_REVISION_ID;
|
buf[0] = ACPI_PDC_REVISION_ID;
|
||||||
buf[1] = 1;
|
buf[1] = 1;
|
||||||
buf[2] = (ACPI_PDC_C_CAPABILITY_SMP | ACPI_PDC_EST_CAPABILITY_SWSMP);
|
buf[2] = (ACPI_PROC_CAP_C_CAPABILITY_SMP | ACPI_PROC_CAP_EST_CAPABILITY_SWSMP);
|
||||||
|
|
||||||
set_xen_guest_handle(op.u.set_pminfo.pdc, buf);
|
set_xen_guest_handle(op.u.set_pminfo.pdc, buf);
|
||||||
|
|
||||||
if ((HYPERVISOR_platform_op(&op) == 0) &&
|
if ((HYPERVISOR_platform_op(&op) == 0) &&
|
||||||
(buf[2] & (ACPI_PDC_C_C1_FFH | ACPI_PDC_C_C2C3_FFH))) {
|
(buf[2] & (ACPI_PROC_CAP_C_C1_FFH | ACPI_PROC_CAP_C_C2C3_FFH))) {
|
||||||
cpuid_leaf5_ecx_val = cx;
|
cpuid_leaf5_ecx_val = cx;
|
||||||
cpuid_leaf5_edx_val = dx;
|
cpuid_leaf5_edx_val = dx;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,11 @@
|
||||||
* Copyright (C) 2013, Intel Corporation
|
* Copyright (C) 2013, Intel Corporation
|
||||||
* Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
* Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||||
*/
|
*/
|
||||||
|
#define pr_fmt(fmt) "ACPI: " fmt
|
||||||
|
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include <linux/dmi.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
|
@ -21,6 +23,8 @@
|
||||||
|
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
|
|
||||||
|
#include <xen/xen.h>
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
DEFINE_PER_CPU(struct acpi_processor *, processors);
|
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 */
|
#endif /* CONFIG_ACPI_HOTPLUG_CPU */
|
||||||
|
|
||||||
#ifdef CONFIG_X86
|
#ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC
|
||||||
static bool acpi_hwp_native_thermal_lvt_set;
|
bool __init processor_physically_present(acpi_handle handle)
|
||||||
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";
|
int cpuid, type;
|
||||||
u32 capbuf[2];
|
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)
|
||||||
|
{
|
||||||
|
u32 capbuf[2] = {};
|
||||||
struct acpi_osc_context osc_context = {
|
struct acpi_osc_context osc_context = {
|
||||||
.uuid_str = sb_uuid_str,
|
.uuid_str = sb_uuid_str,
|
||||||
.rev = 1,
|
.rev = 1,
|
||||||
.cap.length = 8,
|
.cap.length = 8,
|
||||||
.cap.pointer = capbuf,
|
.cap.pointer = capbuf,
|
||||||
};
|
};
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
if (acpi_hwp_native_thermal_lvt_set)
|
if (!processor_physically_present(handle))
|
||||||
return AE_CTRL_TERMINATE;
|
return AE_OK;
|
||||||
|
|
||||||
capbuf[0] = 0x0000;
|
arch_acpi_set_proc_cap_bits(&capbuf[OSC_SUPPORT_DWORD]);
|
||||||
capbuf[1] = 0x1000; /* set bit 12 */
|
|
||||||
|
|
||||||
if (ACPI_SUCCESS(acpi_run_osc(handle, &osc_context))) {
|
status = acpi_run_osc(handle, &osc_context);
|
||||||
if (osc_context.ret.pointer && osc_context.ret.length > 1) {
|
if (ACPI_FAILURE(status))
|
||||||
u32 *capbuf_ret = osc_context.ret.pointer;
|
return status;
|
||||||
|
|
||||||
if (capbuf_ret[1] & 0x1000) {
|
kfree(osc_context.ret.pointer);
|
||||||
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;
|
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_status status;
|
||||||
acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
|
|
||||||
ACPI_UINT32_MAX,
|
acpi_proc_quirk_mwait_check();
|
||||||
acpi_hwp_native_thermal_lvt_osc,
|
|
||||||
NULL, NULL, NULL);
|
status = acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
|
||||||
acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID,
|
ACPI_UINT32_MAX, acpi_processor_osc, NULL,
|
||||||
acpi_hwp_native_thermal_lvt_osc,
|
NULL, 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
|
#endif
|
||||||
|
|
|
@ -1322,9 +1322,6 @@ static int __init acpi_bus_init(void)
|
||||||
goto error1;
|
goto error1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set capability bits for _OSC under processor scope */
|
|
||||||
acpi_early_processor_osc();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _OSC method may exist in module level code,
|
* _OSC method may exist in module level code,
|
||||||
* so it must be run after ACPI_FULL_INITIALIZATION
|
* so it must be run after ACPI_FULL_INITIALIZATION
|
||||||
|
@ -1340,7 +1337,7 @@ static int __init acpi_bus_init(void)
|
||||||
|
|
||||||
acpi_sysfs_init();
|
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
|
* Maybe EC region is required at bus_scan/acpi_get_devices. So it
|
||||||
|
|
|
@ -152,15 +152,13 @@ int acpi_wakeup_device_init(void);
|
||||||
Processor
|
Processor
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
#ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC
|
#ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC
|
||||||
|
void acpi_early_processor_control_setup(void);
|
||||||
void acpi_early_processor_set_pdc(void);
|
void acpi_early_processor_set_pdc(void);
|
||||||
#else
|
|
||||||
static inline void acpi_early_processor_set_pdc(void) {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86
|
void acpi_proc_quirk_mwait_check(void);
|
||||||
void acpi_early_processor_osc(void);
|
bool processor_physically_present(acpi_handle handle);
|
||||||
#else
|
#else
|
||||||
static inline void acpi_early_processor_osc(void) {}
|
static inline void acpi_early_processor_control_setup(void) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
|
|
|
@ -132,6 +132,30 @@ static int map_rintc_hartid(struct acpi_subtable_header *entry,
|
||||||
return -EINVAL;
|
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,
|
static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt,
|
||||||
int type, u32 acpi_id)
|
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) {
|
} else if (header->type == ACPI_MADT_TYPE_RINTC) {
|
||||||
if (!map_rintc_hartid(header, type, acpi_id, &phys_id))
|
if (!map_rintc_hartid(header, type, acpi_id, &phys_id))
|
||||||
break;
|
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;
|
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);
|
map_x2apic_id(header, type, acpi_id, &phys_id);
|
||||||
else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT)
|
else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT)
|
||||||
map_gicc_mpidr(header, type, acpi_id, &phys_id);
|
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:
|
exit:
|
||||||
kfree(buffer.pointer);
|
kfree(buffer.pointer);
|
||||||
|
|
|
@ -9,71 +9,19 @@
|
||||||
|
|
||||||
#define pr_fmt(fmt) "ACPI: " fmt
|
#define pr_fmt(fmt) "ACPI: " fmt
|
||||||
|
|
||||||
#include <linux/dmi.h>
|
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <acpi/processor.h>
|
#include <acpi/processor.h>
|
||||||
|
|
||||||
#include <xen/xen.h>
|
|
||||||
|
|
||||||
#include "internal.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)
|
static void acpi_set_pdc_bits(u32 *buf)
|
||||||
{
|
{
|
||||||
buf[0] = ACPI_PDC_REVISION_ID;
|
buf[0] = ACPI_PDC_REVISION_ID;
|
||||||
buf[1] = 1;
|
buf[1] = 1;
|
||||||
|
|
||||||
/* Enable coordination with firmware's _TSD info */
|
|
||||||
buf[2] = ACPI_PDC_SMP_T_SWCOORD;
|
|
||||||
|
|
||||||
/* Twiddle arch-specific bits needed for _PDC */
|
/* 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)
|
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;
|
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);
|
status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
|
||||||
|
|
||||||
if (ACPI_FAILURE(status))
|
if (ACPI_FAILURE(status))
|
||||||
|
@ -174,36 +108,9 @@ early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||||
return AE_OK;
|
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)
|
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_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
|
||||||
ACPI_UINT32_MAX,
|
ACPI_UINT32_MAX,
|
||||||
|
|
|
@ -518,3 +518,38 @@ bool acpi_quirk_skip_acpi_ac_and_battery(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(acpi_quirk_skip_acpi_ac_and_battery);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
|
||||||
|
|
||||||
/* _PDC bit definition for Intel processors */
|
|
||||||
|
|
||||||
#ifndef __PDC_INTEL_H__
|
|
||||||
#define __PDC_INTEL_H__
|
|
||||||
|
|
||||||
#define ACPI_PDC_P_FFH (0x0001)
|
|
||||||
#define ACPI_PDC_C_C1_HALT (0x0002)
|
|
||||||
#define ACPI_PDC_T_FFH (0x0004)
|
|
||||||
#define ACPI_PDC_SMP_C1PT (0x0008)
|
|
||||||
#define ACPI_PDC_SMP_C2C3 (0x0010)
|
|
||||||
#define ACPI_PDC_SMP_P_SWCOORD (0x0020)
|
|
||||||
#define ACPI_PDC_SMP_C_SWCOORD (0x0040)
|
|
||||||
#define ACPI_PDC_SMP_T_SWCOORD (0x0080)
|
|
||||||
#define ACPI_PDC_C_C1_FFH (0x0100)
|
|
||||||
#define ACPI_PDC_C_C2C3_FFH (0x0200)
|
|
||||||
#define ACPI_PDC_SMP_P_HWCOORD (0x0800)
|
|
||||||
|
|
||||||
#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \
|
|
||||||
ACPI_PDC_C_C1_HALT | \
|
|
||||||
ACPI_PDC_P_FFH)
|
|
||||||
|
|
||||||
#define ACPI_PDC_EST_CAPABILITY_SWSMP (ACPI_PDC_SMP_C1PT | \
|
|
||||||
ACPI_PDC_C_C1_HALT | \
|
|
||||||
ACPI_PDC_SMP_P_SWCOORD | \
|
|
||||||
ACPI_PDC_SMP_P_HWCOORD | \
|
|
||||||
ACPI_PDC_P_FFH)
|
|
||||||
|
|
||||||
#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \
|
|
||||||
ACPI_PDC_SMP_C1PT | \
|
|
||||||
ACPI_PDC_C_C1_HALT | \
|
|
||||||
ACPI_PDC_C_C1_FFH | \
|
|
||||||
ACPI_PDC_C_C2C3_FFH)
|
|
||||||
|
|
||||||
#endif /* __PDC_INTEL_H__ */
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
|
||||||
|
/* Vendor specific processor capabilities bit definition
|
||||||
|
* for Intel processors. Those bits are used to convey OSPM
|
||||||
|
* power management capabilities to the platform.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PROC_CAP_INTEL_H__
|
||||||
|
#define __PROC_CAP_INTEL_H__
|
||||||
|
|
||||||
|
#define ACPI_PROC_CAP_P_FFH (0x0001)
|
||||||
|
#define ACPI_PROC_CAP_C_C1_HALT (0x0002)
|
||||||
|
#define ACPI_PROC_CAP_T_FFH (0x0004)
|
||||||
|
#define ACPI_PROC_CAP_SMP_C1PT (0x0008)
|
||||||
|
#define ACPI_PROC_CAP_SMP_C2C3 (0x0010)
|
||||||
|
#define ACPI_PROC_CAP_SMP_P_SWCOORD (0x0020)
|
||||||
|
#define ACPI_PROC_CAP_SMP_C_SWCOORD (0x0040)
|
||||||
|
#define ACPI_PROC_CAP_SMP_T_SWCOORD (0x0080)
|
||||||
|
#define ACPI_PROC_CAP_C_C1_FFH (0x0100)
|
||||||
|
#define ACPI_PROC_CAP_C_C2C3_FFH (0x0200)
|
||||||
|
#define ACPI_PROC_CAP_SMP_P_HWCOORD (0x0800)
|
||||||
|
#define ACPI_PROC_CAP_COLLAB_PROC_PERF (0x1000)
|
||||||
|
|
||||||
|
#define ACPI_PROC_CAP_EST_CAPABILITY_SMP (ACPI_PROC_CAP_SMP_C1PT | \
|
||||||
|
ACPI_PROC_CAP_C_C1_HALT | \
|
||||||
|
ACPI_PROC_CAP_P_FFH)
|
||||||
|
|
||||||
|
#define ACPI_PROC_CAP_EST_CAPABILITY_SWSMP (ACPI_PROC_CAP_SMP_C1PT | \
|
||||||
|
ACPI_PROC_CAP_C_C1_HALT | \
|
||||||
|
ACPI_PROC_CAP_SMP_P_SWCOORD | \
|
||||||
|
ACPI_PROC_CAP_SMP_P_HWCOORD | \
|
||||||
|
ACPI_PROC_CAP_P_FFH)
|
||||||
|
|
||||||
|
#define ACPI_PROC_CAP_C_CAPABILITY_SMP (ACPI_PROC_CAP_SMP_C2C3 | \
|
||||||
|
ACPI_PROC_CAP_SMP_C1PT | \
|
||||||
|
ACPI_PROC_CAP_C_C1_HALT | \
|
||||||
|
ACPI_PROC_CAP_C_C1_FFH | \
|
||||||
|
ACPI_PROC_CAP_C_C2C3_FFH)
|
||||||
|
|
||||||
|
#endif /* __PROC_CAP_INTEL_H__ */
|
Загрузка…
Ссылка в новой задаче