mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2025-02-25 18:55:26 -06:00
feat: GetPowerStates daemon implementation
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
use crate::server::gpu_controller::fan_control::FanCurve;
|
||||
use anyhow::Context;
|
||||
use lact_schema::{
|
||||
amdgpu_sysfs::gpu_handle::PerformanceLevel, default_fan_curve, request::SetClocksCommand,
|
||||
amdgpu_sysfs::gpu_handle::{PerformanceLevel, PowerLevelKind},
|
||||
default_fan_curve,
|
||||
request::SetClocksCommand,
|
||||
FanControlMode,
|
||||
};
|
||||
use nix::unistd::getuid;
|
||||
@@ -64,6 +66,7 @@ pub struct Gpu {
|
||||
pub max_voltage: Option<i32>,
|
||||
pub voltage_offset: Option<i32>,
|
||||
pub power_profile_mode_index: Option<u16>,
|
||||
pub power_states: HashMap<PowerLevelKind, Vec<u8>>,
|
||||
}
|
||||
|
||||
impl Gpu {
|
||||
|
||||
@@ -9,13 +9,13 @@ use lact_schema::{
|
||||
error::Error,
|
||||
gpu_handle::{
|
||||
overdrive::{ClocksTable, ClocksTableGen},
|
||||
GpuHandle, PerformanceLevel,
|
||||
GpuHandle, PerformanceLevel, PowerLevelKind, PowerLevels,
|
||||
},
|
||||
hw_mon::{FanControlMethod, HwMon},
|
||||
sysfs::SysFS,
|
||||
},
|
||||
ClocksInfo, ClockspeedStats, DeviceInfo, DeviceStats, DrmInfo, FanStats, GpuPciInfo, LinkInfo,
|
||||
PciInfo, PowerStats, VoltageStats, VramStats,
|
||||
PciInfo, PowerState, PowerStates, PowerStats, VoltageStats, VramStats,
|
||||
};
|
||||
use pciid_parser::Database;
|
||||
use std::{
|
||||
@@ -23,6 +23,7 @@ use std::{
|
||||
cell::RefCell,
|
||||
path::{Path, PathBuf},
|
||||
rc::Rc,
|
||||
str::FromStr,
|
||||
time::Duration,
|
||||
};
|
||||
use tokio::{select, sync::Notify, task::JoinHandle, time::sleep};
|
||||
@@ -37,7 +38,7 @@ use {
|
||||
type FanControlHandle = (Rc<Notify>, JoinHandle<()>);
|
||||
|
||||
pub struct GpuController {
|
||||
pub handle: GpuHandle,
|
||||
pub(super) handle: GpuHandle,
|
||||
#[cfg(feature = "libdrm_amdgpu_sys")]
|
||||
pub drm_handle: Option<DrmHandle>,
|
||||
pub pci_info: Option<GpuPciInfo>,
|
||||
@@ -410,6 +411,42 @@ impl GpuController {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_power_states(&self, gpu_config: Option<&config::Gpu>) -> PowerStates {
|
||||
let core = self.get_power_states_kind(gpu_config, PowerLevelKind::CoreClock);
|
||||
let memory = self.get_power_states_kind(gpu_config, PowerLevelKind::MemoryClock);
|
||||
PowerStates { core, memory }
|
||||
}
|
||||
|
||||
fn get_power_states_kind<T>(
|
||||
&self,
|
||||
gpu_config: Option<&config::Gpu>,
|
||||
kind: PowerLevelKind,
|
||||
) -> Vec<PowerState<T>>
|
||||
where
|
||||
T: FromStr,
|
||||
<T as std::str::FromStr>::Err: std::fmt::Display,
|
||||
{
|
||||
let enabled_states = gpu_config.and_then(|gpu| gpu.power_states.get(&kind));
|
||||
let levels = self
|
||||
.handle
|
||||
.get_clock_levels::<T>(kind)
|
||||
.unwrap_or_else(|_| PowerLevels {
|
||||
levels: Vec::new(),
|
||||
active: None,
|
||||
})
|
||||
.levels;
|
||||
|
||||
levels
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(i, value)| {
|
||||
let i = u8::try_from(i).unwrap();
|
||||
let enabled = enabled_states.map_or(true, |enabled| enabled.contains(&i));
|
||||
PowerState { enabled, value }
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub async fn apply_config(&self, config: &config::Gpu) -> anyhow::Result<()> {
|
||||
if config.fan_control_enabled {
|
||||
if let Some(ref settings) = config.fan_control_settings {
|
||||
@@ -510,6 +547,18 @@ impl GpuController {
|
||||
.context("Could not write clocks table")?;
|
||||
}
|
||||
|
||||
for (kind, states) in &config.power_states {
|
||||
if config.performance_level != Some(PerformanceLevel::Manual) {
|
||||
return Err(anyhow!(
|
||||
"Performance level has to be set to `manual` to configure power states"
|
||||
));
|
||||
}
|
||||
|
||||
self.handle
|
||||
.set_enabled_power_levels(*kind, states)
|
||||
.with_context(|| format!("Could not set {kind:?} power states"))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use lact_schema::{
|
||||
amdgpu_sysfs::gpu_handle::{power_profile_mode::PowerProfileModesTable, PerformanceLevel},
|
||||
default_fan_curve,
|
||||
request::{ConfirmCommand, SetClocksCommand},
|
||||
ClocksInfo, DeviceInfo, DeviceListEntry, DeviceStats, FanControlMode, FanCurveMap,
|
||||
ClocksInfo, DeviceInfo, DeviceListEntry, DeviceStats, FanControlMode, FanCurveMap, PowerStates,
|
||||
};
|
||||
use std::{cell::RefCell, collections::BTreeMap, env, path::PathBuf, rc::Rc, time::Duration};
|
||||
use tokio::{sync::oneshot, time::sleep};
|
||||
@@ -281,6 +281,17 @@ impl<'a> Handler {
|
||||
.await
|
||||
}
|
||||
|
||||
pub fn get_power_states(&self, id: &str) -> anyhow::Result<PowerStates> {
|
||||
let config = self
|
||||
.config
|
||||
.try_borrow()
|
||||
.map_err(|err| anyhow!("Could not read config: {err:?}"))?;
|
||||
let gpu_config = config.gpus.get(id);
|
||||
|
||||
let states = self.controller_by_id(id)?.get_power_states(gpu_config);
|
||||
Ok(states)
|
||||
}
|
||||
|
||||
pub async fn set_performance_level(
|
||||
&self,
|
||||
id: &str,
|
||||
|
||||
@@ -113,6 +113,7 @@ async fn handle_request<'a>(request: Request<'a>, handler: &'a Handler) -> anyho
|
||||
Request::SetPowerProfileMode { id, index } => {
|
||||
ok_response(handler.set_power_profile_mode(id, index).await?)
|
||||
}
|
||||
Request::GetPowerStates { id } => ok_response(handler.get_power_states(id)?),
|
||||
Request::EnableOverdrive => ok_response(system::enable_overdrive()?),
|
||||
Request::ConfirmPendingConfig(command) => {
|
||||
ok_response(handler.confirm_pending_config(command)?)
|
||||
|
||||
@@ -224,3 +224,15 @@ pub struct PowerStats {
|
||||
pub cap_min: Option<f64>,
|
||||
pub cap_default: Option<f64>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct PowerStates {
|
||||
pub core: Vec<PowerState<u64>>,
|
||||
pub memory: Vec<PowerState<u64>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
||||
pub struct PowerState<T> {
|
||||
pub enabled: bool,
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@ pub enum Request<'a> {
|
||||
id: &'a str,
|
||||
index: Option<u16>,
|
||||
},
|
||||
GetPowerStates {
|
||||
id: &'a str,
|
||||
},
|
||||
EnableOverdrive,
|
||||
ConfirmPendingConfig(ConfirmCommand),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user