From: "Mario Limonciello (AMD)" <superm1@kernel.org>
To: "Gautham R . Shenoy" <gautham.shenoy@amd.com>
Cc: Perry Yuan <perry.yuan@amd.com>,
linux-kernel@vger.kernel.org (open list:X86 ARCHITECTURE (32-BIT
AND 64-BIT)),
linux-pm@vger.kernel.org (open list:CPU FREQUENCY SCALING
FRAMEWORK), "Mario Limonciello (AMD)" <superm1@kernel.org>
Subject: [PATCH v6 4/5] cpufreq/amd-pstate: Add support for raw EPP writes
Date: Sun, 29 Mar 2026 15:38:10 -0500 [thread overview]
Message-ID: <20260329203811.2590633-5-superm1@kernel.org> (raw)
In-Reply-To: <20260329203811.2590633-1-superm1@kernel.org>
The energy performance preference field of the CPPC request MSR
supports values from 0 to 255, but the strings only offer 4 values.
The other values are useful for tuning the performance of some
workloads.
Add support for writing the raw energy performance preference value
to the sysfs file. If the last value written was an integer then
an integer will be returned. If the last value written was a string
then a string will be returned.
Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
---
v5->v6:
* Move the raw EPP parsing and readback changes into this patch
* Use the kernel bool literal `false` for the raw EPP tracking flag
---
Documentation/admin-guide/pm/amd-pstate.rst | 16 ++++++---
drivers/cpufreq/amd-pstate.c | 36 +++++++++++++++------
drivers/cpufreq/amd-pstate.h | 1 +
3 files changed, 38 insertions(+), 15 deletions(-)
diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
index 2d92c8072b83c..6ff2b477f0472 100644
--- a/Documentation/admin-guide/pm/amd-pstate.rst
+++ b/Documentation/admin-guide/pm/amd-pstate.rst
@@ -316,16 +316,22 @@ A list of all the supported EPP preferences that could be used for
These profiles represent different hints that are provided
to the low-level firmware about the user's desired energy vs efficiency
tradeoff. ``default`` represents the epp value is set by platform
-firmware. This attribute is read-only.
+firmware. ``custom`` designates that integer values 0-255 may be written
+as well. This attribute is read-only.
``energy_performance_preference``
The current energy performance preference can be read from this attribute.
and user can change current preference according to energy or performance needs
-Please get all support profiles list from
-``energy_performance_available_preferences`` attribute, all the profiles are
-integer values defined between 0 to 255 when EPP feature is enabled by platform
-firmware, but if the dynamic EPP feature is enabled, driver will block writes.
+Coarse named profiles are available in the attribute
+``energy_performance_available_preferences``.
+Users can also write individual integer values between 0 to 255.
+When EPP feature is enabled by platform firmware but if the dynamic EPP feature is
+enabled, driver will ignore the written value. Lower epp values shift the bias
+towards improved performance while a higher epp value shifts the bias towards
+power-savings. The exact impact can change from one platform to the other.
+If a valid integer was last written, then a number will be returned on future reads.
+If a valid string was last written then a string will be returned on future reads.
This attribute is read-write.
``boost``
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index 93cda05ffa855..11fc992ea2da1 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -109,6 +109,7 @@ static struct quirk_entry *quirks;
* 2 balance_performance
* 3 balance_power
* 4 power
+ * 5 custom (for raw EPP values)
*/
enum energy_perf_value_index {
EPP_INDEX_DEFAULT = 0,
@@ -116,6 +117,7 @@ enum energy_perf_value_index {
EPP_INDEX_BALANCE_PERFORMANCE,
EPP_INDEX_BALANCE_POWERSAVE,
EPP_INDEX_POWERSAVE,
+ EPP_INDEX_CUSTOM,
EPP_INDEX_MAX,
};
@@ -125,6 +127,7 @@ static const char * const energy_perf_strings[] = {
[EPP_INDEX_BALANCE_PERFORMANCE] = "balance_performance",
[EPP_INDEX_BALANCE_POWERSAVE] = "balance_power",
[EPP_INDEX_POWERSAVE] = "power",
+ [EPP_INDEX_CUSTOM] = "custom",
};
static_assert(ARRAY_SIZE(energy_perf_strings) == EPP_INDEX_MAX);
@@ -135,7 +138,7 @@ static unsigned int epp_values[] = {
[EPP_INDEX_BALANCE_POWERSAVE] = AMD_CPPC_EPP_BALANCE_POWERSAVE,
[EPP_INDEX_POWERSAVE] = AMD_CPPC_EPP_POWERSAVE,
};
-static_assert(ARRAY_SIZE(epp_values) == EPP_INDEX_MAX);
+static_assert(ARRAY_SIZE(epp_values) == EPP_INDEX_MAX - 1);
typedef int (*cppc_mode_transition_fn)(int);
@@ -1413,6 +1416,7 @@ static ssize_t store_energy_performance_preference(struct cpufreq_policy *policy
{
struct amd_cpudata *cpudata = policy->driver_data;
ssize_t ret;
+ bool raw_epp = false;
u8 epp;
if (cpudata->dynamic_epp) {
@@ -1420,14 +1424,21 @@ static ssize_t store_energy_performance_preference(struct cpufreq_policy *policy
return -EBUSY;
}
- ret = sysfs_match_string(energy_perf_strings, buf);
- if (ret < 0)
- return -EINVAL;
-
- if (ret)
- epp = epp_values[ret];
- else
- epp = amd_pstate_get_balanced_epp(policy);
+ /*
+ * if the value matches a number, use that, otherwise see if
+ * matches an index in the energy_perf_strings array
+ */
+ ret = kstrtou8(buf, 0, &epp);
+ raw_epp = !ret;
+ if (ret) {
+ ret = sysfs_match_string(energy_perf_strings, buf);
+ if (ret < 0 || ret == EPP_INDEX_CUSTOM)
+ return -EINVAL;
+ if (ret)
+ epp = epp_values[ret];
+ else
+ epp = amd_pstate_get_balanced_epp(policy);
+ }
if (epp > 0 && cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) {
pr_debug("EPP cannot be set under performance policy\n");
@@ -1438,7 +1449,9 @@ static ssize_t store_energy_performance_preference(struct cpufreq_policy *policy
if (ret)
return ret;
- return ret ? ret : count;
+ cpudata->raw_epp = raw_epp;
+
+ return count;
}
static ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf)
@@ -1448,6 +1461,9 @@ static ssize_t show_energy_performance_preference(struct cpufreq_policy *policy,
epp = FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached);
+ if (cpudata->raw_epp)
+ return sysfs_emit(buf, "%u\n", epp);
+
switch (epp) {
case AMD_CPPC_EPP_PERFORMANCE:
preference = EPP_INDEX_PERFORMANCE;
diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
index a7e52f79a8029..f7461d1b6bf3c 100644
--- a/drivers/cpufreq/amd-pstate.h
+++ b/drivers/cpufreq/amd-pstate.h
@@ -127,6 +127,7 @@ struct amd_cpudata {
u8 epp_default_ac;
u8 epp_default_dc;
bool dynamic_epp;
+ bool raw_epp;
struct notifier_block power_nb;
/* platform profile */
--
2.43.0
next prev parent reply other threads:[~2026-03-29 20:38 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-29 20:38 [PATCH v6 0/5] amd-pstate Dynamic EPP and raw EPP Mario Limonciello (AMD)
2026-03-29 20:38 ` [PATCH v6 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference Mario Limonciello (AMD)
2026-03-29 20:38 ` [PATCH v6 2/5] cpufreq/amd-pstate: add kernel command line to override dynamic epp Mario Limonciello (AMD)
2026-03-29 20:38 ` [PATCH v6 3/5] cpufreq/amd-pstate: Add support for platform profile class Mario Limonciello (AMD)
2026-03-29 20:38 ` Mario Limonciello (AMD) [this message]
2026-03-29 20:38 ` [PATCH v6 5/5] cpufreq/amd-pstate-ut: Add a unit test for raw EPP Mario Limonciello (AMD)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260329203811.2590633-5-superm1@kernel.org \
--to=superm1@kernel.org \
--cc=gautham.shenoy@amd.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=perry.yuan@amd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox