Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+38 -15
+11 -5
Documentation/admin-guide/pm/amd-pstate.rst
··· 316 316 These profiles represent different hints that are provided 317 317 to the low-level firmware about the user's desired energy vs efficiency 318 318 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. 320 321 321 322 ``energy_performance_preference`` 322 323 323 324 The current energy performance preference can be read from this attribute. 324 325 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. 329 335 This attribute is read-write. 330 336 331 337 ``boost``
+26 -10
drivers/cpufreq/amd-pstate.c
··· 109 109 * 2 balance_performance 110 110 * 3 balance_power 111 111 * 4 power 112 + * 5 custom (for raw EPP values) 112 113 */ 113 114 enum energy_perf_value_index { 114 115 EPP_INDEX_DEFAULT = 0, ··· 117 116 EPP_INDEX_BALANCE_PERFORMANCE, 118 117 EPP_INDEX_BALANCE_POWERSAVE, 119 118 EPP_INDEX_POWERSAVE, 119 + EPP_INDEX_CUSTOM, 120 120 EPP_INDEX_MAX, 121 121 }; 122 122 ··· 127 125 [EPP_INDEX_BALANCE_PERFORMANCE] = "balance_performance", 128 126 [EPP_INDEX_BALANCE_POWERSAVE] = "balance_power", 129 127 [EPP_INDEX_POWERSAVE] = "power", 128 + [EPP_INDEX_CUSTOM] = "custom", 130 129 }; 131 130 static_assert(ARRAY_SIZE(energy_perf_strings) == EPP_INDEX_MAX); 132 131 ··· 138 135 [EPP_INDEX_BALANCE_POWERSAVE] = AMD_CPPC_EPP_BALANCE_POWERSAVE, 139 136 [EPP_INDEX_POWERSAVE] = AMD_CPPC_EPP_POWERSAVE, 140 137 }; 141 - static_assert(ARRAY_SIZE(epp_values) == EPP_INDEX_MAX); 138 + static_assert(ARRAY_SIZE(epp_values) == EPP_INDEX_MAX - 1); 142 139 143 140 typedef int (*cppc_mode_transition_fn)(int); 144 141 ··· 1411 1408 { 1412 1409 struct amd_cpudata *cpudata = policy->driver_data; 1413 1410 ssize_t ret; 1411 + bool raw_epp = false; 1414 1412 u8 epp; 1415 1413 1416 1414 if (cpudata->dynamic_epp) { ··· 1419 1415 return -EBUSY; 1420 1416 } 1421 1417 1422 - ret = sysfs_match_string(energy_perf_strings, buf); 1423 - if (ret < 0) 1424 - return -EINVAL; 1425 - 1426 - if (ret) 1427 - epp = epp_values[ret]; 1428 - else 1429 - epp = amd_pstate_get_balanced_epp(policy); 1418 + /* 1419 + * if the value matches a number, use that, otherwise see if 1420 + * matches an index in the energy_perf_strings array 1421 + */ 1422 + ret = kstrtou8(buf, 0, &epp); 1423 + raw_epp = !ret; 1424 + if (ret) { 1425 + ret = sysfs_match_string(energy_perf_strings, buf); 1426 + if (ret < 0 || ret == EPP_INDEX_CUSTOM) 1427 + return -EINVAL; 1428 + if (ret) 1429 + epp = epp_values[ret]; 1430 + else 1431 + epp = amd_pstate_get_balanced_epp(policy); 1432 + } 1430 1433 1431 1434 if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) { 1432 1435 pr_debug("EPP cannot be set under performance policy\n"); ··· 1444 1433 if (ret) 1445 1434 return ret; 1446 1435 1447 - return ret ? ret : count; 1436 + cpudata->raw_epp = raw_epp; 1437 + 1438 + return count; 1448 1439 } 1449 1440 1450 1441 static ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf) ··· 1455 1442 u8 preference, epp; 1456 1443 1457 1444 epp = FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached); 1445 + 1446 + if (cpudata->raw_epp) 1447 + return sysfs_emit(buf, "%u\n", epp); 1458 1448 1459 1449 switch (epp) { 1460 1450 case AMD_CPPC_EPP_PERFORMANCE:
+1
drivers/cpufreq/amd-pstate.h
··· 127 127 u8 epp_default_ac; 128 128 u8 epp_default_dc; 129 129 bool dynamic_epp; 130 + bool raw_epp; 130 131 struct notifier_block power_nb; 131 132 132 133 /* platform profile */