* [PATCH v1 1/2] acpi: Use _OSC method to convey processor OSPM capabilites
2023-05-12 15:25 [PATCH v1 0/2] Prefer using _OSC method over deprecated _PDC Michal Wilczynski
@ 2023-05-12 15:25 ` Michal Wilczynski
2023-05-12 15:25 ` [PATCH v1 2/2] acpi: Move logic responsible for conveying processor OSPM capabilities Michal Wilczynski
1 sibling, 0 replies; 5+ messages in thread
From: Michal Wilczynski @ 2023-05-12 15:25 UTC (permalink / raw)
To: linux-acpi; +Cc: rafael, srinivas.pandruvada, hanjun.guo, Michal Wilczynski
ACPI 3.0 introduced a new Operating System Capabilities _OSC control
method. This method is similar to _PDC, which was marked as deprecated
in ACPI 3.0.
Prefer using _OSC method over deprecated _PDC in the acpi_bus_init(). In
case of the failure of the _OSC, try using _PDC as a fallback.
Refactor workaround for HWP introduced in a21211672c9a ("ACPI / processor:
Request native thermal interrupt handling via _OSC"). This workaround
was already using _OSC to work around buggy BIOS in Skylake systems.
Change acpi_hwp_native_thermal_lvt_osc() to acpi_processor_osc() and
make it more generic.
Change arch_acpi_set_pdc_bits() to arch_acpi_set_proc_cap_bits() as the
capabilities bitfield is not _PDC specific.
Introduce new define ACPI_PDC_COLLAB_PROC_PERF instead of using
hard-coded value.
Signed-off-by: Michal Wilczynski <michal.wilczynski@intel.com>
---
arch/ia64/include/asm/acpi.h | 4 +--
arch/x86/include/asm/acpi.h | 12 +++++----
drivers/acpi/acpi_processor.c | 49 +++++++++++++++++++----------------
drivers/acpi/bus.c | 11 +++++---
drivers/acpi/internal.h | 4 +--
drivers/acpi/processor_pdc.c | 2 +-
include/acpi/pdc_intel.h | 1 +
7 files changed, 46 insertions(+), 37 deletions(-)
diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h
index 87927eb824cc..43797cb44383 100644
--- a/arch/ia64/include/asm/acpi.h
+++ b/arch/ia64/include/asm/acpi.h
@@ -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_PDC_EST_CAPABILITY_SMP;
}
#ifdef CONFIG_ACPI_NUMA
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index 8eb74cf386db..a73d1acfa551 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -100,23 +100,25 @@ 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_PDC_C_CAPABILITY_SMP;
if (cpu_has(c, X86_FEATURE_EST))
- buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;
+ *cap |= ACPI_PDC_EST_CAPABILITY_SWSMP;
if (cpu_has(c, X86_FEATURE_ACPI))
- buf[2] |= ACPI_PDC_T_FFH;
+ *cap |= ACPI_PDC_T_FFH;
+ if (cpu_has(c, X86_FEATURE_HWP))
+ *cap |= ACPI_PDC_COLLAB_PROC_PERF;
/*
* If mwait/monitor is unsupported, C2/C3_FFH will be disabled
*/
if (!cpu_has(c, X86_FEATURE_MWAIT))
- buf[2] &= ~(ACPI_PDC_C_C2C3_FFH);
+ *cap &= ~(ACPI_PDC_C_C2C3_FFH);
}
static inline bool acpi_has_cpu_in_madt(void)
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
index f9aa02cac6d1..26f6c002016b 100644
--- a/drivers/acpi/acpi_processor.c
+++ b/drivers/acpi/acpi_processor.c
@@ -510,13 +510,12 @@ static void acpi_processor_remove(struct acpi_device *device)
#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)
+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] = { 0 };
+ acpi_status status;
struct acpi_osc_context osc_context = {
.uuid_str = sb_uuid_str,
.rev = 1,
@@ -524,39 +523,43 @@ static acpi_status __init acpi_hwp_native_thermal_lvt_osc(acpi_handle handle,
.cap.pointer = capbuf,
};
- if (acpi_hwp_native_thermal_lvt_set)
- return AE_CTRL_TERMINATE;
+ arch_acpi_set_proc_cap_bits(&capbuf[OSC_SUPPORT_DWORD]);
- capbuf[0] = 0x0000;
- capbuf[1] = 0x1000; /* set bit 12 */
+ if (boot_option_idle_override == IDLE_NOMWAIT)
+ capbuf[OSC_SUPPORT_DWORD] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
- if (ACPI_SUCCESS(acpi_run_osc(handle, &osc_context))) {
+ status = acpi_run_osc(handle, &osc_context);
+ if (ACPI_SUCCESS(status)) {
if (osc_context.ret.pointer && osc_context.ret.length > 1) {
u32 *capbuf_ret = osc_context.ret.pointer;
- if (capbuf_ret[1] & 0x1000) {
+ if (!acpi_hwp_native_thermal_lvt_set &&
+ capbuf_ret[1] & 0x1000) {
acpi_handle_info(handle,
- "_OSC native thermal LVT Acked\n");
+ "_OSC native thermal LVT Acked\n");
acpi_hwp_native_thermal_lvt_set = true;
}
}
kfree(osc_context.ret.pointer);
}
- return AE_OK;
+ return status;
}
-void __init acpi_early_processor_osc(void)
+acpi_status __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;
+
+ status = acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, acpi_processor_osc, NULL,
+ NULL, NULL);
+ if (ACPI_FAILURE(status))
+ return status;
+
+ status = acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, acpi_processor_osc,
+ NULL, NULL);
+
+ return status;
}
#endif
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index d161ff707de4..785eb95ec2b3 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -1317,9 +1317,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
@@ -1335,7 +1332,13 @@ static int __init acpi_bus_init(void)
acpi_sysfs_init();
- acpi_early_processor_set_pdc();
+ status = acpi_early_processor_osc();
+ if (ACPI_FAILURE(status)) {
+ pr_err("_OSC processor control methods failed, trying _PDC\n");
+ acpi_early_processor_set_pdc();
+ } else {
+ pr_err("_OSC methods ran succesfully\n");
+ }
/*
* 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 06ad497067ac..58e892376391 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -156,9 +156,9 @@ static inline void acpi_early_processor_set_pdc(void) {}
#endif
#ifdef CONFIG_X86
-void acpi_early_processor_osc(void);
+acpi_status acpi_early_processor_osc(void);
#else
-static inline void acpi_early_processor_osc(void) {}
+static inline acpi_status acpi_early_processor_osc(void) { return AE_ERROR; }
#endif
/* --------------------------------------------------------------------------
diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c
index 18fb04523f93..8d10d000ebc2 100644
--- a/drivers/acpi/processor_pdc.c
+++ b/drivers/acpi/processor_pdc.c
@@ -73,7 +73,7 @@ static void acpi_set_pdc_bits(u32 *buf)
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)
diff --git a/include/acpi/pdc_intel.h b/include/acpi/pdc_intel.h
index 967c552d1cd3..9427f639287f 100644
--- a/include/acpi/pdc_intel.h
+++ b/include/acpi/pdc_intel.h
@@ -16,6 +16,7 @@
#define ACPI_PDC_C_C1_FFH (0x0100)
#define ACPI_PDC_C_C2C3_FFH (0x0200)
#define ACPI_PDC_SMP_P_HWCOORD (0x0800)
+#define ACPI_PDC_COLLAB_PROC_PERF (0x1000)
#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \
ACPI_PDC_C_C1_HALT | \
--
2.40.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v1 2/2] acpi: Move logic responsible for conveying processor OSPM capabilities
2023-05-12 15:25 [PATCH v1 0/2] Prefer using _OSC method over deprecated _PDC Michal Wilczynski
2023-05-12 15:25 ` [PATCH v1 1/2] acpi: Use _OSC method to convey processor OSPM capabilites Michal Wilczynski
@ 2023-05-12 15:25 ` Michal Wilczynski
2023-05-12 18:04 ` kernel test robot
2023-05-12 21:42 ` kernel test robot
1 sibling, 2 replies; 5+ messages in thread
From: Michal Wilczynski @ 2023-05-12 15:25 UTC (permalink / raw)
To: linux-acpi; +Cc: rafael, srinivas.pandruvada, hanjun.guo, Michal Wilczynski
Since _PDC method is deprecated and a preferred method of communicating
OSPM processor power management capabilities is _OSC there is a need to
move functions checking whether processor is present and workarounds for
specific hardware to acpi_processor.c as this logic is not _PDC specific.
It also applies to the _OSC objects.
Move processor_dmi_check(), processor_idle_dmi_table, set_no_mwait() and
processor_physically_present() to acpi_processor.c.
Introduce IDLE_NOMWAIT workaround and processor_dmi_table workarounds to
work with _OSC objects.
Mark acpi_early_processor_set_pdc() and acpi_processor_set_pdc() as
deprecated.
Signed-off-by: Michal Wilczynski <michal.wilczynski@intel.com>
---
drivers/acpi/acpi_processor.c | 83 ++++++++++++++++++++++++++++++++++-
drivers/acpi/internal.h | 3 ++
drivers/acpi/processor_pdc.c | 80 +--------------------------------
include/acpi/processor.h | 2 +-
4 files changed, 87 insertions(+), 81 deletions(-)
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
index 26f6c002016b..2437c916d8b0 100644
--- a/drivers/acpi/acpi_processor.c
+++ b/drivers/acpi/acpi_processor.c
@@ -10,6 +10,7 @@
* Rafael J. Wysocki <rafael.j.wysocki@intel.com>
*/
+#include <linux/dmi.h>
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/kernel.h>
@@ -21,6 +22,8 @@
#include <asm/cpu.h>
+#include <xen/xen.h>
+
#include "internal.h"
DEFINE_PER_CPU(struct acpi_processor *, processors);
@@ -508,7 +511,79 @@ static void acpi_processor_remove(struct acpi_device *device)
}
#endif /* CONFIG_ACPI_HOTPLUG_CPU */
-#ifdef CONFIG_X86
+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 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},
+ {},
+};
+
+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);
+}
+
static bool acpi_hwp_native_thermal_lvt_set;
static acpi_status __init acpi_processor_osc(acpi_handle handle, u32 lvl,
void *context, void **rv)
@@ -523,6 +598,9 @@ static acpi_status __init acpi_processor_osc(acpi_handle handle, u32 lvl,
.cap.pointer = capbuf,
};
+ if (processor_physically_present(handle) == false)
+ return AE_OK;
+
arch_acpi_set_proc_cap_bits(&capbuf[OSC_SUPPORT_DWORD]);
if (boot_option_idle_override == IDLE_NOMWAIT)
@@ -550,6 +628,8 @@ acpi_status __init acpi_early_processor_osc(void)
{
acpi_status status;
+ processor_dmi_check();
+
status = acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, acpi_processor_osc, NULL,
NULL, NULL);
@@ -561,7 +641,6 @@ acpi_status __init acpi_early_processor_osc(void)
return status;
}
-#endif
/*
* The following ACPI IDs are known to be suitable for representing as
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 58e892376391..24e93413ae41 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -155,6 +155,9 @@ void acpi_early_processor_set_pdc(void);
static inline void acpi_early_processor_set_pdc(void) {}
#endif
+void processor_dmi_check(void);
+bool processor_physically_present(acpi_handle handle);
+
#ifdef CONFIG_X86
acpi_status acpi_early_processor_osc(void);
#else
diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c
index 8d10d000ebc2..ce3acd86dd12 100644
--- a/drivers/acpi/processor_pdc.c
+++ b/drivers/acpi/processor_pdc.c
@@ -9,61 +9,12 @@
#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;
@@ -146,7 +97,7 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
return status;
}
-void acpi_processor_set_pdc(acpi_handle handle)
+void __deprecated acpi_processor_set_pdc(acpi_handle handle)
{
struct acpi_object_list *obj_list;
@@ -174,34 +125,7 @@ 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)
+void __init __deprecated acpi_early_processor_set_pdc(void)
{
processor_dmi_check();
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 94181fe9780a..83ed42254567 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -372,7 +372,7 @@ static inline void acpi_cppc_processor_exit(struct acpi_processor *pr)
#endif /* CONFIG_ACPI_CPPC_LIB */
/* in processor_pdc.c */
-void acpi_processor_set_pdc(acpi_handle handle);
+void __deprecated acpi_processor_set_pdc(acpi_handle handle);
/* in processor_throttling.c */
#ifdef CONFIG_ACPI_CPU_FREQ_PSS
--
2.40.1
^ permalink raw reply related [flat|nested] 5+ messages in thread