Commit 6927f218 authored by Mario Limonciello (AMD)'s avatar Mario Limonciello (AMD)
Browse files

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: default avatarGautham R. Shenoy <gautham.shenoy@amd.com>
Signed-off-by: default avatarMario Limonciello (AMD) <superm1@kernel.org>
parent 798c4759
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -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 dynamic EPP is enabled, writes to energy_performance_preference are blocked
even when EPP feature is enabled by platform firmware. 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``
+26 −10
Original line number Diff line number Diff line
@@ -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);

@@ -1408,6 +1411,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) {
@@ -1415,14 +1419,21 @@ static ssize_t store_energy_performance_preference(struct cpufreq_policy *policy
		return -EBUSY;
	}

	/*
	 * 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)
		if (ret < 0 || ret == EPP_INDEX_CUSTOM)
			return -EINVAL;

		if (ret)
			epp = epp_values[ret];
		else
			epp = amd_pstate_get_balanced_epp(policy);
	}

	if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) {
		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
	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)
@@ -1443,6 +1456,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;
+1 −0
Original line number Diff line number Diff line
@@ -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 */