Re: [PATCH v4 2/2] ACPI: CPPC: Add ospm_nominal_perf support
From: Pierre Gondois
Date: Thu May 28 2026 - 08:17:55 EST
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.