[neon/backports-jammy/power-profiles-daemon/Neon/unstable] /: 0.13-1 (patches unapplied)
git-ubuntu importer
null at kde.org
Tue Sep 24 23:21:42 BST 2024
Git commit 0b8e1b8a54d2e92f02361b2a1b8dea174e189a93 by git-ubuntu importer, on behalf of Sebastien Bacher.
Committed on 06/06/2023 at 16:32.
Pushed by carlosdem into branch 'Neon/unstable'.
0.13-1 (patches unapplied)
Imported using git-ubuntu import.
M +5 -0 .gitlab-ci.yml
M +7 -0 NEWS
M +29 -0 README.md
M +13 -0 debian/changelog
M +0 -4 debian/control
D +0 -42 debian/patches/build_older_polkit.patch
M +0 -1 debian/patches/series
A +1 -0 debian/power-profiles-daemon.maintscript
M +1 -0 docs/meson.build
M +1 -1 meson.build
M +1 -0 src/meson.build
M +24 -1 src/power-profiles-daemon.c
M +23 -24 src/powerprofilesctl.in
A +215 -0 src/ppd-driver-amd-pstate.c [License: GPL (v3)]
A +16 -0 src/ppd-driver-amd-pstate.h [License: GPL (v3)]
M +0 -1 src/ppd-driver-intel-pstate.c
M +22 -9 src/ppd-driver-platform-profile.c
M +1 -0 src/ppd-utils.c
M +191 -3 tests/integration-test.py
https://invent.kde.org/neon/backports-jammy/power-profiles-daemon/-/commit/0b8e1b8a54d2e92f02361b2a1b8dea174e189a93
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 714a85c..ddec8d0 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -18,6 +18,11 @@ variables:
umockdev
e2fsprogs
+workflow:
+ rules:
+ - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
+ - if: $CI_PIPELINE_SOURCE == 'push'
+
build_stable:
before_script:
- dnf upgrade -y --nogpgcheck fedora-release fedora-repos*
diff --git a/NEWS b/NEWS
index 8b75a65..59ce68c 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,10 @@
+0.13
+----
+
+This release adds support for the AMD P-State driver that's been added to the
+6.3 Linux kernel. This release also fixes mismatched profiles on some HP
+laptops and some miscellaneous bug fixes.
+
0.12
----
diff --git a/README.md b/README.md
index 1093b19..8ab25a3 100644
--- a/README.md
+++ b/README.md
@@ -134,6 +134,35 @@ ie. the only P-State scaling governor that allows HWP to work.
For more information, please refer to the [Intel P-State scaling driver documentation](https://www.kernel.org/doc/html/v5.17/admin-guide/pm/intel_pstate.html)
and the [Intel Performance and Energy Bias Hint](https://www.kernel.org/doc/html/v5.17/admin-guide/pm/intel_epb.html).
+Operations on AMD-based machines
+----------------------------------
+
+The "driver" for making the hardware act on the user-selected power profile on AMD CPU-based
+machines is based on the [AMD P-State scaling driver](https://www.kernel.org/doc/html/v6.3/admin-guide/pm/amd-pstate.html)
+if available.
+
+It is only used if a `platform_profile` driver isn't available for the system, the
+CPU supports Collaborative Processor Performance Control (CPPC), and the AMD P-State
+scaling driver is in `active` mode.
+
+Example of a system without `platform_profile` support but with `active` P-State
+operation mode:
+```
+$ cat /sys/firmware/acpi/platform_profile_choices
+cat: /sys/firmware/acpi/platform_profile_choices: No such file or directory
+$ cat /sys/devices/system/cpu/amd_pstate/status
+active
+```
+
+If the AMD P-State scaling driver is not loaded or is not in `active` mode, then
+the placeholder driver will be used, and there won't be a performance mode.
+
+Finally, if the AMD P-State scaling driver is used in `active` mode, the P-State
+scaling governor will be changed to `powersave` as it is the only P-State scaling
+governor that allows for the "Energy vs Performance Hints" to be taken into consideration.
+
+For more information, please refer to the [AMD P-State scaling driver documentation](https://www.kernel.org/doc/html/v6.3/admin-guide/pm/amd-pstate.html).
+
Testing
-------
diff --git a/debian/changelog b/debian/changelog
index 534c710..0499c58 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,16 @@
+power-profiles-daemon (0.13-1) experimental; urgency=medium
+
+ * New upstream version (lp: #2022945)
+ - adds support for the AMD P-State driver that's been added to the
+ 6.3 Linux kernel
+ * debian/patches/build_older_polkit.patch:
+ - removed, it's not needed anymore now that Debian updated to a
+ recent polkit version
+ * debian/power-profiles-daemon.maintscript:
+ - remove obsolete conffile (Closes: #1021746)
+
+ -- Sebastien Bacher <seb128 at ubuntu.com> Tue, 06 Jun 2023 13:36:10 +0200
+
power-profiles-daemon (0.12-1) unstable; urgency=medium
* Team upload
diff --git a/debian/control b/debian/control
index b90929d..561ffb1 100644
--- a/debian/control
+++ b/debian/control
@@ -37,7 +37,3 @@ Description: Makes power profiles handling available over D-Bus.
"actions" can be hooked up to change the behaviour of a particular device.
For example, this can be used to disable the fast-charging for some USB
devices when in power-saver mode.
- .
- Note that power-profiles-daemon does not save the currently active
- profile across system restarts and will always start with the "balanced"
- profile selected.
diff --git a/debian/patches/build_older_polkit.patch b/debian/patches/build_older_polkit.patch
deleted file mode 100644
index b05b5ae..0000000
--- a/debian/patches/build_older_polkit.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-Index: power-profiles-daemon/src/power-profiles-daemon.c
-===================================================================
---- power-profiles-daemon.orig/src/power-profiles-daemon.c
-+++ power-profiles-daemon/src/power-profiles-daemon.c
-@@ -103,6 +103,13 @@ typedef enum {
-
- #define PROP_ALL (PROP_ACTIVE_PROFILE | PROP_INHIBITED | PROP_PROFILES | PROP_ACTIONS | PROP_DEGRADED | PROP_ACTIVE_PROFILE_HOLDS)
-
-+/* This uses a weird Auto prefix to avoid conflicts with later added polkit types. */
-+typedef PolkitAuthorizationResult AutoPolkitAuthorizationResult;
-+typedef PolkitSubject AutoPolkitSubject;
-+
-+G_DEFINE_AUTOPTR_CLEANUP_FUNC (AutoPolkitAuthorizationResult, g_object_unref)
-+G_DEFINE_AUTOPTR_CLEANUP_FUNC (AutoPolkitSubject, g_object_unref)
-+
- static const char *
- get_active_profile (PpdApp *data)
- {
-@@ -609,8 +616,8 @@ check_action_permission (PpdApp
- GError **error)
- {
- g_autoptr(GError) local_error = NULL;
-- g_autoptr(PolkitAuthorizationResult) result = NULL;
-- g_autoptr(PolkitSubject) subject = NULL;
-+ g_autoptr(AutoPolkitAuthorizationResult) result = NULL;
-+ g_autoptr(AutoPolkitSubject) subject = NULL;
-
- subject = polkit_system_bus_name_new (sender);
- result = polkit_authority_check_authorization_sync (data->auth,
-Index: power-profiles-daemon/meson.build
-===================================================================
---- power-profiles-daemon.orig/meson.build
-+++ power-profiles-daemon/meson.build
-@@ -34,7 +34,7 @@ endif
- gio_dep = dependency('gio-2.0')
- gudev_dep = dependency('gudev-1.0', version: '>= 234')
- upower_dep = dependency('upower-glib')
--polkit_gobject_dep = dependency('polkit-gobject-1', version: '>= 0.114')
-+polkit_gobject_dep = dependency('polkit-gobject-1', version: '>= 0.91')
- polkit_policy_directory = polkit_gobject_dep.get_pkgconfig_variable('policydir')
-
- gnome = import('gnome')
diff --git a/debian/patches/series b/debian/patches/series
index 8675d1b..a0d0401 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,2 +1 @@
-build_older_polkit.patch
remove_tlp_conflict.patch
diff --git a/debian/power-profiles-daemon.maintscript b/debian/power-profiles-daemon.maintscript
new file mode 100644
index 0000000..06ed2fc
--- /dev/null
+++ b/debian/power-profiles-daemon.maintscript
@@ -0,0 +1 @@
+rm_conffile /etc/dbus-1/system.d/net.hadess.PowerProfiles.conf 0.13-1~
diff --git a/docs/meson.build b/docs/meson.build
index 489658b..4de0210 100644
--- a/docs/meson.build
+++ b/docs/meson.build
@@ -24,6 +24,7 @@ private_headers = [
'ppd-driver-balanced.h',
'ppd-driver-fake.h',
'ppd-driver-intel-pstate.h',
+ 'ppd-driver-amd-pstate.h',
'ppd-driver-placeholder.h',
'ppd-driver-platform-profile.h',
'ppd-driver-power-saver.h',
diff --git a/meson.build b/meson.build
index 7f31046..47e982b 100644
--- a/meson.build
+++ b/meson.build
@@ -1,5 +1,5 @@
project('power-profiles-daemon', [ 'c' ],
- version: '0.12',
+ version: '0.13',
license: 'GPLv3+',
default_options: [
'buildtype=debugoptimized',
diff --git a/src/meson.build b/src/meson.build
index 2094079..6cf5113 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -46,6 +46,7 @@ sources += [
'power-profiles-daemon.c',
'ppd-action-trickle-charge.c',
'ppd-driver-intel-pstate.c',
+ 'ppd-driver-amd-pstate.c',
'ppd-driver-platform-profile.c',
'ppd-driver-placeholder.c',
'ppd-driver-fake.c',
diff --git a/src/power-profiles-daemon.c b/src/power-profiles-daemon.c
index ab1b095..2a3c26b 100644
--- a/src/power-profiles-daemon.c
+++ b/src/power-profiles-daemon.c
@@ -75,6 +75,7 @@ static void start_profile_drivers (PpdApp *data);
#include "ppd-driver-placeholder.h"
#include "ppd-driver-platform-profile.h"
#include "ppd-driver-intel-pstate.h"
+#include "ppd-driver-amd-pstate.h"
#include "ppd-driver-fake.h"
typedef GType (*GTypeGetFunc) (void);
@@ -84,6 +85,7 @@ static GTypeGetFunc objects[] = {
ppd_driver_fake_get_type,
ppd_driver_platform_profile_get_type,
ppd_driver_intel_pstate_get_type,
+ ppd_driver_amd_pstate_get_type,
/* Generic profile driver */
ppd_driver_placeholder_get_type,
@@ -103,6 +105,16 @@ typedef enum {
#define PROP_ALL (PROP_ACTIVE_PROFILE | PROP_INHIBITED | PROP_PROFILES | PROP_ACTIONS | PROP_DEGRADED | PROP_ACTIVE_PROFILE_HOLDS)
+static gboolean
+get_profile_available (PpdApp *data,
+ PpdProfile profile)
+{
+ PpdDriver *driver;
+
+ driver = GET_DRIVER(profile);
+ return driver != NULL;
+}
+
static const char *
get_active_profile (PpdApp *data)
{
@@ -386,6 +398,11 @@ set_active_profile (PpdApp *data,
"Invalid profile name '%s'", profile);
return FALSE;
}
+ if (!get_profile_available (data, target_profile)) {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ "Cannot switch to unavailable profile '%s'", profile);
+ return FALSE;
+ }
if (target_profile == data->active_profile)
return TRUE;
@@ -554,8 +571,14 @@ hold_profile (PpdApp *data,
profile = ppd_profile_from_str (profile_name);
if (profile != PPD_PROFILE_PERFORMANCE &&
profile != PPD_PROFILE_POWER_SAVER) {
+ g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "Only profiles 'performance' and 'power-saver' can be a hold profile");
+ return;
+ }
+ if (!get_profile_available (data, profile)) {
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
- "Only profiles 'performance' and 'power-saver' can be a hold profile");
+ "Cannot hold profile '%s' as it is not available",
+ profile_name);
return;
}
diff --git a/src/powerprofilesctl.in b/src/powerprofilesctl.in
index fac2529..b1ea675 100755
--- a/src/powerprofilesctl.in
+++ b/src/powerprofilesctl.in
@@ -127,44 +127,43 @@ def get_profiles_property(prop):
profiles = proxy.Get('(ss)', 'net.hadess.PowerProfiles', prop)
except:
raise
- else:
- return profiles
+ return profiles
def _list():
try:
profiles = get_profiles_property('Profiles')
reason = get_proxy().Get('(ss)', 'net.hadess.PowerProfiles', 'PerformanceDegraded')
- degraded = (reason != '')
+ degraded = reason != ''
active = get_proxy().Get('(ss)', 'net.hadess.PowerProfiles', 'ActiveProfile')
except:
raise
- else:
- index = 0
- for profile in reversed(profiles):
- if index > 0:
- print('')
- marker = '*' if profile['Profile'] == active else ' '
- print(f'{marker} {profile["Profile"]}:')
- print(' Driver: ', profile['Driver'])
- if profile['Profile'] == 'performance':
- print(' Degraded: ', f'yes ({reason})' if degraded else 'no')
- index += 1
+
+ index = 0
+ for profile in reversed(profiles):
+ if index > 0:
+ print('')
+ marker = '*' if profile['Profile'] == active else ' '
+ print(f'{marker} {profile["Profile"]}:')
+ print(' Driver: ', profile['Driver'])
+ if profile['Profile'] == 'performance':
+ print(' Degraded: ', f'yes ({reason})' if degraded else 'no')
+ index += 1
def _list_holds():
try:
holds = get_profiles_property('ActiveProfileHolds')
except:
raise
- else:
- index = 0
- for hold in holds:
- if index > 0:
- print('')
- print('Hold:')
- print(' Profile: ', hold['Profile'])
- print(' Application ID: ', hold['ApplicationId'])
- print(' Reason: ', hold['Reason'])
- index += 1
+
+ index = 0
+ for hold in holds:
+ if index > 0:
+ print('')
+ print('Hold:')
+ print(' Profile: ', hold['Profile'])
+ print(' Application ID: ', hold['ApplicationId'])
+ print(' Reason: ', hold['Reason'])
+ index += 1
def _launch(args, profile, appid, reason):
try:
diff --git a/src/ppd-driver-amd-pstate.c b/src/ppd-driver-amd-pstate.c
new file mode 100644
index 0000000..825caca
--- /dev/null
+++ b/src/ppd-driver-amd-pstate.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2020 Bastien Nocera <hadess at hadess.net>
+ * Copyright (c) 2022 Prajna Sariputra <putr4.s at gmail.com>
+ *
+ * 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 <upower.h>
+
+#include "ppd-utils.h"
+#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"
+
+struct _PpdDriverAmdPstate
+{
+ PpdDriver parent_instance;
+
+ PpdProfile activated_profile;
+ GList *epp_devices; /* GList of paths */
+};
+
+G_DEFINE_TYPE (PpdDriverAmdPstate, ppd_driver_amd_pstate, PPD_TYPE_DRIVER)
+
+static gboolean ppd_driver_amd_pstate_activate_profile (PpdDriver *driver,
+ PpdProfile profile,
+ PpdProfileActivationReason reason,
+ GError **error);
+
+static GObject*
+ppd_driver_amd_pstate_constructor (GType type,
+ guint n_construct_params,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+
+ object = G_OBJECT_CLASS (ppd_driver_amd_pstate_parent_class)->constructor (type,
+ n_construct_params,
+ construct_params);
+ g_object_set (object,
+ "driver-name", "amd_pstate",
+ "profiles", PPD_PROFILE_PERFORMANCE | PPD_PROFILE_BALANCED | PPD_PROFILE_POWER_SAVER,
+ NULL);
+
+ return object;
+}
+
+static PpdProbeResult
+probe_epp (PpdDriverAmdPstate *pstate)
+{
+ g_autoptr(GDir) dir = NULL;
+ g_autofree char *policy_dir = NULL;
+ g_autofree char *pstate_status_path = NULL;
+ g_autofree char *status = NULL;
+ const char *dirname;
+ PpdProbeResult ret = PPD_PROBE_RESULT_FAIL;
+
+ /* Verify that AMD P-State is running in active mode */
+ pstate_status_path = ppd_utils_get_sysfs_path (PSTATE_STATUS_PATH);
+ if (!g_file_get_contents (pstate_status_path, &status, NULL, NULL))
+ return ret;
+ status = g_strchomp (status);
+ if (g_strcmp0 (status, "active") != 0) {
+ g_debug ("AMD P-State is not running in active mode");
+ return ret;
+ }
+
+ policy_dir = ppd_utils_get_sysfs_path (CPUFREQ_POLICY_DIR);
+ dir = g_dir_open (policy_dir, 0, NULL);
+ if (!dir) {
+ g_debug ("Could not open %s", policy_dir);
+ return ret;
+ }
+
+ while ((dirname = g_dir_read_name (dir)) != NULL) {
+ g_autofree char *path = NULL;
+ g_autofree char *gov_path = NULL;
+ g_autoptr(GError) error = NULL;
+
+ path = g_build_filename (policy_dir,
+ dirname,
+ "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));
+ ret = PPD_PROBE_RESULT_SUCCESS;
+ }
+
+ return ret;
+}
+
+static PpdProbeResult
+ppd_driver_amd_pstate_probe (PpdDriver *driver)
+{
+ PpdDriverAmdPstate *pstate = PPD_DRIVER_AMD_PSTATE (driver);
+ PpdProbeResult ret = PPD_PROBE_RESULT_FAIL;
+
+ ret = probe_epp (pstate);
+
+ if (ret != PPD_PROBE_RESULT_SUCCESS)
+ goto out;
+
+out:
+ g_debug ("%s p-state settings",
+ ret == PPD_PROBE_RESULT_SUCCESS ? "Found" : "Didn't find");
+ return ret;
+}
+
+static const char *
+profile_to_epp_pref (PpdProfile profile)
+{
+ /* Note that we don't check "energy_performance_available_preferences"
+ * as all the values are always available */
+ switch (profile) {
+ case PPD_PROFILE_POWER_SAVER:
+ return "power";
+ case PPD_PROFILE_BALANCED:
+ return "balance_performance";
+ case PPD_PROFILE_PERFORMANCE:
+ return "performance";
+ }
+
+ g_assert_not_reached ();
+}
+
+static gboolean
+apply_pref_to_devices (GList *devices,
+ const char *pref,
+ GError **error)
+{
+ gboolean ret = TRUE;
+ GList *l;
+
+ for (l = devices; l != NULL; l = l->next) {
+ const char *path = l->data;
+
+ ret = ppd_utils_write (path, pref, error);
+ if (!ret)
+ break;
+ }
+
+ return ret;
+}
+
+static gboolean
+ppd_driver_amd_pstate_activate_profile (PpdDriver *driver,
+ PpdProfile profile,
+ PpdProfileActivationReason reason,
+ GError **error)
+{
+ 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)
+ return ret;
+ }
+
+ if (ret)
+ pstate->activated_profile = profile;
+
+ return ret;
+}
+
+static void
+ppd_driver_amd_pstate_finalize (GObject *object)
+{
+ PpdDriverAmdPstate *driver;
+
+ driver = PPD_DRIVER_AMD_PSTATE (object);
+ g_clear_list (&driver->epp_devices, g_free);
+ G_OBJECT_CLASS (ppd_driver_amd_pstate_parent_class)->finalize (object);
+}
+
+static void
+ppd_driver_amd_pstate_class_init (PpdDriverAmdPstateClass *klass)
+{
+ GObjectClass *object_class;
+ PpdDriverClass *driver_class;
+
+ object_class = G_OBJECT_CLASS(klass);
+ object_class->constructor = ppd_driver_amd_pstate_constructor;
+ object_class->finalize = ppd_driver_amd_pstate_finalize;
+
+ driver_class = PPD_DRIVER_CLASS(klass);
+ driver_class->probe = ppd_driver_amd_pstate_probe;
+ driver_class->activate_profile = ppd_driver_amd_pstate_activate_profile;
+}
+
+static void
+ppd_driver_amd_pstate_init (PpdDriverAmdPstate *self)
+{
+}
diff --git a/src/ppd-driver-amd-pstate.h b/src/ppd-driver-amd-pstate.h
new file mode 100644
index 0000000..c4f1690
--- /dev/null
+++ b/src/ppd-driver-amd-pstate.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020 Bastien Nocera <hadess at hadess.net>
+ * Copyright (c) 2022 Prajna Sariputra <putr4.s at gmail.com>
+ *
+ * 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_AMD_PSTATE (ppd_driver_amd_pstate_get_type())
+G_DECLARE_FINAL_TYPE(PpdDriverAmdPstate, ppd_driver_amd_pstate, PPD, DRIVER_AMD_PSTATE, PpdDriver)
diff --git a/src/ppd-driver-intel-pstate.c b/src/ppd-driver-intel-pstate.c
index 17b6af4..413a0d2 100644
--- a/src/ppd-driver-intel-pstate.c
+++ b/src/ppd-driver-intel-pstate.c
@@ -171,7 +171,6 @@ probe_epb (PpdDriverIntelPstate *pstate)
while ((dirname = g_dir_read_name (dir)) != NULL) {
g_autofree char *path = NULL;
- g_autofree char *gov_path = NULL;
path = g_build_filename (policy_dir,
dirname,
diff --git a/src/ppd-driver-platform-profile.c b/src/ppd-driver-platform-profile.c
index 8111251..aebc655 100644
--- a/src/ppd-driver-platform-profile.c
+++ b/src/ppd-driver-platform-profile.c
@@ -26,6 +26,7 @@ struct _PpdDriverPlatformProfile
int lapmode;
PpdProfile acpi_platform_profile;
char **profile_choices;
+ gboolean has_low_power;
GFileMonitor *lapmode_mon;
GFileMonitor *acpi_platform_profile_mon;
guint acpi_platform_profile_changed_id;
@@ -57,10 +58,10 @@ profile_to_acpi_platform_profile_value (PpdDriverPlatformProfile *self,
{
switch (profile) {
case PPD_PROFILE_POWER_SAVER:
+ if (!self->has_low_power)
+ return "balanced";
if (g_strv_contains ((const char * const*) self->profile_choices, "low-power"))
return "low-power";
- if (g_strv_contains ((const char * const*) self->profile_choices, "cool"))
- return "cool";
return "quiet";
case PPD_PROFILE_BALANCED:
return "balanced";
@@ -79,9 +80,9 @@ acpi_platform_profile_value_to_profile (const char *str)
switch (str[0]) {
case 'l': /* low-power */
- case 'c': /* cool */
case 'q': /* quiet */
return PPD_PROFILE_POWER_SAVER;
+ case 'c': /* cool */
case 'b':
return PPD_PROFILE_BALANCED;
case 'p':
@@ -142,12 +143,15 @@ verify_acpi_platform_profile_choices (PpdDriverPlatformProfile *self)
{
const char * const *choices = (const char * const*) self->profile_choices;
- if ((g_strv_contains (choices, "low-power") ||
- g_strv_contains (choices, "cool") ||
- g_strv_contains (choices, "quiet")) &&
- g_strv_contains (choices, "balanced") &&
- g_strv_contains (choices, "performance"))
+ if (g_strv_contains (choices, "balanced") &&
+ g_strv_contains (choices, "performance")) {
+ if (g_strv_contains (choices, "low-power") ||
+ g_strv_contains (choices, "quiet"))
+ self->has_low_power = TRUE;
+ else
+ g_debug ("No \"low-power\" profile for device, will be emulated");
return PPD_PROBE_RESULT_SUCCESS;
+ }
return PPD_PROBE_RESULT_DEFER;
}
@@ -203,7 +207,7 @@ acpi_platform_profile_changed (GFileMonitor *monitor,
gpointer user_data)
{
PpdDriverPlatformProfile *self = user_data;
- g_debug (ACPI_PLATFORM_PROFILE_PATH " changed");
+ g_debug (ACPI_PLATFORM_PROFILE_PATH " changed (%d)", event_type);
if (self->probe_result == PPD_PROBE_RESULT_DEFER) {
g_signal_emit_by_name (G_OBJECT (self), "probe-request", 0);
return;
@@ -219,6 +223,7 @@ ppd_driver_platform_profile_activate_profile (PpdDriver *drive
{
PpdDriverPlatformProfile *self = PPD_DRIVER_PLATFORM_PROFILE (driver);
g_autofree char *platform_profile_path = NULL;
+ const char *platform_profile_value;
g_return_val_if_fail (self->acpi_platform_profile_mon, FALSE);
@@ -228,6 +233,14 @@ ppd_driver_platform_profile_activate_profile (PpdDriver *drive
return TRUE;
}
+ platform_profile_value = profile_to_acpi_platform_profile_value (self, profile);
+ if (self->acpi_platform_profile == acpi_platform_profile_value_to_profile (platform_profile_value)) {
+ g_debug ("Not switching to platform_profile %s, emulating for %s, already there",
+ platform_profile_value,
+ ppd_profile_to_str (profile));
+ return TRUE;
+ }
+
g_signal_handler_block (G_OBJECT (self->acpi_platform_profile_mon), self->acpi_platform_profile_changed_id);
platform_profile_path = ppd_utils_get_sysfs_path (ACPI_PLATFORM_PROFILE_PATH);
if (!ppd_utils_write (platform_profile_path, profile_to_acpi_platform_profile_value (self, profile), error)) {
diff --git a/src/ppd-utils.c b/src/ppd-utils.c
index 89b56e3..5ac732f 100644
--- a/src/ppd-utils.c
+++ b/src/ppd-utils.c
@@ -85,6 +85,7 @@ ppd_utils_monitor_sysfs_attr (GUdevDevice *device,
path = g_build_filename (g_udev_device_get_sysfs_path (device), attribute, NULL);
file = g_file_new_for_path (path);
+ g_debug ("Monitoring file %s for changes", path);
return g_file_monitor_file (file,
G_FILE_MONITOR_NONE,
NULL,
diff --git a/tests/integration-test.py b/tests/integration-test.py
index 77e05c0..8e37f69 100755
--- a/tests/integration-test.py
+++ b/tests/integration-test.py
@@ -320,6 +320,13 @@ class Tests(dbusmock.DBusTestCase):
self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('power-saver'))
self.assertEqual(self.get_dbus_property('ActiveProfile'), 'power-saver')
+ with self.assertRaises(gi.repository.GLib.GError):
+ self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('performance'))
+ self.assertEqual(self.get_dbus_property('ActiveProfile'), 'power-saver')
+
+ with self.assertRaises(gi.repository.GLib.GError):
+ cookie = self.call_dbus_method('HoldProfile', GLib.Variant("(sss)", ('performance', 'testReason', 'testApplication')))
+
# process = subprocess.Popen(['gdbus', 'introspect', '--system', '--dest', 'net.hadess.PowerProfiles', '--object-path', '/net/hadess/PowerProfiles'])
# print (self.get_dbus_property('GPUs'))
@@ -598,6 +605,183 @@ class Tests(dbusmock.DBusTestCase):
self.stop_daemon()
+ def test_amd_pstate(self):
+ '''AMD P-State driver (no UPower)'''
+
+ # 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")
+
+ self.start_daemon()
+
+ profiles = self.get_dbus_property('Profiles')
+ self.assertEqual(len(profiles), 3)
+ self.assertEqual(profiles[0]['Driver'], 'amd_pstate')
+ self.assertEqual(profiles[0]['Profile'], 'power-saver')
+
+ contents = None
+ with open(os.path.join(dir2, "energy_performance_preference"), 'rb') as f:
+ contents = f.read()
+ self.assertEqual(contents, b'balance_performance')
+
+ # Set performance mode
+ self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('performance'))
+ self.assertEqual(self.get_dbus_property('ActiveProfile'), 'performance')
+
+ contents = None
+ with open(os.path.join(dir2, "energy_performance_preference"), 'rb') as f:
+ contents = f.read()
+ self.assertEqual(contents, b'performance')
+
+ 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)'''
+
+ # 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")
+ os.makedirs(pstate_dir)
+ with open(os.path.join(pstate_dir, "status"),'w') as status:
+ status.write("active\n")
+
+ upowerd, obj_upower = self.spawn_server_template(
+ 'upower', {'DaemonVersion': '0.99', 'OnBattery': False}, stdout=subprocess.PIPE)
+
+ 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]['Driver'], 'amd_pstate')
+ self.assertEqual(profiles[0]['Profile'], 'power-saver')
+
+ contents = None
+ with open(os.path.join(dir1, "energy_performance_preference"), 'rb') as f:
+ contents = f.read()
+ # This matches what's written by ppd-driver-amd-pstate.c
+ self.assertEqual(contents, b'balance_performance')
+
+ self.stop_daemon()
+
+ upowerd.terminate()
+ upowerd.wait()
+ upowerd.stdout.close()
+
+ def test_amd_pstate_error(self):
+ '''AMD P-State driver in error state'''
+
+ 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")
+
+ 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')
+ pref_path = os.path.join(dir1, "energy_performance_preference")
+ old_umask = os.umask(0o333)
+ with open(pref_path,'w') as prefs:
+ 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.start_daemon()
+
+ self.assertEqual(self.get_dbus_property('ActiveProfile'), 'balanced')
+
+ # Error when setting performance mode
+ with self.assertRaises(gi.repository.GLib.GError):
+ self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('performance'))
+ self.assertEqual(self.get_dbus_property('ActiveProfile'), 'balanced')
+
+ contents = None
+ with open(os.path.join(dir1, "energy_performance_preference"), 'rb') as f:
+ contents = f.read()
+ self.assertEqual(contents, b'balance_performance\n')
+
+ self.stop_daemon()
+
+ if os.geteuid() == 0:
+ subprocess.check_output(['chattr', '-i', pref_path])
+
+ def test_amd_pstate_passive(self):
+ '''AMD P-State in passive mode -> placeholder'''
+
+ 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 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("passive\n")
+
+ self.start_daemon()
+
+ profiles = self.get_dbus_property('Profiles')
+ self.assertEqual(len(profiles), 2)
+ self.assertEqual(profiles[0]['Driver'], 'placeholder')
+ self.assertEqual(self.get_dbus_property('ActiveProfile'), 'balanced')
+
+ contents = None
+ with open(os.path.join(dir1, "energy_performance_preference"), 'rb') as f:
+ contents = f.read()
+ self.assertEqual(contents, b'performance\n')
+
+ # Set performance 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(dir1, "energy_performance_preference"), 'rb') as f:
+ contents = f.read()
+ self.assertEqual(contents, b'performance\n')
+
+ self.stop_daemon()
+
def test_dytc_performance_driver(self):
'''Lenovo DYTC performance driver'''
@@ -753,19 +937,23 @@ class Tests(dbusmock.DBusTestCase):
self.assertEqual(profiles[0]['Driver'], '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')
+ self.assertEqual(self.read_sysfs_file("sys/firmware/acpi/platform_profile"), b'cool')
self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('power-saver'))
self.assertEqual(self.get_dbus_property('ActiveProfile'), 'power-saver')
self.assertEqual(self.read_sysfs_file("sys/firmware/acpi/platform_profile"), b'cool')
+ self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('performance'))
+ self.set_dbus_property('ActiveProfile', GLib.Variant.new_string('balanced'))
+ self.assertEqual(self.read_sysfs_file("sys/firmware/acpi/platform_profile"), b'balanced')
+
self.stop_daemon()
def test_quiet(self):
- # Uses cool instead of low-power
+ # Uses quiet instead of low-power
acpi_dir = os.path.join(self.testbed.get_root_dir(), "sys/firmware/acpi/")
os.makedirs(acpi_dir)
with open(os.path.join(acpi_dir, "platform_profile"),'w') as profile:
- profile.write("cool\n")
+ profile.write("quiet\n")
with open(os.path.join(acpi_dir, "platform_profile_choices"),'w') as choices:
choices.write("quiet balanced balanced-performance performance\n")
More information about the Neon-commits
mailing list