Strings written to the ``energy_performance_preference`` attribute are
internally translated to integer values written to the processor's
Energy-Performance Preference (EPP) knob (if supported) or its
-Energy-Performance Bias (EPB) knob.
+Energy-Performance Bias (EPB) knob. It is also possible to write a positive
+integer value between 0 to 255, if the EPP feature is present. If the EPP
+feature is not present, writing integer value to this attribute is not
+supported. In this case, user can use
+ "/sys/devices/system/cpu/cpu*/power/energy_perf_bias" interface.
[Note that tasks may by migrated from one CPU to another by the scheduler's
load-balancing algorithm and if different energy vs performance hints are
HWP_EPP_POWERSAVE
};
-static int intel_pstate_get_energy_pref_index(struct cpudata *cpu_data)
+static int intel_pstate_get_energy_pref_index(struct cpudata *cpu_data, int *raw_epp)
{
s16 epp;
int index = -EINVAL;
+ *raw_epp = 0;
epp = intel_pstate_get_epp(cpu_data, 0);
if (epp < 0)
return epp;
if (boot_cpu_has(X86_FEATURE_HWP_EPP)) {
if (epp == HWP_EPP_PERFORMANCE)
return 1;
- if (epp <= HWP_EPP_BALANCE_PERFORMANCE)
+ if (epp == HWP_EPP_BALANCE_PERFORMANCE)
return 2;
- if (epp <= HWP_EPP_BALANCE_POWERSAVE)
+ if (epp == HWP_EPP_BALANCE_POWERSAVE)
return 3;
- else
+ if (epp == HWP_EPP_POWERSAVE)
return 4;
+ *raw_epp = epp;
+ return 0;
} else if (boot_cpu_has(X86_FEATURE_EPB)) {
/*
* Range:
}
static int intel_pstate_set_energy_pref_index(struct cpudata *cpu_data,
- int pref_index)
+ int pref_index, bool use_raw,
+ u32 raw_epp)
{
int epp = -EINVAL;
int ret;
value &= ~GENMASK_ULL(31, 24);
+ if (use_raw) {
+ if (raw_epp > 255) {
+ ret = -EINVAL;
+ goto return_pref;
+ }
+ value |= (u64)raw_epp << 24;
+ ret = wrmsrl_on_cpu(cpu_data->cpu, MSR_HWP_REQUEST, value);
+ goto return_pref;
+ }
+
if (epp == -EINVAL)
epp = epp_values[pref_index - 1];
{
struct cpudata *cpu_data = all_cpu_data[policy->cpu];
char str_preference[21];
+ bool raw = false;
+ u32 epp;
int ret;
ret = sscanf(buf, "%20s", str_preference);
return -EINVAL;
ret = match_string(energy_perf_strings, -1, str_preference);
- if (ret < 0)
+ if (ret < 0) {
+ if (!boot_cpu_has(X86_FEATURE_HWP_EPP))
+ return ret;
+
+ ret = kstrtouint(buf, 10, &epp);
+ if (ret)
+ return ret;
+
+ raw = true;
+ }
+
+ ret = intel_pstate_set_energy_pref_index(cpu_data, ret, raw, epp);
+ if (ret)
return ret;
- intel_pstate_set_energy_pref_index(cpu_data, ret);
return count;
}
struct cpufreq_policy *policy, char *buf)
{
struct cpudata *cpu_data = all_cpu_data[policy->cpu];
- int preference;
+ int preference, raw_epp;
- preference = intel_pstate_get_energy_pref_index(cpu_data);
+ preference = intel_pstate_get_energy_pref_index(cpu_data, &raw_epp);
if (preference < 0)
return preference;
- return sprintf(buf, "%s\n", energy_perf_strings[preference]);
+ if (raw_epp)
+ return sprintf(buf, "%d\n", raw_epp);
+ else
+ return sprintf(buf, "%s\n", energy_perf_strings[preference]);
}
cpufreq_freq_attr_rw(energy_performance_preference);