intel-pstate: Inhibit perf mode when overheating

thermald can disable turbo altogether if needed to avoid reaching
too high operating temperatures, so make the p-state driver monitor
this, and mark the performance mode as inhibited if "no_turbo" is
set.

Closes: #14
This commit is contained in:
Bastien Nocera 2020-09-08 18:09:04 +02:00
parent 82141045e3
commit 95a67713cf
2 changed files with 90 additions and 2 deletions

View file

@ -13,6 +13,7 @@
#include "ppd-driver-intel-pstate.h"
#define CPUFREQ_POLICY_DIR "/devices/system/cpu/cpufreq/"
#define NO_TURBO_PATH "/devices/system/cpu/intel_pstate/no_turbo"
struct _PpdDriverIntelPstate
{
@ -22,6 +23,8 @@ struct _PpdDriverIntelPstate
PpdProfile activated_profile;
gboolean on_battery;
GList *devices; /* GList of paths */
GFileMonitor *no_turbo_mon;
char *no_turbo_path;
};
G_DEFINE_TYPE (PpdDriverIntelPstate, ppd_driver_intel_pstate, PPD_TYPE_DRIVER)
@ -70,6 +73,65 @@ on_battery_changed (GObject *gobject,
pstate->on_battery ? "on battery" : "on mains");
}
static void
update_no_turbo (PpdDriverIntelPstate *pstate)
{
g_autofree char *contents = NULL;
gboolean turbo_disabled = FALSE;
if (g_file_get_contents (pstate->no_turbo_path, &contents, NULL, NULL)) {
if (g_strcmp0 (contents, "1") == 0)
turbo_disabled = TRUE;
}
g_object_set (G_OBJECT (pstate), "performance-inhibited",
turbo_disabled ? "high-operating-temperature" : NULL,
NULL);
}
static void
no_turbo_changed (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer user_data)
{
PpdDriverIntelPstate *pstate = user_data;
g_autofree char *path = NULL;
path = g_file_get_path (file);
g_debug ("File monitor change happened for '%s'", path);
update_no_turbo (pstate);
}
static GFileMonitor *
monitor_no_turbo_prop (const char *path)
{
g_autoptr(GFile) no_turbo = NULL;
if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
g_debug ("Not monitoring '%s' as it does not exist", path);
return NULL;
}
g_debug ("About to start monitoring '%s'", path);
no_turbo = g_file_new_for_path (path);
return g_file_monitor (no_turbo, G_FILE_MONITOR_NONE, NULL, NULL);
}
static char *
get_no_turbo_path (void)
{
const char *root;
g_autofree char *dir = NULL;
root = g_getenv ("UMOCKDEV_DIR");
if (!root || *root == '\0')
root = "/sys";
return g_build_filename (root, NO_TURBO_PATH, NULL);
}
static char *
get_policy_dir (void)
{
@ -119,15 +181,25 @@ ppd_driver_intel_pstate_probe (PpdDriver *driver)
ret = TRUE;
}
if (ret)
pstate->client = up_client_new ();
if (!ret)
goto out;
pstate->client = up_client_new ();
if (pstate->client) {
g_signal_connect (G_OBJECT (pstate->client), "notify::on-battery",
G_CALLBACK (on_battery_changed), pstate);
pstate->on_battery = up_client_get_on_battery (pstate->client);
}
/* Monitor the first "no_turbo" */
pstate->no_turbo_path = get_no_turbo_path ();
pstate->no_turbo_mon = monitor_no_turbo_prop (pstate->no_turbo_path);
if (pstate->no_turbo_mon) {
g_signal_connect (G_OBJECT (pstate->no_turbo_mon), "changed",
G_CALLBACK (no_turbo_changed), pstate);
}
update_no_turbo (pstate);
out:
g_debug ("%s p-state settings",
ret ? "Found" : "Didn't find");
@ -190,6 +262,8 @@ ppd_driver_intel_pstate_finalize (GObject *object)
driver = PPD_DRIVER_INTEL_PSTATE (object);
g_clear_list (&driver->devices, g_free);
g_clear_object (&driver->client);
g_clear_pointer (&driver->no_turbo_path, g_free);
g_clear_object (&driver->no_turbo_mon);
G_OBJECT_CLASS (ppd_driver_intel_pstate_parent_class)->finalize (object);
}

View file

@ -292,6 +292,12 @@ class Tests(dbusmock.DBusTestCase):
with open(os.path.join(dir2, "energy_performance_preference") ,'w') as prefs:
prefs.write("performance")
# Create no_turbo pref
pstate_dir = os.path.join(self.testbed.get_root_dir(), "devices/system/cpu/intel_pstate")
os.makedirs(pstate_dir)
with open(os.path.join(pstate_dir, "no_turbo") ,'w') as no_turbo:
no_turbo.write("0")
self.start_daemon()
profiles = self.get_dbus_property('Profiles')
@ -313,6 +319,14 @@ class Tests(dbusmock.DBusTestCase):
contents = f.read()
self.assertEqual(contents, b'performance')
# Disable turbo
with open(os.path.join(pstate_dir, "no_turbo") ,'w') as no_turbo:
no_turbo.write("1")
self.assertEventually(lambda: self.have_text_in_log('File monitor change happened for '))
self.assertEqual(self.get_dbus_property('ActiveProfile'), 'balanced')
self.assertEqual(self.get_dbus_property('PerformanceInhibited'), 'high-operating-temperature')
self.stop_daemon()
# Verify that the Lenovo DYTC driver still gets preferred