Re: [PATCH v4 2/2] ACPI: CPPC: Add ospm_nominal_perf support
From: Sumit Gupta
Date: Tue Jun 09 2026 - 03:54:19 EST
On 28/05/26 17:42, Pierre Gondois wrote:
External email: Use caution opening links or attachments
Hello Sumit,
On 5/27/26 21:46, Sumit Gupta wrote:
Expose the OSPM Nominal Performance register (ACPI 6.6, Section
8.4.6.1.2.6), which conveys the desired nominal performance level
at which the platform may run. Unlike the existing read-only
Nominal Performance register, it is writable and lets OSPM
request a lower nominal level than the platform-reported nominal.
The platform classifies performance above this level as boosted
and below as throttled for its power/thermal decisions.
It is exposed as a per-policy cpufreq sysfs attribute in kHz, to
match the cpufreq sysfs unit convention:
/sys/devices/system/cpu/cpufreq/policyN/ospm_nominal_freq
The attribute is documented in
Documentation/ABI/testing/sysfs-devices-system-cpu.
Writes are converted to perf via cppc_khz_to_perf(), validated
against [Lowest Performance, Nominal Performance], and applied to
every CPU in policy->cpus.
The register is write-only; the kernel caches the last written
value in struct cppc_cpudata for sysfs readback (returns 0 until
userspace writes a value).
Signed-off-by: Sumit Gupta <sumitg@xxxxxxxxxx>
---
.../ABI/testing/sysfs-devices-system-cpu | 17 ++++++
drivers/acpi/cppc_acpi.c | 35 +++++++++++
drivers/cpufreq/cppc_cpufreq.c | 60 +++++++++++++++++++
include/acpi/cppc_acpi.h | 12 ++++
4 files changed, 124 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index 82d10d556cc8..ac1bf1b89ac4 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -346,6 +346,23 @@ Description: Performance Limited
This file is only present if the cppc-cpufreq driver is in use.
+What: /sys/devices/system/cpu/cpuX/cpufreq/ospm_nominal_freq
+Date: May 2026
+Contact: linux-pm@xxxxxxxxxxxxxxx
+Description: OSPM Nominal Performance (kHz)
+
+ OSPM uses this attribute to request a nominal performance
+ level lower than the platform-reported nominal. The
+ platform treats performance above this level as boost
+ and below as throttle for power and thermal decisions.
+
+ Read returns the last written value in kHz, or 0 if no
+ value has been written. Write a kHz value in the range
+ [lowest_freq, nominal_freq].
+
+ This file is only present if the cppc-cpufreq driver is
+ in use.
+
What: /sys/devices/system/cpu/cpu*/cache/index3/cache_disable_{0,1}
Date: August 2008
KernelVersion: 2.6.27
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index c76cfafa3589..ad6ece16c30d 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -1682,6 +1682,41 @@ int cppc_set_epp(int cpu, u64 epp_val)
}
EXPORT_SYMBOL_GPL(cppc_set_epp);
+/**
+ * cppc_set_ospm_nominal_perf() - Write OSPM Nominal Performance register.
+ * @cpu: CPU on which to write register.
+ * @ospm_nominal_perf: Value to write to the OSPM Nominal Performance register.
+ *
+ * OSPM Nominal Performance conveys the desired nominal performance level
+ * at which the platform may run. Per ACPI 6.6, s8.4.6.1.2.6, the value
+ * must lie within [Lowest Performance, Nominal Performance] and may be
+ * set independently of Minimum, Maximum and Desired performance.
+ *
+ * Return: 0 on success or negative error code.
+ */
+int cppc_set_ospm_nominal_perf(int cpu, u64 ospm_nominal_perf)
+{
+ struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu);
+ struct cppc_perf_caps caps;
+ int ret;
+
+ if (!cpc_desc) {
+ pr_debug("No CPC descriptor for CPU:%d\n", cpu);
+ return -ENODEV;
+ }
+
+ ret = cppc_get_perf_caps(cpu, &caps);
+ if (ret)
+ return ret;
+
+ if (ospm_nominal_perf < caps.lowest_perf ||
+ ospm_nominal_perf > caps.nominal_perf)
+ return -EINVAL;
+
+ return cppc_set_reg_val(cpu, OSPM_NOMINAL_PERF, ospm_nominal_perf);
+}
+EXPORT_SYMBOL_GPL(cppc_set_ospm_nominal_perf);
+
/**
* cppc_get_auto_act_window() - Read autonomous activity window register.
* @cpu: CPU from which to read register.
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 15a728dea911..5c54af1655b5 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -1139,11 +1139,70 @@ static int cppc_get_perf_limited_filtered(int cpu, u64 *perf_limited)
CPPC_CPUFREQ_ATTR_RW_U64(perf_limited, cppc_get_perf_limited_filtered,
cppc_set_perf_limited)
+static ssize_t show_ospm_nominal_freq(struct cpufreq_policy *policy, char *buf)
+{
+ struct cppc_cpudata *cpu_data = policy->driver_data;
+ unsigned int freq_khz;
+
+ if (!cpu_data->ospm_nominal_perf_set)
+ return sysfs_emit(buf, "0\n");
The questions on v3 might be more relevant,
but for instance here, the ospm_nominal_perf value is not 0,
the hardware register might contain any value.
So reading the register might be more meaningful than
returning 0.
Agreed.
In v5, reading the register instead of caching:
- Added cppc_get_ospm_nominal_perf().
- show_ospm_nominal_freq() now returns the current register value,
or "<unsupported>" on -EOPNOTSUPP.
- Dropped the cpu_data->ospm_nominal_perf cache and the
ospm_nominal_perf_set bool entirely.
This also follows your earlier point that being write-only doesn't mean
we can't read it (cppc_get_desired_perf() being the precedent).
Thank you,
Sumit Gupta