Skip to content

Commit

Permalink
Merge branch 'acpi-processor'
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Rafael J. Wysocki committed Aug 25, 2023
2 parents e921f8c + f6fcf03 commit 9bd0c41
Show file tree
Hide file tree
Showing 11 changed files with 226 additions and 188 deletions.
6 changes: 3 additions & 3 deletions arch/ia64/include/asm/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

#ifdef __KERNEL__

#include <acpi/pdc_intel.h>
#include <acpi/proc_cap_intel.h>

#include <linux/init.h>
#include <linux/numa.h>
Expand Down Expand Up @@ -69,9 +69,9 @@ extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
#endif

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
Expand Down
24 changes: 16 additions & 8 deletions arch/x86/include/asm/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
* 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/fixmap.h>
Expand Down Expand Up @@ -102,23 +102,31 @@ static inline bool arch_has_acpi_pdc(void)
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);

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))
buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;
*cap |= ACPI_PROC_CAP_EST_CAPABILITY_SWSMP;

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))
buf[2] &= ~(ACPI_PDC_C_C2C3_FFH);
if (!cpu_has(c, X86_FEATURE_MWAIT) ||
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)
Expand Down
8 changes: 4 additions & 4 deletions arch/x86/xen/enlighten_pv.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
#ifdef CONFIG_ACPI
#include <linux/acpi.h>
#include <asm/acpi.h>
#include <acpi/pdc_intel.h>
#include <acpi/proc_cap_intel.h>
#include <acpi/processor.h>
#include <xen/interface/platform.h>
#endif
Expand Down Expand Up @@ -288,17 +288,17 @@ static bool __init xen_check_mwait(void)

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.
*/
buf[0] = ACPI_PDC_REVISION_ID;
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);

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_edx_val = dx;
}
Expand Down
124 changes: 92 additions & 32 deletions drivers/acpi/acpi_processor.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -21,6 +23,8 @@

#include <asm/cpu.h>

#include <xen/xen.h>

#include "internal.h"

DEFINE_PER_CPU(struct acpi_processor *, processors);
Expand Down Expand Up @@ -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
Expand Down
5 changes: 1 addition & 4 deletions drivers/acpi/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
10 changes: 4 additions & 6 deletions drivers/acpi/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

/* --------------------------------------------------------------------------
Expand Down
29 changes: 29 additions & 0 deletions drivers/acpi/processor_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 9bd0c41

Please sign in to comment.