Skip to content

Commit f473bf3

Browse files
spandruvadarafaeljw
authored andcommitted
cpufreq: intel_pstate: Allow raw energy performance preference value
Currently using attribute "energy_performance_preference", user space can write one of the four per-defined preference string. These preference strings gets mapped to a hard-coded Energy-Performance Preference (EPP) or Energy-Performance Bias (EPB) knob. These four values are supposed to cover broad spectrum of use cases, but are not uniformly distributed in the range. There are number of cases, where this is not enough. For example: Suppose user wants more performance when connected to AC. Instead of using default "balance performance", the "performance" setting can be used. This changes EPP value from 0x80 to 0x00. But setting EPP to 0, results in electrical and thermal issues on some platforms. This results in aggressive throttling, which causes a drop in performance. But some value between 0x80 and 0x00 results in better performance. But that value can't be fixed as the power curve is not linear. In some cases just changing EPP from 0x80 to 0x75 is enough to get significant performance gain. Similarly on battery the default "balance_performance" mode can be aggressive in power consumption. But picking up the next choice "balance power" results in too much loss of performance, which results in bad user experience in use cases like "Google Hangout". It was observed that some value between these two EPP is optimal. This change allows fine grain EPP tuning for platform like Chromebook or for users who wants to fine tune power and performance. Here based on the product and use cases, different EPP values can be set. This change is similar to the change done for: /sys/devices/system/cpu/cpu*/power/energy_perf_bias where user has choice to write a predefined string or raw value. The change itself is trivial. When user preference doesn't match predefined string preferences and value is an unsigned integer and in range, use that value for EPP. When the EPP feature is not present writing raw value is not supported. Suggested-by: Len Brown <[email protected]> Signed-off-by: Srinivas Pandruvada <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent ed7bde7 commit f473bf3

File tree

2 files changed

+45
-11
lines changed

2 files changed

+45
-11
lines changed

Documentation/admin-guide/pm/intel_pstate.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,11 @@ somewhere between the two extremes:
565565
Strings written to the ``energy_performance_preference`` attribute are
566566
internally translated to integer values written to the processor's
567567
Energy-Performance Preference (EPP) knob (if supported) or its
568-
Energy-Performance Bias (EPB) knob.
568+
Energy-Performance Bias (EPB) knob. It is also possible to write a positive
569+
integer value between 0 to 255, if the EPP feature is present. If the EPP
570+
feature is not present, writing integer value to this attribute is not
571+
supported. In this case, user can use
572+
"/sys/devices/system/cpu/cpu*/power/energy_perf_bias" interface.
569573

570574
[Note that tasks may by migrated from one CPU to another by the scheduler's
571575
load-balancing algorithm and if different energy vs performance hints are

drivers/cpufreq/intel_pstate.c

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -602,24 +602,27 @@ static const unsigned int epp_values[] = {
602602
HWP_EPP_POWERSAVE
603603
};
604604

605-
static int intel_pstate_get_energy_pref_index(struct cpudata *cpu_data)
605+
static int intel_pstate_get_energy_pref_index(struct cpudata *cpu_data, int *raw_epp)
606606
{
607607
s16 epp;
608608
int index = -EINVAL;
609609

610+
*raw_epp = 0;
610611
epp = intel_pstate_get_epp(cpu_data, 0);
611612
if (epp < 0)
612613
return epp;
613614

614615
if (boot_cpu_has(X86_FEATURE_HWP_EPP)) {
615616
if (epp == HWP_EPP_PERFORMANCE)
616617
return 1;
617-
if (epp <= HWP_EPP_BALANCE_PERFORMANCE)
618+
if (epp == HWP_EPP_BALANCE_PERFORMANCE)
618619
return 2;
619-
if (epp <= HWP_EPP_BALANCE_POWERSAVE)
620+
if (epp == HWP_EPP_BALANCE_POWERSAVE)
620621
return 3;
621-
else
622+
if (epp == HWP_EPP_POWERSAVE)
622623
return 4;
624+
*raw_epp = epp;
625+
return 0;
623626
} else if (boot_cpu_has(X86_FEATURE_EPB)) {
624627
/*
625628
* Range:
@@ -638,7 +641,8 @@ static int intel_pstate_get_energy_pref_index(struct cpudata *cpu_data)
638641
}
639642

640643
static int intel_pstate_set_energy_pref_index(struct cpudata *cpu_data,
641-
int pref_index)
644+
int pref_index, bool use_raw,
645+
u32 raw_epp)
642646
{
643647
int epp = -EINVAL;
644648
int ret;
@@ -657,6 +661,16 @@ static int intel_pstate_set_energy_pref_index(struct cpudata *cpu_data,
657661

658662
value &= ~GENMASK_ULL(31, 24);
659663

664+
if (use_raw) {
665+
if (raw_epp > 255) {
666+
ret = -EINVAL;
667+
goto return_pref;
668+
}
669+
value |= (u64)raw_epp << 24;
670+
ret = wrmsrl_on_cpu(cpu_data->cpu, MSR_HWP_REQUEST, value);
671+
goto return_pref;
672+
}
673+
660674
if (epp == -EINVAL)
661675
epp = epp_values[pref_index - 1];
662676

@@ -694,31 +708,47 @@ static ssize_t store_energy_performance_preference(
694708
{
695709
struct cpudata *cpu_data = all_cpu_data[policy->cpu];
696710
char str_preference[21];
711+
bool raw = false;
712+
u32 epp;
697713
int ret;
698714

699715
ret = sscanf(buf, "%20s", str_preference);
700716
if (ret != 1)
701717
return -EINVAL;
702718

703719
ret = match_string(energy_perf_strings, -1, str_preference);
704-
if (ret < 0)
720+
if (ret < 0) {
721+
if (!boot_cpu_has(X86_FEATURE_HWP_EPP))
722+
return ret;
723+
724+
ret = kstrtouint(buf, 10, &epp);
725+
if (ret)
726+
return ret;
727+
728+
raw = true;
729+
}
730+
731+
ret = intel_pstate_set_energy_pref_index(cpu_data, ret, raw, epp);
732+
if (ret)
705733
return ret;
706734

707-
intel_pstate_set_energy_pref_index(cpu_data, ret);
708735
return count;
709736
}
710737

711738
static ssize_t show_energy_performance_preference(
712739
struct cpufreq_policy *policy, char *buf)
713740
{
714741
struct cpudata *cpu_data = all_cpu_data[policy->cpu];
715-
int preference;
742+
int preference, raw_epp;
716743

717-
preference = intel_pstate_get_energy_pref_index(cpu_data);
744+
preference = intel_pstate_get_energy_pref_index(cpu_data, &raw_epp);
718745
if (preference < 0)
719746
return preference;
720747

721-
return sprintf(buf, "%s\n", energy_perf_strings[preference]);
748+
if (raw_epp)
749+
return sprintf(buf, "%d\n", raw_epp);
750+
else
751+
return sprintf(buf, "%s\n", energy_perf_strings[preference]);
722752
}
723753

724754
cpufreq_freq_attr_rw(energy_performance_preference);

0 commit comments

Comments
 (0)