Re: [PATCH v2] ACPI: CPPC: mask Desired_Excursion when autonomous selection is enabled

From: Pierre Gondois

Date: Thu Apr 30 2026 - 12:56:09 EST


Hello Xueqin,

NIT: The patch only modifies the cppc_cpufreq.c file, so I think the commit line should be:

"ACPI: CPPC:" -> "cpufreq: CPPC:"

On 4/30/26 11:22, luoxueqin wrote:
From: Xueqin luo <luoxueqin@xxxxxxxxxx>

According to the ACPI specification, the Desired_Excursion field is not
utilized when Autonomous Selection is enabled. In this mode, the bit is
architecturally ignored and does not carry meaningful information.

Currently, the kernel exposes the raw Performance Limited register
value to userspace through the cpufreq sysfs interface. This may lead to
misinterpretation, as userspace may assume Desired_Excursion is valid
even when autonomous selection is active.

To provide a stable and semantically correct ABI, mask out the
Desired_Excursion bit when autonomous selection is enabled, so that
userspace does not observe undefined or misleading values.

Writes are left unchanged, as the field is architecturally ignored in
this mode and write attempts are harmless.

Signed-off-by: Xueqin Luo <luoxueqin@xxxxxxxxxx>
---

v2: update subject

drivers/cpufreq/cppc_cpufreq.c | 40 ++++++++++++++++++++++++++++++++--
1 file changed, 38 insertions(+), 2 deletions(-)

diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 7e7f9dfb7a24..c7444a6ceb55 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -982,8 +982,44 @@ store_energy_performance_preference_val(struct cpufreq_policy *policy,
return count;
}
-CPPC_CPUFREQ_ATTR_RW_U64(perf_limited, cppc_get_perf_limited,
- cppc_set_perf_limited)
+static ssize_t show_perf_limited(struct cpufreq_policy *policy, char *buf)
+{
+ bool auto_sel_enabled = false;
+ u64 perf_limited;
+ int ret;
+
+ /* Get Autonomous Selection status */
+ ret = cppc_get_auto_sel(policy->cpu, &auto_sel_enabled);

Would it be equivalent to used the cached value ?

cpu_data->perf_ctrls.auto_sel

------------

Also, if the perf_limited register is not supported,
we are not emitting "<unsupported>" anymore.

Maybe we can keep the CPPC_CPUFREQ_ATTR_RW_U64()
macro and replace cppc_get_perf_limited() by a wrapper
doing what you want ?

+ if (ret) {
+ if (ret == -EOPNOTSUPP)
+ auto_sel_enabled = false;
+ else
+ return ret;
+ }
+
+ /* Read the Performance Limited register */
+ ret = cppc_get_perf_limited(policy->cpu, &perf_limited);
+ if (ret)
+ return ret;
+
+ /*
+ * Desired_Excursion is architecturally ignored when Autonomous
+ * Selection is enabled. Mask it to avoid exposing undefined
+ * semantics to userspace.
+ */
+ if (auto_sel_enabled)
+ perf_limited &= ~CPPC_PERF_LIMITED_DESIRED_EXCURSION;
+
+ return sysfs_emit(buf, "%llu\n", perf_limited);
+
+}
+
+static ssize_t store_perf_limited(struct cpufreq_policy *policy,
+ const char *buf, size_t count)
+{
+ return cppc_cpufreq_sysfs_store_u64(policy->cpu,
+ cppc_set_perf_limited, buf, count);
+}
cpufreq_freq_attr_ro(freqdomain_cpus);
cpufreq_freq_attr_rw(auto_select);