From 08d95b6becb7dd7551c15738b01114c7efe2f059 Mon Sep 17 00:00:00 2001
From: Anton <snyypi@gmail.com>
Date: Mon, 9 Sep 2024 19:46:38 +0400
Subject: [PATCH] Add EPB (Energy Performance Bias) settings support (#771)

* Added `energy_perf_bias` support for intel_pstate driver

* Refactored epb part, added doc for energy_perf_bias settings
---
 README.md                 | 16 ++++++++++
 auto-cpufreq.conf-example | 16 ++++++++++
 auto_cpufreq/core.py      | 16 +++++++++-
 scripts/cpufreqctl.sh     | 62 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 109 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index b41d5f2c..1d98c98e 100644
--- a/README.md
+++ b/README.md
@@ -326,6 +326,14 @@ governor = performance
 # EPP: see available preferences by running: cat /sys/devices/system/cpu/cpu0/cpufreq/energy_performance_available_preferences
 energy_performance_preference = performance
 
+# EPB (Energy Performance Bias) for the intel_pstate driver
+# see conversion info: https://www.kernel.org/doc/html/latest/admin-guide/pm/intel_epb.html
+# available EPB options include a numeric value between 0-15
+# (where 0 = maximum performance and 15 = maximum power saving),
+# or one of the following strings:
+# performance (0), balance_performance (4), default (6), balance_power (8), or power (15)
+# energy_perf_bias = balance_performance
+
 # Platform Profiles
 # https://www.kernel.org/doc/html/latest/userspace-api/sysfs-platform_profile.html
 # See available options by running:
@@ -356,6 +364,14 @@ governor = powersave
 # EPP: see available preferences by running: cat /sys/devices/system/cpu/cpu0/cpufreq/energy_performance_available_preferences
 energy_performance_preference = power
 
+# EPB (Energy Performance Bias) for the intel_pstate driver
+# see conversion info: https://www.kernel.org/doc/html/latest/admin-guide/pm/intel_epb.html
+# available EPB options include a numeric value between 0-15
+# (where 0 = maximum performance and 15 = maximum power saving),
+# or one of the following strings:
+# performance (0), balance_performance (4), default (6), balance_power (8), or power (15)
+# energy_perf_bias = balance_power
+
 # Platform Profiles
 # https://www.kernel.org/doc/html/latest/userspace-api/sysfs-platform_profile.html
 # See available options by running:
diff --git a/auto-cpufreq.conf-example b/auto-cpufreq.conf-example
index 9c7ff213..b5ba8580 100644
--- a/auto-cpufreq.conf-example
+++ b/auto-cpufreq.conf-example
@@ -7,6 +7,14 @@ governor = performance
 # EPP: see available preferences by running: cat /sys/devices/system/cpu/cpu0/cpufreq/energy_performance_available_preferences
 energy_performance_preference = performance
 
+# EPB (Energy Performance Bias) for the intel_pstate driver
+# see conversion info: https://www.kernel.org/doc/html/latest/admin-guide/pm/intel_epb.html
+# available EPB options include a numeric value between 0-15
+# (where 0 = maximum performance and 15 = maximum power saving),
+# or one of the following strings:
+# performance (0), balance_performance (4), default (6), balance_power (8), or power (15)
+# energy_perf_bias = balance_performance
+
 # Platform Profiles
 # https://www.kernel.org/doc/html/latest/userspace-api/sysfs-platform_profile.html
 # See available options by running:
@@ -48,6 +56,14 @@ governor = powersave
 # EPP: see available preferences by running: cat /sys/devices/system/cpu/cpu0/cpufreq/energy_performance_available_preferences
 energy_performance_preference = power
 
+# EPB (Energy Performance Bias) for the intel_pstate driver
+# see conversion info: https://www.kernel.org/doc/html/latest/admin-guide/pm/intel_epb.html
+# available EPB options include a numeric value between 0-15
+# (where 0 = maximum performance and 15 = maximum power saving),
+# or one of the following strings:
+# performance (0), balance_performance (4), default (6), balance_power (8), or power (15)
+# energy_perf_bias = balance_power
+
 # Platform Profiles
 # https://www.kernel.org/doc/html/latest/userspace-api/sysfs-platform_profile.html
 # See available options by running:
diff --git a/auto_cpufreq/core.py b/auto_cpufreq/core.py
index b51d55df..ae0147fd 100755
--- a/auto_cpufreq/core.py
+++ b/auto_cpufreq/core.py
@@ -504,6 +504,18 @@ def set_platform_profile(conf, profile):
             print(f'Setting to use: "{pp}" Platform Profile')
             run(f"cpufreqctl.auto-cpufreq --pp --set={pp}", shell=True)
 
+def set_energy_perf_bias(conf, profile):
+    if Path("/sys/devices/system/cpu/intel_pstate").exists() is False:
+        print('Not setting EPB (not supported by system)')
+        return
+    epb = "balance_performance" if profile == "charger" else "balance_power"
+    if conf.has_option(profile, "energy_perf_bias"):
+        epb = conf[profile]["energy_perf_bias"]
+
+    run(f"cpufreqctl.auto-cpufreq --epb --set={epb}", shell=True)
+    print(f'Setting to use: "{epb}" EPB')
+
+
 def set_powersave():
     conf = config.get_config()
     gov = conf["battery"]["governor"] if conf.has_option("battery", "governor") else AVAILABLE_GOVERNORS_SORTED[-1]
@@ -531,6 +543,7 @@ def set_powersave():
                 run("cpufreqctl.auto-cpufreq --epp --set=balance_power", shell=True)
                 print('Setting to use: "balance_power" EPP')
 
+    set_energy_perf_bias(conf, "battery")
     set_platform_profile(conf, "battery")
     set_frequencies()
 
@@ -637,7 +650,8 @@ def set_performance():
                 else:
                     run("cpufreqctl.auto-cpufreq --epp --set=balance_performance", shell=True)
                     print('Setting to use: "balance_performance" EPP')
-
+    
+    set_energy_perf_bias(conf, "charger")
     set_platform_profile(conf, "charger")
     set_frequencies()
 
diff --git a/scripts/cpufreqctl.sh b/scripts/cpufreqctl.sh
index 5f493ad2..2b0fb13a 100755
--- a/scripts/cpufreqctl.sh
+++ b/scripts/cpufreqctl.sh
@@ -240,6 +240,58 @@ function set_energy_performance_preference () {
   fi
 }
 
+
+function get_energy_performance_bias () {
+  if [ -z $CORE ]; then
+    i=0
+    ag=''
+    while [ $i -ne $cpucount ]; do
+      if [ $i = 0 ]; then
+        ag=`cat $FLROOT/cpu0/power/energy_perf_bias`
+      else
+        ag=$ag' '`cat $FLROOT/cpu$i/power/energy_perf_bias`
+      fi
+      i=`expr $i + 1`
+    done
+    echo $ag
+  else cat $FLROOT/cpu$CORE/power/energy_perf_bias
+  fi
+}
+
+function set_energy_performance_bias () {
+  if [ `driver` != 'intel_pstate' ]; then
+    verbose "EPB is not supported by a driver other than intel_pstate"
+    return
+  fi
+  local EPB_VALUE=6 # default value
+  if [[ "$VALUE" =~ ^[0-9]+$ && $VALUE -ge 0 && $VALUE -le 15 ]]; then
+    EPB_VALUE=$VALUE
+  else
+    case $VALUE in
+      performance) EPB_VALUE=0;;
+      balance_performance) EPB_VALUE=4;;
+      default) EPB_VALUE=6;;
+      balance_power) EPB_VALUE=8;;
+      power) EPB_VALUE=15;;
+      *)
+        verbose "Invalid value provided for EPB"
+        verbose "Acceptable values: performance|balance-power|default|balance-power|power or a number in the range [0-15]"
+        return
+      ;;
+    esac
+  fi
+
+  if [ -z $CORE ]; then
+    i=0
+    while [ $i -ne $cpucount ]; do
+      FLNM="$FLROOT/cpu"$i"/power/energy_perf_bias"
+      if [ -w $FLNM ]; then echo $EPB_VALUE > $FLNM; fi
+      i=`expr $i + 1`
+    done
+  else echo $EPB_VALUE > $FLROOT/cpu$CORE/power/energy_perf_bias
+  fi
+}
+
 case $OPTION in
   -h|--help) help;;
   --version) echo $VERSION;;
@@ -264,6 +316,16 @@ case $OPTION in
       set_energy_performance_preference
     fi
   ;;
+  --epb)
+    if [ ! -z $AVAILABLE ]; then cat $FLROOT/cpu0/power/energy_perf_bias
+    elif [ -z $VALUE ]; then 
+      verbose "Getting CPU"$CORE" EBPs"
+      get_energy_performance_bias
+    else
+      verbose "Setting CPU"$CORE" EBPs to "$VALUE
+      set_energy_performance_bias
+    fi
+  ;;
   -p|--pp)
     if [ ! -z $AVAILABLE ]; then cat $FWROOT/acpi/platform_profile_choices
     elif [ -z $VALUE ]; then