* [PATCH v2] ACPI: processor: Use Apple-specific methods for P/C-states
@ 2026-11-13 13:12 Atharva Tiwari
0 siblings, 0 replies; only message in thread
From: Atharva Tiwari @ 2026-11-13 13:12 UTC (permalink / raw)
Cc: Atharva Tiwari, Rafael J. Wysocki, Len Brown, open list:ACPI, open list
Use APSS and ACST instead of _PSS and _CST when available on Intel Macs
as they include better P/C-States.
These methods are used in macOS (X86PlatformPlugin.kext),
and when not found we fallback to generic _PSS and _CST methods.
Changes in v2:
- Improved description of the patch
- Replaced goto's and if statement's with new functions
- Added support to differentiate _PSS and APSS in debug info/error info
- Added support to differentiate _CST and ACST in debug info/error info
- Used Package instead of variable for ACST description
Link to v1:
https://lore.kernel.org/all/20261015204450.1270-1-atharvatiwarilinuxdev@gmail.com/
Signed-off-by: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
---
drivers/acpi/acpi_processor.c | 80 +++++++++++++++++++++-----------
drivers/acpi/processor_perflib.c | 43 +++++++++++++----
2 files changed, 86 insertions(+), 37 deletions(-)
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
index 5fbab5417..bbe471b3c 100644
--- a/drivers/acpi/acpi_processor.c
+++ b/drivers/acpi/acpi_processor.c
@@ -18,6 +18,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/platform_data/x86/apple.h>
#include <linux/platform_device.h>
#include <acpi/processor.h>
@@ -815,6 +816,22 @@ bool acpi_processor_claim_cst_control(void)
}
EXPORT_SYMBOL_NS_GPL(acpi_processor_claim_cst_control, "ACPI_PROCESSOR_IDLE");
+static int acpi_processor_apple_acst(acpi_handle handle, struct acpi_buffer *buffer)
+{
+ acpi_status status;
+
+ if (!x86_apple_machine)
+ return 0;
+
+ status = acpi_evaluate_object(handle, "ACST", NULL, buffer);
+ if (ACPI_FAILURE(status)) {
+ buffer->length = ACPI_ALLOCATE_BUFFER;
+ buffer->pointer = NULL;
+ return 0;
+ }
+
+ return 1;
+}
/**
* acpi_processor_evaluate_cst - Evaluate the processor _CST control method.
* @handle: ACPI handle of the processor object containing the _CST.
@@ -837,28 +854,35 @@ int acpi_processor_evaluate_cst(acpi_handle handle, u32 cpu,
acpi_status status;
u64 count;
int last_index = 0;
- int i, ret = 0;
+ int i, ret = 0, base = 0;
+ bool using_acst = false;
- status = acpi_evaluate_object(handle, "_CST", NULL, &buffer);
- if (ACPI_FAILURE(status)) {
- acpi_handle_debug(handle, "No _CST\n");
- return -ENODEV;
+ using_acst = acpi_processor_apple_acst(handle, &buffer);
+ if (using_acst)
+ base = 1; /* ACST is a 4 field package we need to skip the first field */
+
+ if (!using_acst) {
+ status = acpi_evaluate_object(handle, "_CST", NULL, &buffer);
+ if (ACPI_FAILURE(status)) {
+ acpi_handle_debug(handle, "No _CST\n");
+ return -ENODEV;
+ }
}
cst = buffer.pointer;
- /* There must be at least 2 elements. */
- if (!cst || cst->type != ACPI_TYPE_PACKAGE || cst->package.count < 2) {
- acpi_handle_warn(handle, "Invalid _CST output\n");
+ /* There must be at least 2 elements for _CST and at least 3 elements for ACST. */
+ if (!cst || cst->type != ACPI_TYPE_PACKAGE || cst->package.count < base + 2) {
+ acpi_handle_warn(handle, "Invalid %s output\n", using_acst ? "ACST" : "_CST");
ret = -EFAULT;
goto end;
}
- count = cst->package.elements[0].integer.value;
+ count = cst->package.elements[base].integer.value;
/* Validate the number of C-states. */
- if (count < 1 || count != cst->package.count - 1) {
- acpi_handle_warn(handle, "Inconsistent _CST data\n");
+ if (count < 1 || count != cst->package.count - 1 - base) {
+ acpi_handle_warn(handle, "Inconsistent %s data\n", using_acst ? "ACST" : "_CST");
ret = -EFAULT;
goto end;
}
@@ -882,24 +906,24 @@ int acpi_processor_evaluate_cst(acpi_handle handle, u32 cpu,
memset(&cx, 0, sizeof(cx));
- element = &cst->package.elements[i];
+ element = &cst->package.elements[base + i];
if (element->type != ACPI_TYPE_PACKAGE) {
- acpi_handle_info(handle, "_CST C%d type(%x) is not package, skip...\n",
- i, element->type);
+ acpi_handle_info(handle, "%s C%d type(%x) is not package, skip...\n",
+ using_acst ? "ACST" : "_CST", i, element->type);
continue;
}
if (element->package.count != 4) {
- acpi_handle_info(handle, "_CST C%d package count(%d) is not 4, skip...\n",
- i, element->package.count);
+ acpi_handle_info(handle, "%s C%d package count(%d) is not 4, skip...\n",
+ using_acst ? "ACST" : "_CST", i, element->package.count);
continue;
}
obj = &element->package.elements[0];
if (obj->type != ACPI_TYPE_BUFFER) {
- acpi_handle_info(handle, "_CST C%d package element[0] type(%x) is not buffer, skip...\n",
- i, obj->type);
+ acpi_handle_info(handle, "%s C%d package element[0] type(%x) is not buffer, skip...\n",
+ using_acst ? "ACST" : "_CST", i, obj->type);
continue;
}
@@ -907,8 +931,8 @@ int acpi_processor_evaluate_cst(acpi_handle handle, u32 cpu,
obj = &element->package.elements[1];
if (obj->type != ACPI_TYPE_INTEGER) {
- acpi_handle_info(handle, "_CST C[%d] package element[1] type(%x) is not integer, skip...\n",
- i, obj->type);
+ acpi_handle_info(handle, "%s C[%d] package element[1] type(%x) is not integer, skip...\n",
+ using_acst ? "ACST" : "_CST", i, obj->type);
continue;
}
@@ -947,8 +971,8 @@ int acpi_processor_evaluate_cst(acpi_handle handle, u32 cpu,
cx.entry_method = ACPI_CSTATE_HALT;
snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT");
} else {
- acpi_handle_info(handle, "_CST C%d declares FIXED_HARDWARE C-state but not supported in hardware, skip...\n",
- i);
+ acpi_handle_info(handle, "%s C%d declares FIXED_HARDWARE C-state but not supported in hardware, skip...\n",
+ using_acst ? "ACST" : "_CST", i);
continue;
}
} else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
@@ -956,8 +980,8 @@ int acpi_processor_evaluate_cst(acpi_handle handle, u32 cpu,
snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x",
cx.address);
} else {
- acpi_handle_info(handle, "_CST C%d space_id(%x) neither FIXED_HARDWARE nor SYSTEM_IO, skip...\n",
- i, reg->space_id);
+ acpi_handle_info(handle, "%s C%d space_id(%x) neither FIXED_HARDWARE nor SYSTEM_IO, skip...\n",
+ using_acst ? "ACST" : "_CST", i, reg->space_id);
continue;
}
@@ -966,8 +990,8 @@ int acpi_processor_evaluate_cst(acpi_handle handle, u32 cpu,
obj = &element->package.elements[2];
if (obj->type != ACPI_TYPE_INTEGER) {
- acpi_handle_info(handle, "_CST C%d package element[2] type(%x) not integer, skip...\n",
- i, obj->type);
+ acpi_handle_info(handle, "%s C%d package element[2] type(%x) not integer, skip...\n",
+ using_acst ? "ACST" : "_CST", i, obj->type);
continue;
}
@@ -975,8 +999,8 @@ int acpi_processor_evaluate_cst(acpi_handle handle, u32 cpu,
obj = &element->package.elements[3];
if (obj->type != ACPI_TYPE_INTEGER) {
- acpi_handle_info(handle, "_CST C%d package element[3] type(%x) not integer, skip...\n",
- i, obj->type);
+ acpi_handle_info(handle, "%s C%d package element[3] type(%x) not integer, skip...\n",
+ using_acst ? "ACST" : "_CST", i, obj->type);
continue;
}
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 9e25d6124..9b9533649 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -17,6 +17,7 @@
#include <linux/cpufreq.h>
#include <linux/slab.h>
#include <linux/acpi.h>
+#include <linux/platform_data/x86/apple.h>
#include <acpi/processor.h>
#ifdef CONFIG_X86
#include <asm/cpufeature.h>
@@ -313,6 +314,23 @@ static void amd_fixup_frequency(struct acpi_processor_px *px, int i)
}
}
+static int acpi_evaluate_apple_apss(acpi_handle handle, struct acpi_buffer *buffer)
+{
+ acpi_status status;
+
+ if (!x86_apple_machine)
+ return 0;
+
+ status = acpi_evaluate_object(handle, "APSS", NULL, buffer);
+ if (ACPI_FAILURE(status)) {
+ buffer->length = ACPI_ALLOCATE_BUFFER;
+ buffer->pointer = NULL;
+ return 0;
+ }
+
+ return 1;
+}
+
static int acpi_processor_get_performance_states(struct acpi_processor *pr)
{
int result = 0;
@@ -323,16 +341,21 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
union acpi_object *pss = NULL;
int i;
int last_invalid = -1;
+ bool using_apss;
- status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
- if (ACPI_FAILURE(status)) {
- acpi_evaluation_failure_warn(pr->handle, "_PSS", status);
- return -ENODEV;
+ using_apss = acpi_evaluate_apple_apss(pr->handle, &buffer);
+
+ if (!using_apss) {
+ status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
+ if (ACPI_FAILURE(status)) {
+ acpi_evaluation_failure_warn(pr->handle, "_PSS", status);
+ return -ENODEV;
+ }
}
pss = buffer.pointer;
if (!pss || pss->type != ACPI_TYPE_PACKAGE) {
- pr_err("Invalid _PSS data\n");
+ pr_err("Invalid %s data\n", using_apss ? "APSS" : "_PSS");
result = -EFAULT;
goto end;
}
@@ -360,7 +383,8 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
status = acpi_extract_package(&(pss->package.elements[i]),
&format, &state);
if (ACPI_FAILURE(status)) {
- acpi_handle_warn(pr->handle, "Invalid _PSS data: %s\n",
+ acpi_handle_warn(pr->handle, "Invalid %s data: %s\n",
+ using_apss ? "APSS" : "_PSS",
acpi_format_exception(status));
result = -EFAULT;
kfree(pr->performance->states);
@@ -384,8 +408,8 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
if (!px->core_frequency ||
(u32)(px->core_frequency * 1000) != px->core_frequency * 1000) {
pr_err(FW_BUG
- "Invalid BIOS _PSS frequency found for processor %d: 0x%llx MHz\n",
- pr->id, px->core_frequency);
+ "Invalid BIOS %s frequency found for processor %d: 0x%llx MHz\n",
+ using_apss ? "APSS" : "_PSS", pr->id, px->core_frequency);
if (last_invalid == -1)
last_invalid = i;
} else {
@@ -402,7 +426,8 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
if (last_invalid == 0) {
pr_err(FW_BUG
- "No valid BIOS _PSS frequency found for processor %d\n", pr->id);
+ "No valid BIOS %s frequency found for processor %d\n",
+ using_apss ? "APSS" : "_PSS", pr->id);
result = -EFAULT;
kfree(pr->performance->states);
pr->performance->states = NULL;
--
2.55.0
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-11-13 13:12 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-13 13:12 [PATCH v2] ACPI: processor: Use Apple-specific methods for P/C-states Atharva Tiwari
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®