diff --git a/staging/power-profiles-daemon/0001-tests-Split-immutable-control-into-a-test-helper.patch b/staging/power-profiles-daemon/0001-tests-Split-immutable-control-into-a-test-helper.patch new file mode 100644 index 0000000..6176898 --- /dev/null +++ b/staging/power-profiles-daemon/0001-tests-Split-immutable-control-into-a-test-helper.patch @@ -0,0 +1,79 @@ +From f2f910c8642c1c8a42ed23e55852ee0cf5290cef Mon Sep 17 00:00:00 2001 +From: Mario Limonciello +Date: Sun, 17 Dec 2023 08:40:42 -0600 +Subject: [PATCH 1/5] tests: Split immutable control into a test helper + +--- + tests/integration-test.py | 28 ++++++++++++++++------------ + 1 file changed, 16 insertions(+), 12 deletions(-) + +diff --git a/tests/integration-test.py b/tests/integration-test.py +index 8e37f69..549ef94 100755 +--- a/tests/integration-test.py ++++ b/tests/integration-test.py +@@ -247,6 +247,18 @@ class Tests(dbusmock.DBusTestCase): + return f.read() + return None + ++ def change_immutable(self, f, enable): ++ s = '-' ++ if enable: ++ os.chmod(f, 0o444) ++ s = '+' ++ if os.geteuid() == 0: ++ if not GLib.find_program_in_path('chattr'): ++ os._exit(77) ++ subprocess.check_output(['chattr', '%si' % s, f]) ++ if not enable: ++ os.chmod(f, 0o666) ++ + def create_dytc_device(self): + self.tp_acpi = self.testbed.add_device('platform', 'thinkpad_acpi', None, + ['dytc_lapmode', '0\n'], +@@ -491,10 +503,7 @@ class Tests(dbusmock.DBusTestCase): + prefs.write("balance_performance\n") + os.umask(old_umask) + # Make file non-writable to root +- if os.geteuid() == 0: +- if not GLib.find_program_in_path('chattr'): +- os._exit(77) +- subprocess.check_output(['chattr', '+i', pref_path]) ++ self.change_immutable(pref_path, True) + + self.start_daemon() + +@@ -512,8 +521,7 @@ class Tests(dbusmock.DBusTestCase): + + self.stop_daemon() + +- if os.geteuid() == 0: +- subprocess.check_output(['chattr', '-i', pref_path]) ++ self.change_immutable(pref_path, False) + + def test_intel_pstate_passive(self): + '''Intel P-State in passive mode -> placeholder''' +@@ -719,10 +727,7 @@ class Tests(dbusmock.DBusTestCase): + prefs.write("balance_performance\n") + os.umask(old_umask) + # Make file non-writable to root +- if os.geteuid() == 0: +- if not GLib.find_program_in_path('chattr'): +- os._exit(77) +- subprocess.check_output(['chattr', '+i', pref_path]) ++ self.change_immutable(pref_path, True) + + self.start_daemon() + +@@ -740,8 +745,7 @@ class Tests(dbusmock.DBusTestCase): + + self.stop_daemon() + +- if os.geteuid() == 0: +- subprocess.check_output(['chattr', '-i', pref_path]) ++ self.change_immutable(pref_path, False) + + def test_amd_pstate_passive(self): + '''AMD P-State in passive mode -> placeholder''' +-- +2.43.0 + diff --git a/staging/power-profiles-daemon/0002-Allow-both-CPU-and-platform-drivers-to-be-simultaneo.patch b/staging/power-profiles-daemon/0002-Allow-both-CPU-and-platform-drivers-to-be-simultaneo.patch new file mode 100644 index 0000000..a88a046 --- /dev/null +++ b/staging/power-profiles-daemon/0002-Allow-both-CPU-and-platform-drivers-to-be-simultaneo.patch @@ -0,0 +1,1174 @@ +From c985660cf66a9d361ac19da71dc97358e82a7aa7 Mon Sep 17 00:00:00 2001 +From: Mario Limonciello +Date: Sat, 16 Dec 2023 01:24:16 -0600 +Subject: [PATCH 2/5] Allow both CPU and platform drivers to be simultaneously + active + +This is done by designating all drivers as CPU drivers or platform drivers. +One of each driver can be active at any given time. + +When setting an active profile CPU driver is set first as this is less likely to have +failures. If failures occur setting the platform driver then the CPU driver is undone. + +If both profiles are degraded then the string for the reason from both drivers will be +comma separated to be compatible with existing API and users. + +This is leveraged from https://gitlab.freedesktop.org/upower/power-profiles-daemon/-/merge_requests/123 +--- + docs/power-profiles-daemon-docs.xml | 2 + + docs/power-profiles-daemon-sections.txt | 14 ++ + src/meson.build | 2 + + src/power-profiles-daemon.c | 168 +++++++++++++++++------- + src/powerprofilesctl.in | 6 +- + src/ppd-driver-amd-pstate.c | 4 +- + src/ppd-driver-amd-pstate.h | 4 +- + src/ppd-driver-cpu.c | 46 +++++++ + src/ppd-driver-cpu.h | 27 ++++ + src/ppd-driver-fake.c | 4 +- + src/ppd-driver-fake.h | 4 +- + src/ppd-driver-intel-pstate.c | 6 +- + src/ppd-driver-intel-pstate.h | 4 +- + src/ppd-driver-placeholder.c | 4 +- + src/ppd-driver-placeholder.h | 4 +- + src/ppd-driver-platform-profile.c | 2 +- + src/ppd-driver-platform-profile.h | 4 +- + src/ppd-driver-platform.c | 56 ++++++++ + src/ppd-driver-platform.h | 29 ++++ + src/ppd-driver.c | 59 ++++----- + src/ppd-driver.h | 5 +- + tests/integration-test.py | 149 +++++++++++++++++---- + 22 files changed, 473 insertions(+), 130 deletions(-) + create mode 100644 src/ppd-driver-cpu.c + create mode 100644 src/ppd-driver-cpu.h + create mode 100644 src/ppd-driver-platform.c + create mode 100644 src/ppd-driver-platform.h + +diff --git a/docs/power-profiles-daemon-docs.xml b/docs/power-profiles-daemon-docs.xml +index 0a2c627..f2801b5 100644 +--- a/docs/power-profiles-daemon-docs.xml ++++ b/docs/power-profiles-daemon-docs.xml +@@ -70,6 +70,8 @@ + Internal API + + ++ ++ + + + +diff --git a/docs/power-profiles-daemon-sections.txt b/docs/power-profiles-daemon-sections.txt +index 0063310..078578c 100644 +--- a/docs/power-profiles-daemon-sections.txt ++++ b/docs/power-profiles-daemon-sections.txt +@@ -18,6 +18,20 @@ PpdProfileActivationReason + PPD_TYPE_DRIVER + + ++
++ppd-driver-cpu ++CPU Profile Drivers ++PpdDriverCpuClass ++PpdDriverCpu ++
++ ++
++ppd-driver-platform ++Platform Profile Drivers ++PpdDriverPlatformClass ++PpdDriverPlatform ++
++ +
+ ppd-profile + Constants +diff --git a/src/meson.build b/src/meson.build +index 6cf5113..ea4073b 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -19,6 +19,8 @@ sources = [ + 'ppd-utils.c', + 'ppd-action.c', + 'ppd-driver.c', ++ 'ppd-driver-cpu.c', ++ 'ppd-driver-platform.c', + resources, + ] + +diff --git a/src/power-profiles-daemon.c b/src/power-profiles-daemon.c +index 2a3c26b..2599670 100644 +--- a/src/power-profiles-daemon.c ++++ b/src/power-profiles-daemon.c +@@ -15,7 +15,8 @@ + + #include "power-profiles-daemon-resources.h" + #include "power-profiles-daemon.h" +-#include "ppd-driver.h" ++#include "ppd-driver-cpu.h" ++#include "ppd-driver-platform.h" + #include "ppd-action.h" + #include "ppd-enums.h" + +@@ -39,7 +40,8 @@ typedef struct { + PpdProfile active_profile; + PpdProfile selected_profile; + GPtrArray *probed_drivers; +- PpdDriver *driver; ++ PpdDriverCpu *cpu_driver; ++ PpdDriverPlatform *platform_driver; + GPtrArray *actions; + GHashTable *profile_holds; + } PpdApp; +@@ -67,9 +69,6 @@ static PpdApp *ppd_app = NULL; + static void stop_profile_drivers (PpdApp *data); + static void start_profile_drivers (PpdApp *data); + +-#define GET_DRIVER(p) (ppd_driver_get_profiles (data->driver) & p ? data->driver : NULL) +-#define ACTIVE_DRIVER (data->driver) +- + /* profile drivers and actions */ + #include "ppd-action-trickle-charge.h" + #include "ppd-driver-placeholder.h" +@@ -105,14 +104,21 @@ typedef enum { + + #define PROP_ALL (PROP_ACTIVE_PROFILE | PROP_INHIBITED | PROP_PROFILES | PROP_ACTIONS | PROP_DEGRADED | PROP_ACTIVE_PROFILE_HOLDS) + ++static gboolean ++driver_profile_support(PpdDriver *driver, ++ PpdProfile profile) ++{ ++ if (!PPD_IS_DRIVER (driver)) ++ return FALSE; ++ return (ppd_driver_get_profiles (driver) & profile) != 0; ++} ++ + static gboolean + get_profile_available (PpdApp *data, + PpdProfile profile) + { +- PpdDriver *driver; +- +- driver = GET_DRIVER(profile); +- return driver != NULL; ++ return driver_profile_support (PPD_DRIVER(data->cpu_driver), profile) || ++ driver_profile_support (PPD_DRIVER(data->platform_driver), profile); + } + + static const char * +@@ -121,18 +127,22 @@ get_active_profile (PpdApp *data) + return ppd_profile_to_str (data->active_profile); + } + +-static const char * ++static char * + get_performance_degraded (PpdApp *data) + { +- const char *ret; +- PpdDriver *driver; +- +- driver = GET_DRIVER(PPD_PROFILE_PERFORMANCE); +- if (!driver) +- return ""; +- ret = ppd_driver_get_performance_degraded (driver); +- g_assert (ret != NULL); +- return ret; ++ const gchar *cpu_degraded = ""; ++ const gchar *platform_degraded = ""; ++ ++ if (driver_profile_support(PPD_DRIVER(data->platform_driver), PPD_PROFILE_PERFORMANCE)) ++ platform_degraded = ppd_driver_get_performance_degraded (PPD_DRIVER(data->platform_driver)); ++ if (driver_profile_support(PPD_DRIVER(data->cpu_driver), PPD_PROFILE_PERFORMANCE)) ++ cpu_degraded = ppd_driver_get_performance_degraded (PPD_DRIVER(data->cpu_driver)); ++ ++ if (g_strcmp0(cpu_degraded, "") == 0) ++ return g_strdup(platform_degraded); ++ if (g_strcmp0(platform_degraded, "") == 0) ++ return g_strdup(cpu_degraded); ++ return g_strdup_printf("%s,%s", cpu_degraded, platform_degraded); + } + + static GVariant * +@@ -144,17 +154,24 @@ get_profiles_variant (PpdApp *data) + g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}")); + + for (i = 0; i < NUM_PROFILES; i++) { +- PpdDriver *driver = GET_DRIVER(1 << i); ++ PpdDriver *platform_driver = PPD_DRIVER(data->platform_driver); ++ PpdDriver *cpu_driver = PPD_DRIVER(data->cpu_driver); ++ PpdProfile profile = 1 << i; + GVariantBuilder asv_builder; + +- if (driver == NULL) ++ /* check if any of the drivers support */ ++ if (!get_profile_available(data, profile)) + continue; + + g_variant_builder_init (&asv_builder, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_add (&asv_builder, "{sv}", "Profile", +- g_variant_new_string (ppd_profile_to_str (1 << i))); +- g_variant_builder_add (&asv_builder, "{sv}", "Driver", +- g_variant_new_string (ppd_driver_get_driver_name (driver))); ++ g_variant_new_string (ppd_profile_to_str (profile))); ++ if (driver_profile_support(cpu_driver, profile)) ++ g_variant_builder_add (&asv_builder, "{sv}", "CpuDriver", ++ g_variant_new_string (ppd_driver_get_driver_name (cpu_driver))); ++ if (driver_profile_support(PPD_DRIVER(data->platform_driver), profile)) ++ g_variant_builder_add (&asv_builder, "{sv}", "PlatformDriver", ++ g_variant_new_string (ppd_driver_get_driver_name (platform_driver))); + + g_variant_builder_add (&builder, "a{sv}", &asv_builder); + } +@@ -231,8 +248,9 @@ send_dbus_event (PpdApp *data, + g_variant_new_string ("")); + } + if (mask & PROP_DEGRADED) { ++ g_autofree gchar *degraded = get_performance_degraded (data); + g_variant_builder_add (&props_builder, "{sv}", "PerformanceDegraded", +- g_variant_new_string (get_performance_degraded (data))); ++ g_variant_new_string (degraded)); + } + if (mask & PROP_PROFILES) { + g_variant_builder_add (&props_builder, "{sv}", "Profiles", +@@ -264,7 +282,10 @@ save_configuration (PpdApp *data) + { + g_autoptr(GError) error = NULL; + +- g_key_file_set_string (data->config, "State", "Driver", ppd_driver_get_driver_name (data->driver)); ++ if (PPD_IS_DRIVER_CPU(data->cpu_driver)) ++ g_key_file_set_string (data->config, "State", "CpuDriver", ppd_driver_get_driver_name (PPD_DRIVER(data->cpu_driver))); ++ if (PPD_IS_DRIVER_PLATFORM(data->platform_driver)) ++ g_key_file_set_string (data->config, "State", "PlatformDriver", ppd_driver_get_driver_name (PPD_DRIVER(data->platform_driver))); + g_key_file_set_string (data->config, "State", "Profile", ppd_profile_to_str (data->active_profile)); + if (!g_key_file_save_to_file (data->config, data->config_path, &error)) + g_warning ("Could not save configuration file '%s': %s", data->config_path, error->message); +@@ -273,12 +294,16 @@ save_configuration (PpdApp *data) + static gboolean + apply_configuration (PpdApp *data) + { +- g_autofree char *driver = NULL; ++ g_autofree char *platform_driver = NULL; + g_autofree char *profile_str = NULL; ++ g_autofree char *cpu_driver = NULL; + PpdProfile profile; + +- driver = g_key_file_get_string (data->config, "State", "Driver", NULL); +- if (g_strcmp0 (ppd_driver_get_driver_name (data->driver), driver) != 0) ++ cpu_driver = g_key_file_get_string (data->config, "State", "CpuDriver", NULL); ++ if (PPD_IS_DRIVER_CPU(data->cpu_driver) && g_strcmp0 (ppd_driver_get_driver_name (PPD_DRIVER(data->cpu_driver)), cpu_driver) != 0) ++ return FALSE; ++ platform_driver = g_key_file_get_string (data->config, "State", "PlatformDriver", NULL); ++ if (PPD_IS_DRIVER_PLATFORM(data->platform_driver) && g_strcmp0 (ppd_driver_get_driver_name (PPD_DRIVER(data->platform_driver)), platform_driver) != 0) + return FALSE; + profile_str = g_key_file_get_string (data->config, "State", "Profile", NULL); + if (profile_str == NULL) +@@ -339,18 +364,43 @@ activate_target_profile (PpdApp *data, + PpdProfileActivationReason reason, + GError **error) + { +- GError *internal_error = NULL; ++ g_autoptr(GError) recovery_error = NULL; ++ PpdProfile current_profile = data->active_profile; ++ gboolean cpu_set = TRUE; ++ gboolean platform_set = TRUE; + + g_debug ("Setting active profile '%s' for reason '%s' (current: '%s')", + ppd_profile_to_str (target_profile), + ppd_profile_activation_reason_to_str (reason), +- ppd_profile_to_str (data->active_profile)); ++ ppd_profile_to_str (current_profile)); ++ ++ /* Try CPU first */ ++ if (driver_profile_support(PPD_DRIVER(data->cpu_driver), target_profile)) ++ cpu_set = ppd_driver_activate_profile (PPD_DRIVER(data->cpu_driver), target_profile, reason, error); + +- if (!ppd_driver_activate_profile (data->driver, target_profile, reason, &internal_error)) { +- g_warning ("Failed to activate driver '%s': %s", +- ppd_driver_get_driver_name (data->driver), +- internal_error->message); +- g_propagate_error (error, internal_error); ++ if (!cpu_set) { ++ g_prefix_error(error, "Failed to activate CPU driver '%s': ", ppd_driver_get_driver_name (PPD_DRIVER(data->cpu_driver))); ++ return FALSE; ++ } ++ ++ /* Then try platform */ ++ if (driver_profile_support(PPD_DRIVER(data->platform_driver), target_profile)) ++ platform_set = ppd_driver_activate_profile (PPD_DRIVER(data->platform_driver), target_profile, reason, error); ++ ++ if (!platform_set) { ++ g_prefix_error(error, "Failed to activate platform driver '%s': ", ppd_driver_get_driver_name (PPD_DRIVER(data->platform_driver))); ++ /* try to recover */ ++ if (cpu_set) { ++ g_debug ("Reverting CPU driver '%s' to profile '%s'", ++ ppd_driver_get_driver_name (PPD_DRIVER(data->cpu_driver)), ++ ppd_profile_to_str (current_profile)); ++ if (!ppd_driver_activate_profile (PPD_DRIVER(data->cpu_driver), current_profile, PPD_PROFILE_ACTIVATION_REASON_INTERNAL, &recovery_error)) { ++ g_prefix_error(error, "Failed to revert CPU driver '%s': ", ppd_driver_get_driver_name (PPD_DRIVER(data->cpu_driver))); ++ g_warning ("Failed to revert CPU driver '%s': %s", ++ ppd_driver_get_driver_name (PPD_DRIVER(data->cpu_driver)), ++ recovery_error->message); ++ } ++ } + return FALSE; + } + +@@ -676,8 +726,10 @@ handle_get_property (GDBusConnection *connection, + return get_profiles_variant (data); + if (g_strcmp0 (property_name, "Actions") == 0) + return get_actions_variant (data); +- if (g_strcmp0 (property_name, "PerformanceDegraded") == 0) +- return g_variant_new_string (get_performance_degraded (data)); ++ if (g_strcmp0 (property_name, "PerformanceDegraded") == 0) { ++ g_autofree gchar *degraded = get_performance_degraded (data); ++ return g_variant_new_string (degraded); ++ } + if (g_strcmp0 (property_name, "ActiveProfileHolds") == 0) + return get_profile_holds_variant (data); + return NULL; +@@ -789,13 +841,11 @@ bus_acquired_handler (GDBusConnection *connection, + static gboolean + has_required_drivers (PpdApp *data) + { +- PpdDriver *driver; +- +- driver = GET_DRIVER (PPD_PROFILE_BALANCED); +- if (!driver || !G_IS_OBJECT (driver)) ++ if (!PPD_IS_DRIVER_CPU(data->cpu_driver) && ++ !PPD_IS_DRIVER_PLATFORM(data->platform_driver)) + return FALSE; +- driver = GET_DRIVER (PPD_PROFILE_POWER_SAVER); +- if (!driver || !G_IS_OBJECT (driver)) ++ ++ if (!get_profile_available(data, PPD_PROFILE_BALANCED | PPD_PROFILE_POWER_SAVER)) + return FALSE; + + return TRUE; +@@ -817,13 +867,15 @@ stop_profile_drivers (PpdApp *data) + release_all_profile_holds (data); + g_ptr_array_set_size (data->probed_drivers, 0); + g_ptr_array_set_size (data->actions, 0); +- g_clear_object (&data->driver); ++ g_clear_object (&data->cpu_driver); ++ g_clear_object (&data->platform_driver); + } + + static void + start_profile_drivers (PpdApp *data) + { + guint i; ++ g_autoptr(GError) initial_error = NULL; + + for (i = 0; i < G_N_ELEMENTS (objects); i++) { + GObject *object; +@@ -836,9 +888,16 @@ start_profile_drivers (PpdApp *data) + + g_debug ("Handling driver '%s'", ppd_driver_get_driver_name (driver)); + +- if (data->driver != NULL) { +- g_debug ("Driver '%s' already probed, skipping driver '%s'", +- ppd_driver_get_driver_name (data->driver), ++ if (PPD_IS_DRIVER_CPU(data->cpu_driver) && PPD_IS_DRIVER_CPU(driver)) { ++ g_debug ("CPU driver '%s' already probed, skipping driver '%s'", ++ ppd_driver_get_driver_name (PPD_DRIVER(data->cpu_driver)), ++ ppd_driver_get_driver_name (driver)); ++ continue; ++ } ++ ++ if (PPD_IS_DRIVER_PLATFORM(data->platform_driver) && PPD_IS_DRIVER_PLATFORM(driver)) { ++ g_debug ("Platform driver '%s' already probed, skipping driver '%s'", ++ ppd_driver_get_driver_name (PPD_DRIVER(data->platform_driver)), + ppd_driver_get_driver_name (driver)); + continue; + } +@@ -865,7 +924,12 @@ start_profile_drivers (PpdApp *data) + continue; + } + +- data->driver = driver; ++ if (PPD_IS_DRIVER_CPU(driver)) ++ data->cpu_driver = PPD_DRIVER_CPU(driver); ++ else if (PPD_IS_DRIVER_PLATFORM(driver)) ++ data->platform_driver = PPD_DRIVER_PLATFORM(driver); ++ else ++ g_assert_not_reached (); + + g_signal_connect (G_OBJECT (driver), "notify::performance-degraded", + G_CALLBACK (driver_performance_degraded_changed_cb), data); +@@ -896,7 +960,8 @@ start_profile_drivers (PpdApp *data) + + /* Set initial state either from configuration, or using the currently selected profile */ + apply_configuration (data); +- activate_target_profile (data, data->active_profile, PPD_PROFILE_ACTIVATION_REASON_RESET, NULL); ++ if (!activate_target_profile (data, data->active_profile, PPD_PROFILE_ACTIVATION_REASON_RESET, &initial_error)) ++ g_warning("Failed to activate initial profile: %s", initial_error->message); + + send_dbus_event (data, PROP_ALL); + +@@ -972,7 +1037,8 @@ free_app_data (PpdApp *data) + g_clear_pointer (&data->config, g_key_file_unref); + g_ptr_array_free (data->probed_drivers, TRUE); + g_ptr_array_free (data->actions, TRUE); +- g_clear_object (&data->driver); ++ g_clear_object (&data->cpu_driver); ++ g_clear_object (&data->platform_driver); + g_hash_table_destroy (data->profile_holds); + + g_clear_object (&data->auth); +diff --git a/src/powerprofilesctl.in b/src/powerprofilesctl.in +index b1ea675..6197709 100755 +--- a/src/powerprofilesctl.in ++++ b/src/powerprofilesctl.in +@@ -144,7 +144,11 @@ def _list(): + print('') + marker = '*' if profile['Profile'] == active else ' ' + print(f'{marker} {profile["Profile"]}:') +- print(' Driver: ', profile['Driver']) ++ for driver in ['CpuDriver', 'PlatformDriver']: ++ if driver not in profile: ++ continue ++ value = profile[driver] ++ print(f' {driver}:\t{value}') + if profile['Profile'] == 'performance': + print(' Degraded: ', f'yes ({reason})' if degraded else 'no') + index += 1 +diff --git a/src/ppd-driver-amd-pstate.c b/src/ppd-driver-amd-pstate.c +index 825caca..b0e4fa3 100644 +--- a/src/ppd-driver-amd-pstate.c ++++ b/src/ppd-driver-amd-pstate.c +@@ -19,13 +19,13 @@ + + struct _PpdDriverAmdPstate + { +- PpdDriver parent_instance; ++ PpdDriverCpu parent_instance; + + PpdProfile activated_profile; + GList *epp_devices; /* GList of paths */ + }; + +-G_DEFINE_TYPE (PpdDriverAmdPstate, ppd_driver_amd_pstate, PPD_TYPE_DRIVER) ++G_DEFINE_TYPE (PpdDriverAmdPstate, ppd_driver_amd_pstate, PPD_TYPE_DRIVER_CPU) + + static gboolean ppd_driver_amd_pstate_activate_profile (PpdDriver *driver, + PpdProfile profile, +diff --git a/src/ppd-driver-amd-pstate.h b/src/ppd-driver-amd-pstate.h +index c4f1690..926483b 100644 +--- a/src/ppd-driver-amd-pstate.h ++++ b/src/ppd-driver-amd-pstate.h +@@ -10,7 +10,7 @@ + + #pragma once + +-#include "ppd-driver.h" ++#include "ppd-driver-cpu.h" + + #define PPD_TYPE_DRIVER_AMD_PSTATE (ppd_driver_amd_pstate_get_type()) +-G_DECLARE_FINAL_TYPE(PpdDriverAmdPstate, ppd_driver_amd_pstate, PPD, DRIVER_AMD_PSTATE, PpdDriver) ++G_DECLARE_FINAL_TYPE(PpdDriverAmdPstate, ppd_driver_amd_pstate, PPD, DRIVER_AMD_PSTATE, PpdDriverCpu) +diff --git a/src/ppd-driver-cpu.c b/src/ppd-driver-cpu.c +new file mode 100644 +index 0000000..7982465 +--- /dev/null ++++ b/src/ppd-driver-cpu.c +@@ -0,0 +1,46 @@ ++/* ++ * Copyright (c) 2023 Mario Limonciello ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 3 as published by ++ * the Free Software Foundation. ++ * ++ */ ++ ++#include "ppd-driver-cpu.h" ++ ++/** ++ * SECTION:ppd-driver-cpu ++ * @Short_description: CPU Drivers ++ * @Title: CPU Profile Drivers ++ * ++ * Profile drivers are the implementation of the different profiles for ++ * the whole system. A driver will need to implement support `power-saver` ++ * and `balanced` at a minimum. ++ * ++ * CPU drivers are typically used to change specifically the CPU efficiency ++ * to match the desired platform state. ++ */ ++ ++G_DEFINE_TYPE (PpdDriverCpu, ppd_driver_cpu, PPD_TYPE_DRIVER) ++ ++static void ++ppd_driver_cpu_finalize (GObject *object) ++{ ++ G_OBJECT_CLASS (ppd_driver_cpu_parent_class)->finalize (object); ++} ++ ++static void ++ppd_driver_cpu_class_init (PpdDriverCpuClass *klass) ++{ ++ GObjectClass *object_class; ++ ++ object_class = G_OBJECT_CLASS(klass); ++ object_class->finalize = ppd_driver_cpu_finalize; ++} ++ ++static void ++ppd_driver_cpu_init (PpdDriverCpu *self) ++{ ++} ++ +diff --git a/src/ppd-driver-cpu.h b/src/ppd-driver-cpu.h +new file mode 100644 +index 0000000..dde1026 +--- /dev/null ++++ b/src/ppd-driver-cpu.h +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (c) 2023 Mario Limonciello ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 3 as published by ++ * the Free Software Foundation. ++ * ++ */ ++ ++#pragma once ++ ++#include "ppd-driver.h" ++ ++#define PPD_TYPE_DRIVER_CPU (ppd_driver_cpu_get_type()) ++G_DECLARE_DERIVABLE_TYPE(PpdDriverCpu, ppd_driver_cpu, PPD, DRIVER_CPU, PpdDriver) ++ ++/** ++ * PpdDriverCpuClass: ++ * @parent_class: The parent class. ++ * ++ * New CPU drivers should derive from #PpdDriverCpu and implement ++ * both @probe() and @activate_profile. ++ */ ++struct _PpdDriverCpuClass ++{ ++ PpdDriverClass parent_class; ++}; +diff --git a/src/ppd-driver-fake.c b/src/ppd-driver-fake.c +index ecd6154..30a03fc 100644 +--- a/src/ppd-driver-fake.c ++++ b/src/ppd-driver-fake.c +@@ -18,7 +18,7 @@ void restart_profile_drivers (void); + + struct _PpdDriverFake + { +- PpdDriver parent_instance; ++ PpdDriverCpu parent_instance; + + gboolean tio_set; + struct termios old_tio; +@@ -27,7 +27,7 @@ struct _PpdDriverFake + gboolean degraded; + }; + +-G_DEFINE_TYPE (PpdDriverFake, ppd_driver_fake, PPD_TYPE_DRIVER) ++G_DEFINE_TYPE (PpdDriverFake, ppd_driver_fake, PPD_TYPE_DRIVER_CPU) + + static GObject* + ppd_driver_fake_constructor (GType type, +diff --git a/src/ppd-driver-fake.h b/src/ppd-driver-fake.h +index 6ab2f82..49a2c2b 100644 +--- a/src/ppd-driver-fake.h ++++ b/src/ppd-driver-fake.h +@@ -9,7 +9,7 @@ + + #pragma once + +-#include "ppd-driver.h" ++#include "ppd-driver-cpu.h" + + #define PPD_TYPE_DRIVER_FAKE (ppd_driver_fake_get_type()) +-G_DECLARE_FINAL_TYPE(PpdDriverFake, ppd_driver_fake, PPD, DRIVER_FAKE, PpdDriver) ++G_DECLARE_FINAL_TYPE(PpdDriverFake, ppd_driver_fake, PPD, DRIVER_FAKE, PpdDriverCpu) +diff --git a/src/ppd-driver-intel-pstate.c b/src/ppd-driver-intel-pstate.c +index 912850a..3307ee4 100644 +--- a/src/ppd-driver-intel-pstate.c ++++ b/src/ppd-driver-intel-pstate.c +@@ -25,7 +25,7 @@ + + struct _PpdDriverIntelPstate + { +- PpdDriver parent_instance; ++ PpdDriverCpu parent_instance; + + PpdProfile activated_profile; + GList *epp_devices; /* GList of paths */ +@@ -35,7 +35,7 @@ struct _PpdDriverIntelPstate + char *no_turbo_path; + }; + +-G_DEFINE_TYPE (PpdDriverIntelPstate, ppd_driver_intel_pstate, PPD_TYPE_DRIVER) ++G_DEFINE_TYPE (PpdDriverIntelPstate, ppd_driver_intel_pstate, PPD_TYPE_DRIVER_CPU) + + static gboolean ppd_driver_intel_pstate_activate_profile (PpdDriver *driver, + PpdProfile profile, +@@ -143,7 +143,7 @@ logind_proxy_signal_cb (GDBusProxy *proxy, + return; + + g_debug ("System woke up from suspend, re-applying energy_perf_bias"); +- ret = ppd_driver_intel_pstate_activate_profile (PPD_DRIVER (pstate), ++ ret = ppd_driver_intel_pstate_activate_profile (PPD_DRIVER(pstate), + pstate->activated_profile, + PPD_PROFILE_ACTIVATION_REASON_RESUME, + &error); +diff --git a/src/ppd-driver-intel-pstate.h b/src/ppd-driver-intel-pstate.h +index 42f8cf2..10ad645 100644 +--- a/src/ppd-driver-intel-pstate.h ++++ b/src/ppd-driver-intel-pstate.h +@@ -9,7 +9,7 @@ + + #pragma once + +-#include "ppd-driver.h" ++#include "ppd-driver-cpu.h" + + #define PPD_TYPE_DRIVER_INTEL_PSTATE (ppd_driver_intel_pstate_get_type()) +-G_DECLARE_FINAL_TYPE(PpdDriverIntelPstate, ppd_driver_intel_pstate, PPD, DRIVER_INTEL_PSTATE, PpdDriver) ++G_DECLARE_FINAL_TYPE(PpdDriverIntelPstate, ppd_driver_intel_pstate, PPD, DRIVER_INTEL_PSTATE, PpdDriverCpu) +diff --git a/src/ppd-driver-placeholder.c b/src/ppd-driver-placeholder.c +index 11d9e93..58c75d1 100644 +--- a/src/ppd-driver-placeholder.c ++++ b/src/ppd-driver-placeholder.c +@@ -11,10 +11,10 @@ + + struct _PpdDriverPlaceholder + { +- PpdDriver parent_instance; ++ PpdDriverPlatform parent_instance; + }; + +-G_DEFINE_TYPE (PpdDriverPlaceholder, ppd_driver_placeholder, PPD_TYPE_DRIVER) ++G_DEFINE_TYPE (PpdDriverPlaceholder, ppd_driver_placeholder, PPD_TYPE_DRIVER_PLATFORM) + + static GObject* + ppd_driver_placeholder_constructor (GType type, +diff --git a/src/ppd-driver-placeholder.h b/src/ppd-driver-placeholder.h +index a822790..f18ea01 100644 +--- a/src/ppd-driver-placeholder.h ++++ b/src/ppd-driver-placeholder.h +@@ -9,7 +9,7 @@ + + #pragma once + +-#include "ppd-driver.h" ++#include "ppd-driver-platform.h" + + #define PPD_TYPE_DRIVER_PLACEHOLDER (ppd_driver_placeholder_get_type()) +-G_DECLARE_FINAL_TYPE(PpdDriverPlaceholder, ppd_driver_placeholder, PPD, DRIVER_PLACEHOLDER, PpdDriver) ++G_DECLARE_FINAL_TYPE(PpdDriverPlaceholder, ppd_driver_placeholder, PPD, DRIVER_PLACEHOLDER, PpdDriverPlatform) +diff --git a/src/ppd-driver-platform-profile.c b/src/ppd-driver-platform-profile.c +index aebc655..f90da57 100644 +--- a/src/ppd-driver-platform-profile.c ++++ b/src/ppd-driver-platform-profile.c +@@ -32,7 +32,7 @@ struct _PpdDriverPlatformProfile + guint acpi_platform_profile_changed_id; + }; + +-G_DEFINE_TYPE (PpdDriverPlatformProfile, ppd_driver_platform_profile, PPD_TYPE_DRIVER) ++G_DEFINE_TYPE (PpdDriverPlatformProfile, ppd_driver_platform_profile, PPD_TYPE_DRIVER_PLATFORM) + + static GObject* + ppd_driver_platform_profile_constructor (GType type, +diff --git a/src/ppd-driver-platform-profile.h b/src/ppd-driver-platform-profile.h +index 916fd7e..320f9c7 100644 +--- a/src/ppd-driver-platform-profile.h ++++ b/src/ppd-driver-platform-profile.h +@@ -9,7 +9,7 @@ + + #pragma once + +-#include "ppd-driver.h" ++#include "ppd-driver-platform.h" + + #define PPD_TYPE_DRIVER_PLATFORM_PROFILE (ppd_driver_platform_profile_get_type()) +-G_DECLARE_FINAL_TYPE(PpdDriverPlatformProfile, ppd_driver_platform_profile, PPD, DRIVER_PLATFORM_PROFILE, PpdDriver) ++G_DECLARE_FINAL_TYPE(PpdDriverPlatformProfile, ppd_driver_platform_profile, PPD, DRIVER_PLATFORM_PROFILE, PpdDriverPlatform) +diff --git a/src/ppd-driver-platform.c b/src/ppd-driver-platform.c +new file mode 100644 +index 0000000..66668b9 +--- /dev/null ++++ b/src/ppd-driver-platform.c +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (c) 2023 Mario Limonciello ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 3 as published by ++ * the Free Software Foundation. ++ * ++ */ ++ ++#include "ppd-driver-platform.h" ++ ++G_DEFINE_TYPE (PpdDriverPlatform, ppd_driver_platform, PPD_TYPE_DRIVER) ++ ++/** ++ * SECTION:ppd-driver-platform ++ * @Short_description: Profile Drivers ++ * @Title: Platform Profile Drivers ++ * ++ * Profile drivers are the implementation of the different profiles for ++ * the whole system. A driver will need to implement support `power-saver` ++ * and `balanced` at a minimum. ++ * ++ * If no system-specific platform driver is available, a placeholder driver ++ * will be put in place, and the `performance` profile will be unavailable. ++ * ++ * There should not be a need to implement system-specific drivers, as the ++ * [`platform_profile`](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/ABI/testing/sysfs-platform_profile) ++ * kernel API offers a way to implement system-specific profiles which ++ * `power-profiles-daemon` can consume. ++ * ++ * When a driver implements the `performance` profile, it might set the ++ * #PpdDriver:performance-degraded property if the profile isn't running to ++ * its fullest performance for any reason, such as thermal limits being ++ * reached, or because a part of the user's body is too close for safety, ++ * for example. ++ */ ++ ++static void ++ppd_driver_platform_finalize (GObject *object) ++{ ++ G_OBJECT_CLASS (ppd_driver_platform_parent_class)->finalize (object); ++} ++ ++static void ++ppd_driver_platform_class_init (PpdDriverPlatformClass *klass) ++{ ++ GObjectClass *object_class; ++ ++ object_class = G_OBJECT_CLASS(klass); ++ object_class->finalize = ppd_driver_platform_finalize; ++} ++ ++static void ++ppd_driver_platform_init (PpdDriverPlatform *self) ++{ ++} +\ No newline at end of file +diff --git a/src/ppd-driver-platform.h b/src/ppd-driver-platform.h +new file mode 100644 +index 0000000..123c255 +--- /dev/null ++++ b/src/ppd-driver-platform.h +@@ -0,0 +1,29 @@ ++/* ++ * Copyright (c) 2023 Mario Limonciello ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 3 as published by ++ * the Free Software Foundation. ++ * ++ */ ++ ++#pragma once ++ ++#include "ppd-driver.h" ++ ++#define PPD_TYPE_DRIVER_PLATFORM (ppd_driver_platform_get_type()) ++G_DECLARE_DERIVABLE_TYPE(PpdDriverPlatform, ppd_driver_platform, PPD, DRIVER_PLATFORM, PpdDriver) ++ ++/** ++ * PpdDriverPlatformClass: ++ * @parent_class: The parent class. ++ * ++ * New Platform drivers should derive from #PpdDriverPlatform and implement ++ * at least one of @probe() and @activate_profile. ++ */ ++struct _PpdDriverPlatformClass ++{ ++ PpdDriverClass parent_class; ++}; ++ ++ +diff --git a/src/ppd-driver.c b/src/ppd-driver.c +index 9a1f369..db9e335 100644 +--- a/src/ppd-driver.c ++++ b/src/ppd-driver.c +@@ -19,13 +19,7 @@ + * the whole system. A driver will need to implement support `power-saver` + * and `balanced` at a minimum. + * +- * If no system-specific driver is available, a placeholder driver +- * will be put in place, and the `performance` profile will be unavailable. +- * +- * There should not be a need to implement system-specific drivers, as the +- * [`platform_profile`](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/ABI/testing/sysfs-platform_profile) +- * kernel API offers a way to implement system-specific profiles which +- * `power-profiles-daemon` can consume. ++ * All drivers should be derived from either #PpdDriverCpu or #PpdDriverPlatform + * + * When a driver implements the `performance` profile, it might set the + * #PpdDriver:performance-degraded property if the profile isn't running to +@@ -117,7 +111,6 @@ ppd_driver_finalize (GObject *object) + + priv = PPD_DRIVER_GET_PRIVATE (PPD_DRIVER (object)); + g_clear_pointer (&priv->driver_name, g_free); +- g_clear_pointer (&priv->performance_degraded, g_free); + + G_OBJECT_CLASS (ppd_driver_parent_class)->finalize (object); + } +@@ -191,9 +184,8 @@ ppd_driver_class_init (PpdDriverClass *klass) + PPD_TYPE_PROFILE, + 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +- + /** +- * PpdDriver:performance-degraded: ++ * PpdPlatformDriver:performance-degraded: + * + * If set to a non-%NULL value, the reason why the performance profile is unavailable. + * The value must be one of the options listed in the D-Bus API reference. +@@ -204,6 +196,7 @@ ppd_driver_class_init (PpdDriverClass *klass) + "Why the performance profile is degraded, if set", + NULL, + G_PARAM_READWRITE)); ++ + } + + static void +@@ -270,29 +263,6 @@ ppd_driver_get_selected (PpdDriver *driver) + return priv->selected; + } + +-const char * +-ppd_driver_get_performance_degraded (PpdDriver *driver) +-{ +- PpdDriverPrivate *priv; +- +- g_return_val_if_fail (PPD_IS_DRIVER (driver), NULL); +- +- priv = PPD_DRIVER_GET_PRIVATE (driver); +- return priv->performance_degraded ? priv->performance_degraded : ""; +-} +- +-gboolean +-ppd_driver_is_performance_degraded (PpdDriver *driver) +-{ +- PpdDriverPrivate *priv; +- +- g_return_val_if_fail (PPD_IS_DRIVER (driver), FALSE); +- +- priv = PPD_DRIVER_GET_PRIVATE (driver); +- +- return (priv->performance_degraded != NULL); +-} +- + void + ppd_driver_emit_profile_changed (PpdDriver *driver, + PpdProfile profile) +@@ -323,3 +293,26 @@ ppd_profile_activation_reason_to_str (PpdProfileActivationReason reason) + g_assert_not_reached (); + } + } ++ ++const char * ++ppd_driver_get_performance_degraded (PpdDriver *driver) ++{ ++ PpdDriverPrivate *priv; ++ ++ g_return_val_if_fail (PPD_IS_DRIVER (driver), NULL); ++ ++ priv = PPD_DRIVER_GET_PRIVATE (driver); ++ return priv->performance_degraded ? priv->performance_degraded : ""; ++} ++ ++gboolean ++ppd_driver_is_performance_degraded (PpdDriver *driver) ++{ ++ PpdDriverPrivate *priv; ++ ++ g_return_val_if_fail (PPD_IS_DRIVER (driver), FALSE); ++ ++ priv = PPD_DRIVER_GET_PRIVATE (driver); ++ ++ return (priv->performance_degraded != NULL); ++} +diff --git a/src/ppd-driver.h b/src/ppd-driver.h +index f1e0f63..f05fbb6 100644 +--- a/src/ppd-driver.h ++++ b/src/ppd-driver.h +@@ -64,8 +64,9 @@ typedef enum{ + * @probe: Called by the daemon on startup. + * @activate_profile: Called by the daemon for every profile change. + * +- * New profile drivers should derive from #PpdDriver and implement +- * at least one of probe() and @activate_profile. ++ * New profile drivers should not derive from #PpdDriver. They should ++ * derive from the child from #PpdDriverCpu or #PpdDriverPlatform drivers ++ * and implement at least one of probe() and @activate_profile. + */ + struct _PpdDriverClass + { +diff --git a/tests/integration-test.py b/tests/integration-test.py +index 549ef94..68d50ae 100755 +--- a/tests/integration-test.py ++++ b/tests/integration-test.py +@@ -324,8 +324,8 @@ class Tests(dbusmock.DBusTestCase): + + profiles = self.get_dbus_property('Profiles') + self.assertEqual(len(profiles), 2) +- self.assertEqual(profiles[1]['Driver'], 'placeholder') +- self.assertEqual(profiles[0]['Driver'], 'placeholder') ++ self.assertEqual(profiles[1]['PlatformDriver'], 'placeholder') ++ self.assertEqual(profiles[0]['PlatformDriver'], 'placeholder') + self.assertEqual(profiles[1]['Profile'], 'balanced') + self.assertEqual(profiles[0]['Profile'], 'power-saver') + +@@ -355,6 +355,45 @@ class Tests(dbusmock.DBusTestCase): + self.assertEqual(len(profiles), 3) + self.assertEqual(self.get_dbus_property('PerformanceInhibited'), '') + ++ def test_multi_degredation(self): ++ '''Test handling of degradation from multiple drivers''' ++ self.create_dytc_device() ++ self.create_platform_profile() ++ ++ # Create CPU with preference ++ dir1 = os.path.join(self.testbed.get_root_dir(), "sys/devices/system/cpu/cpufreq/policy0/") ++ os.makedirs(dir1) ++ with open(os.path.join(dir1, 'scaling_governor'), 'w') as gov: ++ gov.write('powersave\n') ++ with open(os.path.join(dir1, "energy_performance_preference"),'w') as prefs: ++ prefs.write("performance\n") ++ ++ # Create Intel P-State configuration ++ pstate_dir = os.path.join(self.testbed.get_root_dir(), "sys/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\n") ++ with open(os.path.join(pstate_dir, "status"),'w') as status: ++ status.write("active\n") ++ ++ self.start_daemon() ++ ++ # Set performance mode ++ self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('performance')) ++ self.assertEqual(self.get_dbus_property('ActiveProfile'), 'performance') ++ ++ # Degraded CPU ++ with open(os.path.join(pstate_dir, "no_turbo"),'w') as no_turbo: ++ no_turbo.write("1\n") ++ self.assertEventually(lambda: self.have_text_in_log('File monitor change happened for ')) ++ ++ self.assertEqual(self.get_dbus_property('PerformanceDegraded'), 'high-operating-temperature') ++ ++ # Degraded DYTC ++ self.testbed.set_attribute(self.tp_acpi, 'dytc_lapmode', '1\n') ++ self.assertEventually(lambda: self.have_text_in_log('dytc_lapmode is now on')) ++ self.assertEqual(self.get_dbus_property('PerformanceDegraded'), 'high-operating-temperature,lap-detected') ++ + def test_degraded_transition(self): + '''Test that transitions work as expected when degraded''' + +@@ -408,7 +447,7 @@ class Tests(dbusmock.DBusTestCase): + + profiles = self.get_dbus_property('Profiles') + self.assertEqual(len(profiles), 3) +- self.assertEqual(profiles[0]['Driver'], 'intel_pstate') ++ self.assertEqual(profiles[0]['CpuDriver'], 'intel_pstate') + self.assertEqual(profiles[0]['Profile'], 'power-saver') + + contents = None +@@ -435,13 +474,14 @@ class Tests(dbusmock.DBusTestCase): + + self.stop_daemon() + +- # Verify that the Lenovo DYTC driver still gets preferred ++ # Verify that Lenovo DYTC and Intel P-State drivers are loaded + self.create_platform_profile() + self.start_daemon() + + profiles = self.get_dbus_property('Profiles') + self.assertEqual(len(profiles), 3) +- self.assertEqual(profiles[0]['Driver'], 'platform_profile') ++ self.assertEqual(profiles[0]['CpuDriver'], 'intel_pstate') ++ self.assertEqual(profiles[0]['PlatformDriver'], 'platform_profile') + + def test_intel_pstate_balance(self): + '''Intel P-State driver (balance)''' +@@ -470,7 +510,7 @@ class Tests(dbusmock.DBusTestCase): + + profiles = self.get_dbus_property('Profiles') + self.assertEqual(len(profiles), 3) +- self.assertEqual(profiles[0]['Driver'], 'intel_pstate') ++ self.assertEqual(profiles[0]['CpuDriver'], 'intel_pstate') + self.assertEqual(profiles[0]['Profile'], 'power-saver') + + contents = None +@@ -545,7 +585,7 @@ class Tests(dbusmock.DBusTestCase): + + profiles = self.get_dbus_property('Profiles') + self.assertEqual(len(profiles), 2) +- self.assertEqual(profiles[0]['Driver'], 'placeholder') ++ self.assertEqual(profiles[0]['PlatformDriver'], 'placeholder') + self.assertEqual(self.get_dbus_property('ActiveProfile'), 'balanced') + + contents = None +@@ -590,7 +630,7 @@ class Tests(dbusmock.DBusTestCase): + + profiles = self.get_dbus_property('Profiles') + self.assertEqual(len(profiles), 3) +- self.assertEqual(profiles[0]['Driver'], 'intel_pstate') ++ self.assertEqual(profiles[0]['CpuDriver'], 'intel_pstate') + self.assertEqual(self.get_dbus_property('ActiveProfile'), 'balanced') + + # Set power-saver mode +@@ -613,6 +653,77 @@ class Tests(dbusmock.DBusTestCase): + + self.stop_daemon() + ++ def test_multi_driver_flows(self): ++ '''Test corner cases associated with multiple drivers''' ++ ++ # Create 2 CPUs with preferences ++ dir1 = os.path.join(self.testbed.get_root_dir(), "sys/devices/system/cpu/cpufreq/policy0/") ++ os.makedirs(dir1) ++ with open(os.path.join(dir1, 'scaling_governor'), 'w') as f: ++ f.write('powersave\n') ++ prefs1 = os.path.join(dir1, "energy_performance_preference") ++ with open(prefs1,'w') as f: ++ f.write("performance\n") ++ ++ dir2 = os.path.join(self.testbed.get_root_dir(), "sys/devices/system/cpu/cpufreq/policy1/") ++ os.makedirs(dir2) ++ with open(os.path.join(dir2, 'scaling_governor'), 'w') as f: ++ f.write('powersave\n') ++ prefs2 = os.path.join(dir2, "energy_performance_preference") ++ with open(prefs2,'w') as f: ++ f.write("performance\n") ++ ++ # Create AMD P-State configuration ++ pstate_dir = os.path.join(self.testbed.get_root_dir(), "sys/devices/system/cpu/amd_pstate") ++ os.makedirs(pstate_dir) ++ with open(os.path.join(pstate_dir, "status"),'w') as status: ++ status.write("active\n") ++ ++ # create ACPI platform profile ++ self.create_platform_profile() ++ profile = os.path.join(self.testbed.get_root_dir(), "sys/firmware/acpi/platform_profile") ++ ++ self.start_daemon() ++ ++ # Verify that both drivers are loaded ++ profiles = self.get_dbus_property('Profiles') ++ self.assertEqual(len(profiles), 3) ++ self.assertEqual(profiles[0]['CpuDriver'], 'amd_pstate') ++ self.assertEqual(profiles[0]['PlatformDriver'], 'platform_profile') ++ ++ # test both drivers can switch to power-saver ++ self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('power-saver')) ++ self.assertEqual(self.get_dbus_property('ActiveProfile'), 'power-saver') ++ ++ # test both drivers can switch to performance ++ self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('performance')) ++ self.assertEqual(self.get_dbus_property('ActiveProfile'), 'performance') ++ ++ # test both drivers can switch to balanced ++ self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('balanced')) ++ self.assertEqual(self.get_dbus_property('ActiveProfile'), 'balanced') ++ ++ # test when CPU driver fails to write ++ self.change_immutable(prefs1, True) ++ with self.assertRaises(gi.repository.GLib.GError): ++ self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('power-saver')) ++ self.assertEqual(self.get_dbus_property('ActiveProfile'), 'balanced') ++ self.assertEqual(self.read_sysfs_file("sys/firmware/acpi/platform_profile"), b'balanced') ++ self.change_immutable(prefs1, False) ++ ++ # test when platform driver fails to write ++ self.change_immutable(profile, True) ++ with self.assertRaises(gi.repository.GLib.GError): ++ self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('power-saver')) ++ self.assertEqual(self.get_dbus_property('ActiveProfile'), 'balanced') ++ ++ # make sure CPU was undone since platform failed ++ self.assertEqual(self.read_sysfs_file("sys/devices/system/cpu/cpufreq/policy0/energy_performance_preference"), b'balance_performance') ++ self.assertEqual(self.read_sysfs_file("sys/devices/system/cpu/cpufreq/policy1/energy_performance_preference"), b'balance_performance') ++ self.change_immutable(profile, False) ++ ++ self.stop_daemon() ++ + def test_amd_pstate(self): + '''AMD P-State driver (no UPower)''' + +@@ -640,7 +751,7 @@ class Tests(dbusmock.DBusTestCase): + + profiles = self.get_dbus_property('Profiles') + self.assertEqual(len(profiles), 3) +- self.assertEqual(profiles[0]['Driver'], 'amd_pstate') ++ self.assertEqual(profiles[0]['CpuDriver'], 'amd_pstate') + self.assertEqual(profiles[0]['Profile'], 'power-saver') + + contents = None +@@ -659,14 +770,6 @@ class Tests(dbusmock.DBusTestCase): + + self.stop_daemon() + +- # Verify that the Lenovo DYTC driver still gets preferred +- self.create_platform_profile() +- self.start_daemon() +- +- profiles = self.get_dbus_property('Profiles') +- self.assertEqual(len(profiles), 3) +- self.assertEqual(profiles[0]['Driver'], 'platform_profile') +- + def test_amd_pstate_balance(self): + '''AMD P-State driver (balance)''' + +@@ -694,7 +797,7 @@ class Tests(dbusmock.DBusTestCase): + + profiles = self.get_dbus_property('Profiles') + self.assertEqual(len(profiles), 3) +- self.assertEqual(profiles[0]['Driver'], 'amd_pstate') ++ self.assertEqual(profiles[0]['CpuDriver'], 'amd_pstate') + self.assertEqual(profiles[0]['Profile'], 'power-saver') + + contents = None +@@ -767,7 +870,7 @@ class Tests(dbusmock.DBusTestCase): + + profiles = self.get_dbus_property('Profiles') + self.assertEqual(len(profiles), 2) +- self.assertEqual(profiles[0]['Driver'], 'placeholder') ++ self.assertEqual(profiles[0]['PlatformDriver'], 'placeholder') + self.assertEqual(self.get_dbus_property('ActiveProfile'), 'balanced') + + contents = None +@@ -795,9 +898,9 @@ class Tests(dbusmock.DBusTestCase): + + profiles = self.get_dbus_property('Profiles') + self.assertEqual(len(profiles), 3) +- self.assertEqual(profiles[0]['Driver'], 'platform_profile') ++ self.assertEqual(profiles[0]['PlatformDriver'], 'platform_profile') + self.assertEqual(profiles[0]['Profile'], 'power-saver') +- self.assertEqual(profiles[2]['Driver'], 'platform_profile') ++ self.assertEqual(profiles[2]['PlatformDriver'], 'platform_profile') + self.assertEqual(profiles[2]['Profile'], 'performance') + self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('performance')) + self.assertEqual(self.get_dbus_property('ActiveProfile'), 'performance') +@@ -938,7 +1041,7 @@ class Tests(dbusmock.DBusTestCase): + self.start_daemon() + profiles = self.get_dbus_property('Profiles') + self.assertEqual(len(profiles), 3) +- self.assertEqual(profiles[0]['Driver'], 'platform_profile') ++ self.assertEqual(profiles[0]['PlatformDriver'], 'platform_profile') + self.assertEqual(profiles[0]['Profile'], 'power-saver') + self.assertEqual(self.get_dbus_property('ActiveProfile'), 'balanced') + self.assertEqual(self.read_sysfs_file("sys/firmware/acpi/platform_profile"), b'cool') +@@ -964,7 +1067,7 @@ class Tests(dbusmock.DBusTestCase): + self.start_daemon() + profiles = self.get_dbus_property('Profiles') + self.assertEqual(len(profiles), 3) +- self.assertEqual(profiles[0]['Driver'], 'platform_profile') ++ self.assertEqual(profiles[0]['PlatformDriver'], 'platform_profile') + self.assertEqual(profiles[0]['Profile'], 'power-saver') + self.assertEqual(self.get_dbus_property('ActiveProfile'), 'balanced') + self.assertEqual(self.read_sysfs_file("sys/firmware/acpi/platform_profile"), b'balanced') +-- +2.43.0 + diff --git a/staging/power-profiles-daemon/0003-Update-integration-test-to-be-compatible-with-pm-pro.patch b/staging/power-profiles-daemon/0003-Update-integration-test-to-be-compatible-with-pm-pro.patch new file mode 100644 index 0000000..f13922e --- /dev/null +++ b/staging/power-profiles-daemon/0003-Update-integration-test-to-be-compatible-with-pm-pro.patch @@ -0,0 +1,31 @@ +From 0086cd7a5bd2391d97871274da21514f2602edcd Mon Sep 17 00:00:00 2001 +From: Mario Limonciello +Date: Thu, 21 Dec 2023 07:01:54 -0600 +Subject: [PATCH 3/5] Update integration test to be compatible with pm profile + check + +This is needed for compatbility with https://gitlab.freedesktop.org/upower/power-profiles-daemon/-/merge_requests/128 +--- + tests/integration-test.py | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/tests/integration-test.py b/tests/integration-test.py +index 68d50ae..1eb13ae 100755 +--- a/tests/integration-test.py ++++ b/tests/integration-test.py +@@ -683,6 +683,12 @@ class Tests(dbusmock.DBusTestCase): + self.create_platform_profile() + profile = os.path.join(self.testbed.get_root_dir(), "sys/firmware/acpi/platform_profile") + ++ # desktop PM profile ++ dir3 = os.path.join(self.testbed.get_root_dir(), "sys/firmware/acpi/") ++ os.makedirs(dir3, exist_ok=True) ++ with open(os.path.join(dir3, "pm_profile"), 'w') as pm_profile: ++ pm_profile.write("1\n") ++ + self.start_daemon() + + # Verify that both drivers are loaded +-- +2.43.0 + diff --git a/staging/power-profiles-daemon/0004-Disable-loading-amd-pstate-when-the-PM-profile-is-a-.patch b/staging/power-profiles-daemon/0004-Disable-loading-amd-pstate-when-the-PM-profile-is-a-.patch new file mode 100644 index 0000000..f96d006 --- /dev/null +++ b/staging/power-profiles-daemon/0004-Disable-loading-amd-pstate-when-the-PM-profile-is-a-.patch @@ -0,0 +1,185 @@ +From 8705e70422a4c5970547b5c079b2ac693973fb4b Mon Sep 17 00:00:00 2001 +From: Mario Limonciello +Date: Tue, 19 Dec 2023 20:05:13 -0600 +Subject: [PATCH 4/5] Disable loading amd-pstate when the PM profile is a + server or undefined + +This mirrors the behavior used by Kernel 6.5 and later where amd-pstate +is configured to default into 'performance' by the kernel. It's not +as useful in server to be changing it. + +Link: https://github.com/torvalds/linux/commit/32f80b9adfdb43f8af248596724f59dde938a190 +--- + src/ppd-driver-amd-pstate.c | 33 ++++++++++++++++++++ + tests/integration-test.py | 62 ++++++++++++++++++++++++++++++++++++- + 2 files changed, 94 insertions(+), 1 deletion(-) + +diff --git a/src/ppd-driver-amd-pstate.c b/src/ppd-driver-amd-pstate.c +index b0e4fa3..e1056a8 100644 +--- a/src/ppd-driver-amd-pstate.c ++++ b/src/ppd-driver-amd-pstate.c +@@ -16,6 +16,20 @@ + #define CPUFREQ_POLICY_DIR "/sys/devices/system/cpu/cpufreq/" + #define DEFAULT_CPU_FREQ_SCALING_GOV "powersave" + #define PSTATE_STATUS_PATH "/sys/devices/system/cpu/amd_pstate/status" ++#define ACPI_PM_PROFILE "/sys/firmware/acpi/pm_profile" ++ ++enum acpi_preferred_pm_profiles { ++ PM_UNSPECIFIED = 0, ++ PM_DESKTOP = 1, ++ PM_MOBILE = 2, ++ PM_WORKSTATION = 3, ++ PM_ENTERPRISE_SERVER = 4, ++ PM_SOHO_SERVER = 5, ++ PM_APPLIANCE_PC = 6, ++ PM_PERFORMANCE_SERVER = 7, ++ PM_TABLET = 8, ++ NR_PM_PROFILES = 9 ++}; + + struct _PpdDriverAmdPstate + { +@@ -57,6 +71,9 @@ probe_epp (PpdDriverAmdPstate *pstate) + g_autofree char *policy_dir = NULL; + g_autofree char *pstate_status_path = NULL; + g_autofree char *status = NULL; ++ g_autofree char *pm_profile_path = NULL; ++ g_autofree char *pm_profile_str = NULL; ++ guint64 pm_profile; + const char *dirname; + PpdProbeResult ret = PPD_PROBE_RESULT_FAIL; + +@@ -77,6 +94,22 @@ probe_epp (PpdDriverAmdPstate *pstate) + return ret; + } + ++ /* only run on things that we know aren't servers */ ++ pm_profile_path = ppd_utils_get_sysfs_path (ACPI_PM_PROFILE); ++ if (!g_file_get_contents (pm_profile_path, &pm_profile_str, NULL, NULL)) ++ return ret; ++ pm_profile = g_ascii_strtoull(pm_profile_str, NULL, 10); ++ switch (pm_profile) { ++ case PM_UNSPECIFIED: ++ case PM_ENTERPRISE_SERVER: ++ case PM_SOHO_SERVER: ++ case PM_PERFORMANCE_SERVER: ++ g_debug ("AMD-P-State not supported on PM profile %" G_GUINT64_FORMAT, pm_profile); ++ return ret; ++ default: ++ break; ++ } ++ + while ((dirname = g_dir_read_name (dir)) != NULL) { + g_autofree char *path = NULL; + g_autofree char *gov_path = NULL; +diff --git a/tests/integration-test.py b/tests/integration-test.py +index 1eb13ae..11bcbc2 100755 +--- a/tests/integration-test.py ++++ b/tests/integration-test.py +@@ -275,7 +275,7 @@ class Tests(dbusmock.DBusTestCase): + + def create_platform_profile(self): + acpi_dir = os.path.join(self.testbed.get_root_dir(), "sys/firmware/acpi/") +- os.makedirs(acpi_dir) ++ os.makedirs(acpi_dir, exist_ok=True) + with open(os.path.join(acpi_dir, "platform_profile"),'w') as profile: + profile.write("performance\n") + with open(os.path.join(acpi_dir, "platform_profile_choices"),'w') as choices: +@@ -753,6 +753,12 @@ class Tests(dbusmock.DBusTestCase): + with open(os.path.join(pstate_dir, "status"),'w') as status: + status.write("active\n") + ++ # desktop PM profile ++ dir3 = os.path.join(self.testbed.get_root_dir(), "sys/firmware/acpi/") ++ os.makedirs(dir3) ++ with open(os.path.join(dir3, "pm_profile"), 'w') as pm_profile: ++ pm_profile.write("1\n") ++ + self.start_daemon() + + profiles = self.get_dbus_property('Profiles') +@@ -792,6 +798,12 @@ class Tests(dbusmock.DBusTestCase): + with open(os.path.join(pstate_dir, "status"),'w') as status: + status.write("active\n") + ++ # desktop PM profile ++ dir2 = os.path.join(self.testbed.get_root_dir(), "sys/firmware/acpi/") ++ os.makedirs(dir2) ++ with open(os.path.join(dir2, "pm_profile"), 'w') as pm_profile: ++ pm_profile.write("1\n") ++ + upowerd, obj_upower = self.spawn_server_template( + 'upower', {'DaemonVersion': '0.99', 'OnBattery': False}, stdout=subprocess.PIPE) + +@@ -838,6 +850,12 @@ class Tests(dbusmock.DBusTestCase): + # Make file non-writable to root + self.change_immutable(pref_path, True) + ++ # desktop PM profile ++ dir2 = os.path.join(self.testbed.get_root_dir(), "sys/firmware/acpi/") ++ os.makedirs(dir2) ++ with open(os.path.join(dir2, "pm_profile"), 'w') as pm_profile: ++ pm_profile.write("1\n") ++ + self.start_daemon() + + self.assertEqual(self.get_dbus_property('ActiveProfile'), 'balanced') +@@ -872,6 +890,12 @@ class Tests(dbusmock.DBusTestCase): + with open(os.path.join(pstate_dir, "status"),'w') as status: + status.write("passive\n") + ++ # desktop PM profile ++ dir2 = os.path.join(self.testbed.get_root_dir(), "sys/firmware/acpi/") ++ os.makedirs(dir2) ++ with open(os.path.join(dir2, "pm_profile"), 'w') as pm_profile: ++ pm_profile.write("1\n") ++ + self.start_daemon() + + profiles = self.get_dbus_property('Profiles') +@@ -895,6 +919,42 @@ class Tests(dbusmock.DBusTestCase): + + self.stop_daemon() + ++ def test_amd_pstate_server(self): ++ # Create 2 CPUs with preferences ++ dir1 = os.path.join(self.testbed.get_root_dir(), "sys/devices/system/cpu/cpufreq/policy0/") ++ os.makedirs(dir1) ++ with open(os.path.join(dir1, 'scaling_governor'), 'w') as gov: ++ gov.write('powersave\n') ++ with open(os.path.join(dir1, "energy_performance_preference"),'w') as prefs: ++ prefs.write("performance\n") ++ dir2 = os.path.join(self.testbed.get_root_dir(), "sys/devices/system/cpu/cpufreq/policy1/") ++ os.makedirs(dir2) ++ with open(os.path.join(dir2, 'scaling_governor'), 'w') as gov: ++ gov.write('powersave\n') ++ with open(os.path.join(dir2, "energy_performance_preference"),'w') as prefs: ++ prefs.write("performance\n") ++ ++ # Create AMD P-State configuration ++ pstate_dir = os.path.join(self.testbed.get_root_dir(), "sys/devices/system/cpu/amd_pstate") ++ os.makedirs(pstate_dir) ++ with open(os.path.join(pstate_dir, "status"),'w') as status: ++ status.write("active\n") ++ ++ # server PM profile ++ dir3 = os.path.join(self.testbed.get_root_dir(), "sys/firmware/acpi/") ++ os.makedirs(dir3) ++ with open(os.path.join(dir3, "pm_profile"), 'w') as pm_profile: ++ pm_profile.write("4\n") ++ ++ self.start_daemon() ++ ++ profiles = self.get_dbus_property('Profiles') ++ self.assertEqual(len(profiles), 2) ++ with self.assertRaises(KeyError): ++ print(profiles[0]['CpuDriver']) ++ ++ self.stop_daemon() ++ + def test_dytc_performance_driver(self): + '''Lenovo DYTC performance driver''' + +-- +2.43.0 + diff --git a/staging/power-profiles-daemon/0005-Don-t-change-governor-for-amd-pstate-at-probe.patch b/staging/power-profiles-daemon/0005-Don-t-change-governor-for-amd-pstate-at-probe.patch new file mode 100644 index 0000000..d6c0bda --- /dev/null +++ b/staging/power-profiles-daemon/0005-Don-t-change-governor-for-amd-pstate-at-probe.patch @@ -0,0 +1,213 @@ +From 48efb3af1fa6467b208dde7389c998dc28abee54 Mon Sep 17 00:00:00 2001 +From: Mario Limonciello +Date: Thu, 21 Dec 2023 07:18:22 -0600 +Subject: [PATCH 5/5] Don't change governor for amd-pstate at probe + +Make the change specifically when changing modes and only set powersave +for balance and powersaver profiles. +--- + src/ppd-driver-amd-pstate.c | 68 +++++++++++++++++++++++++------------ + tests/integration-test.py | 31 +++++++++++++---- + 2 files changed, 71 insertions(+), 28 deletions(-) + +diff --git a/src/ppd-driver-amd-pstate.c b/src/ppd-driver-amd-pstate.c +index e1056a8..e48fa69 100644 +--- a/src/ppd-driver-amd-pstate.c ++++ b/src/ppd-driver-amd-pstate.c +@@ -14,7 +14,6 @@ + #include "ppd-driver-amd-pstate.h" + + #define CPUFREQ_POLICY_DIR "/sys/devices/system/cpu/cpufreq/" +-#define DEFAULT_CPU_FREQ_SCALING_GOV "powersave" + #define PSTATE_STATUS_PATH "/sys/devices/system/cpu/amd_pstate/status" + #define ACPI_PM_PROFILE "/sys/firmware/acpi/pm_profile" + +@@ -111,28 +110,21 @@ probe_epp (PpdDriverAmdPstate *pstate) + } + + while ((dirname = g_dir_read_name (dir)) != NULL) { ++ g_autofree char *base = NULL; + g_autofree char *path = NULL; +- g_autofree char *gov_path = NULL; + g_autoptr(GError) error = NULL; + +- path = g_build_filename (policy_dir, ++ base = g_build_filename (policy_dir, + dirname, ++ NULL); ++ ++ path = g_build_filename (base, + "energy_performance_preference", + NULL); + if (!g_file_test (path, G_FILE_TEST_EXISTS)) + continue; + +- /* Force a scaling_governor where the preference can be written */ +- gov_path = g_build_filename (policy_dir, +- dirname, +- "scaling_governor", +- NULL); +- if (!ppd_utils_write (gov_path, DEFAULT_CPU_FREQ_SCALING_GOV, &error)) { +- g_warning ("Could not change scaling governor %s to '%s'", dirname, DEFAULT_CPU_FREQ_SCALING_GOV); +- continue; +- } +- +- pstate->epp_devices = g_list_prepend (pstate->epp_devices, g_steal_pointer (&path)); ++ pstate->epp_devices = g_list_prepend (pstate->epp_devices, g_steal_pointer (&base)); + ret = PPD_PROBE_RESULT_SUCCESS; + } + +@@ -156,6 +148,21 @@ out: + return ret; + } + ++static const char * ++profile_to_gov_pref (PpdProfile profile) ++{ ++ switch (profile) { ++ case PPD_PROFILE_POWER_SAVER: ++ return "powersave"; ++ case PPD_PROFILE_BALANCED: ++ return "powersave"; ++ case PPD_PROFILE_PERFORMANCE: ++ return "performance"; ++ } ++ ++ g_assert_not_reached (); ++} ++ + static const char * + profile_to_epp_pref (PpdProfile profile) + { +@@ -175,16 +182,30 @@ profile_to_epp_pref (PpdProfile profile) + + static gboolean + apply_pref_to_devices (GList *devices, +- const char *pref, ++ PpdProfile profile, + GError **error) + { + gboolean ret = TRUE; + GList *l; + + for (l = devices; l != NULL; l = l->next) { +- const char *path = l->data; ++ const char *base = l->data; ++ g_autofree char *epp = NULL; ++ g_autofree char *gov = NULL; ++ ++ gov = g_build_filename (base, ++ "scaling_governor", ++ NULL); + +- ret = ppd_utils_write (path, pref, error); ++ ret = ppd_utils_write (gov, profile_to_gov_pref(profile), error); ++ if (!ret) ++ break; ++ ++ epp = g_build_filename (base, ++ "energy_performance_preference", ++ NULL); ++ ++ ret = ppd_utils_write (epp, profile_to_epp_pref(profile), error); + if (!ret) + break; + } +@@ -200,15 +221,20 @@ ppd_driver_amd_pstate_activate_profile (PpdDriver *driver, + { + PpdDriverAmdPstate *pstate = PPD_DRIVER_AMD_PSTATE (driver); + gboolean ret = FALSE; +- const char *pref; + + g_return_val_if_fail (pstate->epp_devices != NULL, FALSE); + + if (pstate->epp_devices) { +- pref = profile_to_epp_pref (profile); +- ret = apply_pref_to_devices (pstate->epp_devices, pref, error); +- if (!ret) ++ ret = apply_pref_to_devices (pstate->epp_devices, profile, error); ++ if (!ret && pstate->activated_profile != PPD_PROFILE_UNSET) { ++ g_autoptr(GError) error_local = NULL; ++ /* reset back to previous */ ++ if (!apply_pref_to_devices (pstate->epp_devices, ++ pstate->activated_profile, ++ &error_local)) ++ g_warning("failed to restore previous profile: %s", error_local->message); + return ret; ++ } + } + + if (ret) +diff --git a/tests/integration-test.py b/tests/integration-test.py +index 11bcbc2..383b8b3 100755 +--- a/tests/integration-test.py ++++ b/tests/integration-test.py +@@ -770,6 +770,9 @@ class Tests(dbusmock.DBusTestCase): + with open(os.path.join(dir2, "energy_performance_preference"), 'rb') as f: + contents = f.read() + self.assertEqual(contents, b'balance_performance') ++ with open(os.path.join(dir2, "scaling_governor"), 'rb') as f: ++ contents = f.read() ++ self.assertEqual(contents, b'performance') + + # Set performance mode + self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('performance')) +@@ -779,6 +782,23 @@ class Tests(dbusmock.DBusTestCase): + with open(os.path.join(dir2, "energy_performance_preference"), 'rb') as f: + contents = f.read() + self.assertEqual(contents, b'performance') ++ contents = None ++ with open(os.path.join(dir2, "scaling_governor"), 'rb') as f: ++ contents = f.read() ++ self.assertEqual(contents, b'performance') ++ ++ # Set powersave mode ++ self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('power-saver')) ++ self.assertEqual(self.get_dbus_property('ActiveProfile'), 'power-saver') ++ ++ contents = None ++ with open(os.path.join(dir2, "energy_performance_preference"), 'rb') as f: ++ contents = f.read() ++ self.assertEqual(contents, b'power') ++ contents = None ++ with open(os.path.join(dir2, "scaling_governor"), 'rb') as f: ++ contents = f.read() ++ self.assertEqual(contents, b'powersave') + + self.stop_daemon() + +@@ -788,9 +808,6 @@ class Tests(dbusmock.DBusTestCase): + # Create CPU with preference + dir1 = os.path.join(self.testbed.get_root_dir(), "sys/devices/system/cpu/cpufreq/policy0/") + os.makedirs(dir1) +- gov_path = os.path.join(dir1, 'scaling_governor') +- with open(gov_path, 'w') as gov: +- gov.write('performance\n') + with open(os.path.join(dir1, "energy_performance_preference"),'w') as prefs: + prefs.write("performance\n") + pstate_dir = os.path.join(self.testbed.get_root_dir(), "sys/devices/system/cpu/amd_pstate") +@@ -809,10 +826,6 @@ class Tests(dbusmock.DBusTestCase): + + self.start_daemon() + +- with open(gov_path, 'rb') as f: +- contents = f.read() +- self.assertEqual(contents, b'powersave') +- + profiles = self.get_dbus_property('Profiles') + self.assertEqual(len(profiles), 3) + self.assertEqual(profiles[0]['CpuDriver'], 'amd_pstate') +@@ -823,6 +836,10 @@ class Tests(dbusmock.DBusTestCase): + contents = f.read() + # This matches what's written by ppd-driver-amd-pstate.c + self.assertEqual(contents, b'balance_performance') ++ contents = None ++ with open(os.path.join(dir1, "scaling_governor"), 'rb') as f: ++ contents = f.read() ++ self.assertEqual(contents, b'performance') + + self.stop_daemon() + +-- +2.43.0 + diff --git a/staging/power-profiles-daemon/power-profiles-daemon.spec b/staging/power-profiles-daemon/power-profiles-daemon.spec index 8870be5..eee61b0 100644 --- a/staging/power-profiles-daemon/power-profiles-daemon.spec +++ b/staging/power-profiles-daemon/power-profiles-daemon.spec @@ -1,14 +1,17 @@ Name: power-profiles-daemon Version: 0.13 -Release: 2%{?dist}.ublue +Release: 6%{?dist}.ublue Summary: Makes power profiles handling available over D-Bus -License: GPLv3+ +License: GPL-3.0-or-later URL: https://gitlab.freedesktop.org/hadess/power-profiles-daemon Source0: https://gitlab.freedesktop.org/hadess/power-profiles-daemon/uploads/1f2ea40547b2af8d255875d7085211e5/power-profiles-daemon-0.13.tar.xz +Patch1: 0001-tests-Split-immutable-control-into-a-test-helper.patch +Patch2: 0002-Allow-both-CPU-and-platform-drivers-to-be-simultaneo.patch +Patch3: 0003-Update-integration-test-to-be-compatible-with-pm-pro.patch +Patch4: 0004-Disable-loading-amd-pstate-when-the-PM-profile-is-a-.patch +Patch5: 0005-Don-t-change-governor-for-amd-pstate-at-probe.patch -# https://gitlab.freedesktop.org/upower/power-profiles-daemon/-/merge_requests/127 -Patch0: 127.patch BuildRequires: meson BuildRequires: gcc @@ -35,7 +38,8 @@ BuildArch: noarch This package contains the documentation for %{name}. %prep -%autosetup -p1 +%autosetup -N +%autopatch -p1 %build %meson -Dgtk_doc=true @@ -81,73 +85,4 @@ fi %{_datadir}/gtk-doc/html/%{name}/ %changelog -* Fri Jul 21 2023 Fedora Release Engineering - 0.13-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild - -* Wed Apr 26 2023 Bastien Nocera - 0.13-1 -- Update to 0.13 - -* Fri Jan 20 2023 Fedora Release Engineering - 0.12-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild - -* Fri Jul 22 2022 Fedora Release Engineering - 0.12-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild - -* Tue Jun 28 2022 Bastien Nocera - 0.12-1 -+ power-profiles-daemon-0.12-1 -- Update to 0.12 - -* Mon May 02 2022 Bastien Nocera - 0.11.1-1 -+ power-profiles-daemon-0.11.1-1 -- Update to 0.11.1 - -* Fri Apr 29 2022 Bastien Nocera - 0.11-1 -+ power-profiles-daemon-0.11-1 -- Update to 0.11 - -* Fri Jan 21 2022 Fedora Release Engineering - 0.10.1-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild - -* Fri Nov 05 2021 Kalev Lember - 0.10.1-2 -- Apply power-profiles-daemon.service preset on upgrades to F35 and F36 - -* Thu Oct 28 2021 Bastien Nocera - 0.10.1-1 -- power-profiles-daemon-0.10.1-1 -- Update to 0.10.1 - -* Mon Oct 04 2021 Bastien Nocera - 0.10.0-1 -+ power-profiles-daemon-0.10.0-1 -- Update to 0.10.0 - -* Fri Jul 23 2021 Fedora Release Engineering - 0.9.0-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild - -* Tue Jul 20 2021 Bastien Nocera - 0.9.0-1 -+ power-profiles-daemon-0.9.0-1 -- Update to 0.9.0 - -* Wed Apr 14 2021 Bastien Nocera - 0.8.1-2 -+ power-profiles-daemon-0.8.1-2 -- Remove linter, as apparently unwanted in check section - -* Thu Apr 01 2021 Bastien Nocera - 0.8.1-1 -+ power-profiles-daemon-0.8.1-1 -- Update to 0.8.1 - -* Mon Mar 22 2021 Bastien Nocera - 0.8-1 -+ power-profiles-daemon-0.8-1 -- Update to 0.8 - -* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek - 0.1-4 -- Rebuilt for updated systemd-rpm-macros - See https://pagure.io/fesco/issue/2583. - -* Wed Jan 27 2021 Fedora Release Engineering - 0.1-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild - -* Wed Oct 28 2020 Bastien Nocera - 0.1-2 -+ power-profiles-daemon-0.1-2 -- Reload presets when updating from an older version - -* Fri Aug 07 2020 Bastien Nocera - 0.1-1 -- Initial package +%autochangelog