Skip to content

Commit 6927f21

Browse files
committed
cpufreq/amd-pstate: Add support for raw EPP writes
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. Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com> Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
1 parent 798c475 commit 6927f21

3 files changed

Lines changed: 38 additions & 15 deletions

File tree

Documentation/admin-guide/pm/amd-pstate.rst

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -316,16 +316,22 @@ A list of all the supported EPP preferences that could be used for
316316
These profiles represent different hints that are provided
317317
to the low-level firmware about the user's desired energy vs efficiency
318318
tradeoff. ``default`` represents the epp value is set by platform
319-
firmware. This attribute is read-only.
319+
firmware. ``custom`` designates that integer values 0-255 may be written
320+
as well. This attribute is read-only.
320321

321322
``energy_performance_preference``
322323

323324
The current energy performance preference can be read from this attribute.
324325
and user can change current preference according to energy or performance needs
325-
Please get all support profiles list from
326-
``energy_performance_available_preferences`` attribute, all the profiles are
327-
integer values defined between 0 to 255 when EPP feature is enabled by platform
328-
firmware, but if the dynamic EPP feature is enabled, driver will block writes.
326+
Coarse named profiles are available in the attribute
327+
``energy_performance_available_preferences``.
328+
Users can also write individual integer values between 0 to 255.
329+
When dynamic EPP is enabled, writes to energy_performance_preference are blocked
330+
even when EPP feature is enabled by platform firmware. Lower epp values shift the bias
331+
towards improved performance while a higher epp value shifts the bias towards
332+
power-savings. The exact impact can change from one platform to the other.
333+
If a valid integer was last written, then a number will be returned on future reads.
334+
If a valid string was last written then a string will be returned on future reads.
329335
This attribute is read-write.
330336

331337
``boost``

drivers/cpufreq/amd-pstate.c

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,15 @@ static struct quirk_entry *quirks;
109109
* 2 balance_performance
110110
* 3 balance_power
111111
* 4 power
112+
* 5 custom (for raw EPP values)
112113
*/
113114
enum energy_perf_value_index {
114115
EPP_INDEX_DEFAULT = 0,
115116
EPP_INDEX_PERFORMANCE,
116117
EPP_INDEX_BALANCE_PERFORMANCE,
117118
EPP_INDEX_BALANCE_POWERSAVE,
118119
EPP_INDEX_POWERSAVE,
120+
EPP_INDEX_CUSTOM,
119121
EPP_INDEX_MAX,
120122
};
121123

@@ -125,6 +127,7 @@ static const char * const energy_perf_strings[] = {
125127
[EPP_INDEX_BALANCE_PERFORMANCE] = "balance_performance",
126128
[EPP_INDEX_BALANCE_POWERSAVE] = "balance_power",
127129
[EPP_INDEX_POWERSAVE] = "power",
130+
[EPP_INDEX_CUSTOM] = "custom",
128131
};
129132
static_assert(ARRAY_SIZE(energy_perf_strings) == EPP_INDEX_MAX);
130133

@@ -135,7 +138,7 @@ static unsigned int epp_values[] = {
135138
[EPP_INDEX_BALANCE_POWERSAVE] = AMD_CPPC_EPP_BALANCE_POWERSAVE,
136139
[EPP_INDEX_POWERSAVE] = AMD_CPPC_EPP_POWERSAVE,
137140
};
138-
static_assert(ARRAY_SIZE(epp_values) == EPP_INDEX_MAX);
141+
static_assert(ARRAY_SIZE(epp_values) == EPP_INDEX_MAX - 1);
139142

140143
typedef int (*cppc_mode_transition_fn)(int);
141144

@@ -1408,21 +1411,29 @@ static ssize_t store_energy_performance_preference(struct cpufreq_policy *policy
14081411
{
14091412
struct amd_cpudata *cpudata = policy->driver_data;
14101413
ssize_t ret;
1414+
bool raw_epp = false;
14111415
u8 epp;
14121416

14131417
if (cpudata->dynamic_epp) {
14141418
pr_debug("EPP cannot be set when dynamic EPP is enabled\n");
14151419
return -EBUSY;
14161420
}
14171421

1418-
ret = sysfs_match_string(energy_perf_strings, buf);
1419-
if (ret < 0)
1420-
return -EINVAL;
1421-
1422-
if (ret)
1423-
epp = epp_values[ret];
1424-
else
1425-
epp = amd_pstate_get_balanced_epp(policy);
1422+
/*
1423+
* if the value matches a number, use that, otherwise see if
1424+
* matches an index in the energy_perf_strings array
1425+
*/
1426+
ret = kstrtou8(buf, 0, &epp);
1427+
raw_epp = !ret;
1428+
if (ret) {
1429+
ret = sysfs_match_string(energy_perf_strings, buf);
1430+
if (ret < 0 || ret == EPP_INDEX_CUSTOM)
1431+
return -EINVAL;
1432+
if (ret)
1433+
epp = epp_values[ret];
1434+
else
1435+
epp = amd_pstate_get_balanced_epp(policy);
1436+
}
14261437

14271438
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) {
14281439
pr_debug("EPP cannot be set under performance policy\n");
@@ -1433,7 +1444,9 @@ static ssize_t store_energy_performance_preference(struct cpufreq_policy *policy
14331444
if (ret)
14341445
return ret;
14351446

1436-
return ret ? ret : count;
1447+
cpudata->raw_epp = raw_epp;
1448+
1449+
return count;
14371450
}
14381451

14391452
static ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf)
@@ -1443,6 +1456,9 @@ static ssize_t show_energy_performance_preference(struct cpufreq_policy *policy,
14431456

14441457
epp = FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached);
14451458

1459+
if (cpudata->raw_epp)
1460+
return sysfs_emit(buf, "%u\n", epp);
1461+
14461462
switch (epp) {
14471463
case AMD_CPPC_EPP_PERFORMANCE:
14481464
preference = EPP_INDEX_PERFORMANCE;

drivers/cpufreq/amd-pstate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ struct amd_cpudata {
127127
u8 epp_default_ac;
128128
u8 epp_default_dc;
129129
bool dynamic_epp;
130+
bool raw_epp;
130131
struct notifier_block power_nb;
131132

132133
/* platform profile */

0 commit comments

Comments
 (0)