mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2026-08-18 17:04:42 -05:00
feat: automatically disable conflicting power-profiles-daemon actions (#615)
* feat: automatically disable conflicting power-profiles-daemon actions * chore: update README ppd information * fix: random intel xe tile ordering
This commit is contained in:
@@ -127,10 +127,13 @@ more information.
|
||||
## Power profiles daemon note!
|
||||
|
||||
If you are using `power-profiles-daemon` (which is installed by default on many
|
||||
distributions), by default it will override the amdgpu performance level setting
|
||||
distributions), by default it may override the amdgpu performance level setting
|
||||
according to its own profile.
|
||||
|
||||
To avoid this, create a file at
|
||||
When using LACT 0.7.5+ and power-profiles-daemon 0.30+, LACT will try to connect to power-profiles-daemon
|
||||
and automatically disable the conflicting amdgpu action in ppd to avoid this conflict.
|
||||
|
||||
If running older versions, you can resolve this manually by creating a file at
|
||||
`/etc/systemd/system/power-profiles-daemon.service.d/override.conf` with the
|
||||
following contents:
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@ mod config;
|
||||
mod server;
|
||||
mod socket;
|
||||
mod suspend;
|
||||
mod system;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use anyhow::Context;
|
||||
use config::Config;
|
||||
use futures::future::select_all;
|
||||
use server::system;
|
||||
use server::{handle_stream, handler::Handler, Server};
|
||||
use std::sync::Arc;
|
||||
use std::{os::unix::net::UnixStream as StdUnixStream, time::Duration};
|
||||
@@ -31,7 +31,7 @@ use tracing_subscriber::EnvFilter;
|
||||
/// RDNA3, minimum family that supports the new pmfw interface
|
||||
pub const AMDGPU_FAMILY_GC_11_0_0: u32 = 145;
|
||||
|
||||
pub use server::system::MODULE_CONF_PATH;
|
||||
pub use system::MODULE_CONF_PATH;
|
||||
|
||||
const MIN_SYSTEM_UPTIME_SECS: f32 = 15.0;
|
||||
const DRM_EVENT_TIMEOUT_PERIOD_MS: u64 = 100;
|
||||
|
||||
@@ -2,11 +2,10 @@ pub mod gpu_controller;
|
||||
pub mod handler;
|
||||
mod opencl;
|
||||
mod profiles;
|
||||
pub(crate) mod system;
|
||||
mod vulkan;
|
||||
|
||||
use self::handler::Handler;
|
||||
use crate::{config::Config, socket};
|
||||
use crate::{config::Config, socket, system};
|
||||
use anyhow::Context;
|
||||
use futures::future::join_all;
|
||||
use lact_schema::{Pong, Request, Response};
|
||||
@@ -39,6 +38,8 @@ impl Server {
|
||||
None
|
||||
};
|
||||
|
||||
system::power_profiles_daemon::setup().await;
|
||||
|
||||
let handler = Handler::new(config).await?;
|
||||
|
||||
socket::set_permissions(&socket_path, &handler.config.read().await.daemon)?;
|
||||
|
||||
@@ -89,6 +89,7 @@ impl IntelGpuController {
|
||||
tile_gts.len(),
|
||||
common.sysfs_path.display()
|
||||
);
|
||||
tile_gts.sort();
|
||||
}
|
||||
let drm_file = if cfg!(not(test)) {
|
||||
let drm_path = format!("/dev/dri/by-path/pci-{}-render", common.pci_slot_name);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
pub mod power_profiles_daemon;
|
||||
|
||||
use anyhow::{anyhow, ensure, Context};
|
||||
use lact_schema::{InitramfsType, SystemInfo, GIT_COMMIT};
|
||||
use nix::sys::socket::{
|
||||
@@ -249,7 +251,7 @@ pub(crate) fn listen_netlink_kernel_event(notify: &Notify) -> anyhow::Result<()>
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::server::system::detect_initramfs_type;
|
||||
use super::detect_initramfs_type;
|
||||
use lact_schema::InitramfsType;
|
||||
use os_release::OsRelease;
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
use anyhow::{anyhow, Context};
|
||||
use tracing::{debug, error, info, warn};
|
||||
use zbus::{proxy, Connection};
|
||||
|
||||
const CONFLICTING_ACTIONS: [&str; 1] = ["amdgpu_dpm"];
|
||||
const MIN_PPD_MINOR_VERSION: u32 = 30;
|
||||
|
||||
pub async fn setup() {
|
||||
let conn = match Connection::system().await {
|
||||
Ok(conn) => conn,
|
||||
Err(err) => {
|
||||
warn!("could not establish DBus connection: {err}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
match PowerProfilesDaemonProxy::new(&conn).await {
|
||||
Ok(ppd_client) => {
|
||||
if let Err(err) = disable_conflicting_actions(&ppd_client).await {
|
||||
error!("power-profiles-daemon detected, but conflicting actions could not be disabled: {err:#}");
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
debug!("could not connect to power-profiles-daemon: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn disable_conflicting_actions(client: &PowerProfilesDaemonProxy<'_>) -> anyhow::Result<()> {
|
||||
let version = client.version().await?;
|
||||
debug!("connected to power-profiles-daemon {version}");
|
||||
|
||||
let (_major, minor) = version
|
||||
.split_once('.')
|
||||
.with_context(|| format!("Could not parse version string '{version}'"))?;
|
||||
let minor = minor
|
||||
.parse::<u32>()
|
||||
.context("Could not parse minor version")?;
|
||||
|
||||
if minor < MIN_PPD_MINOR_VERSION {
|
||||
return Err(anyhow!(
|
||||
"daemon version {version} is older than minimum required for actions configuration"
|
||||
));
|
||||
}
|
||||
|
||||
let current_actions = client
|
||||
.actions_info()
|
||||
.await
|
||||
.context("Could not list actions")?;
|
||||
|
||||
for action_map in current_actions {
|
||||
if let Some(name) = action_map
|
||||
.get("Name")
|
||||
.and_then(|value| value.downcast_ref::<String>().ok())
|
||||
{
|
||||
if CONFLICTING_ACTIONS.contains(&name.as_str()) {
|
||||
match action_map
|
||||
.get("Enabled")
|
||||
.and_then(|enabled| enabled.downcast_ref::<bool>().ok())
|
||||
{
|
||||
Some(enabled) => {
|
||||
if enabled {
|
||||
match client.set_action_enabled(&name, false).await {
|
||||
Ok(()) => {
|
||||
info!(
|
||||
"disabled conflicting power-profiles-daemon action {name}"
|
||||
);
|
||||
}
|
||||
Err(err) => {
|
||||
error!("could not disable conflicting power-profiles-daemon action {name}: {err}");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
info!("conflicting power-profiles-daemon action {name} is already disabled");
|
||||
}
|
||||
}
|
||||
None => {
|
||||
error!("could not check status for power-profiles-daemon action {name}: {action_map:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[proxy(
|
||||
interface = "org.freedesktop.UPower.PowerProfiles",
|
||||
default_service = "org.freedesktop.UPower.PowerProfiles",
|
||||
default_path = "/org/freedesktop/UPower/PowerProfiles"
|
||||
)]
|
||||
trait PowerProfilesDaemon {
|
||||
/// SetActionEnabled method
|
||||
fn set_action_enabled(&self, action: &str, enabled: bool) -> zbus::Result<()>;
|
||||
|
||||
/// Actions property
|
||||
#[zbus(property)]
|
||||
fn actions(&self) -> zbus::Result<Vec<String>>;
|
||||
|
||||
/// ActionsInfo property
|
||||
#[zbus(property)]
|
||||
fn actions_info(
|
||||
&self,
|
||||
) -> zbus::Result<Vec<std::collections::HashMap<String, zbus::zvariant::OwnedValue>>>;
|
||||
|
||||
/// ActiveProfile property
|
||||
#[zbus(property)]
|
||||
fn active_profile(&self) -> zbus::Result<String>;
|
||||
|
||||
#[zbus(property)]
|
||||
fn set_active_profile(&self, value: &str) -> zbus::Result<()>;
|
||||
|
||||
/// Version property
|
||||
#[zbus(property)]
|
||||
fn version(&self) -> zbus::Result<String>;
|
||||
}
|
||||
Reference in New Issue
Block a user