mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2025-02-25 18:55:26 -06:00
feat: persist fan curve when toggling fan control, avoid applying fan settings when there is no fan
This commit is contained in:
@@ -24,7 +24,7 @@ use std::{
|
||||
use tokio::{select, sync::Notify, task::JoinHandle, time::sleep};
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
type FanControlHandle = (Arc<Notify>, JoinHandle<()>, FanCurve);
|
||||
type FanControlHandle = (Arc<Notify>, JoinHandle<()>);
|
||||
|
||||
pub struct GpuController {
|
||||
handle: GpuHandle,
|
||||
@@ -156,18 +156,19 @@ impl GpuController {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_stats(&self) -> anyhow::Result<DeviceStats> {
|
||||
let fan_control_guard = self
|
||||
pub fn get_stats(&self, gpu_config: Option<&GpuConfig>) -> anyhow::Result<DeviceStats> {
|
||||
let fan_control_enabled = self
|
||||
.fan_control_handle
|
||||
.lock()
|
||||
.map_err(|err| anyhow!("Could not lock fan control mutex: {err}"))?;
|
||||
.map_err(|err| anyhow!("Could not lock fan control mutex: {err}"))?
|
||||
.is_some();
|
||||
|
||||
Ok(DeviceStats {
|
||||
fan: FanStats {
|
||||
control_enabled: fan_control_guard.is_some(),
|
||||
curve: fan_control_guard
|
||||
.as_ref()
|
||||
.map(|(_, _, curve)| curve.0.clone()),
|
||||
control_enabled: fan_control_enabled,
|
||||
curve: gpu_config
|
||||
.and_then(|config| config.fan_control_settings.as_ref())
|
||||
.map(|settings| settings.curve.0.clone()),
|
||||
speed_current: self.hw_mon_and_then(HwMon::get_fan_current),
|
||||
speed_max: self.hw_mon_and_then(HwMon::get_fan_max),
|
||||
speed_min: self.hw_mon_and_then(HwMon::get_fan_min),
|
||||
@@ -242,8 +243,6 @@ impl GpuController {
|
||||
|
||||
let notify = Arc::new(Notify::new());
|
||||
let task_notify = notify.clone();
|
||||
let task_curve = curve.clone();
|
||||
debug!("using curve {curve:?}");
|
||||
|
||||
let handle = tokio::spawn(async move {
|
||||
loop {
|
||||
@@ -256,7 +255,7 @@ impl GpuController {
|
||||
let temp = temps
|
||||
.remove(&temp_key)
|
||||
.expect("Could not get temperature by given key");
|
||||
let target_pwm = task_curve.pwm_at_temp(temp);
|
||||
let target_pwm = curve.pwm_at_temp(temp);
|
||||
trace!("fan control tick: setting pwm to {target_pwm}");
|
||||
|
||||
if let Err(err) = hw_mon.set_fan_pwm(target_pwm) {
|
||||
@@ -267,7 +266,7 @@ impl GpuController {
|
||||
debug!("exited fan control task");
|
||||
});
|
||||
|
||||
*notify_guard = Some((notify, handle, curve));
|
||||
*notify_guard = Some((notify, handle));
|
||||
|
||||
debug!(
|
||||
"started fan control with interval {}ms",
|
||||
@@ -283,7 +282,7 @@ impl GpuController {
|
||||
.lock()
|
||||
.map_err(|err| anyhow!("Lock error: {err}"))?
|
||||
.take();
|
||||
if let Some((notify, handle, _)) = maybe_notify {
|
||||
if let Some((notify, handle)) = maybe_notify {
|
||||
notify.notify_one();
|
||||
handle.await?;
|
||||
|
||||
|
||||
@@ -131,7 +131,12 @@ impl<'a> Handler {
|
||||
}
|
||||
|
||||
pub fn get_gpu_stats(&'a self, id: &str) -> anyhow::Result<DeviceStats> {
|
||||
self.controller_by_id(id)?.get_stats()
|
||||
let config = self
|
||||
.config
|
||||
.read()
|
||||
.map_err(|err| anyhow!("Could not read config: {err:?}"))?;
|
||||
let gpu_config = config.gpus.get(id);
|
||||
self.controller_by_id(id)?.get_stats(gpu_config)
|
||||
}
|
||||
|
||||
pub fn get_clocks_info(&'a self, id: &str) -> anyhow::Result<ClocksInfo> {
|
||||
@@ -144,9 +149,9 @@ impl<'a> Handler {
|
||||
enabled: bool,
|
||||
curve: Option<FanCurveMap>,
|
||||
) -> anyhow::Result<()> {
|
||||
let settings = if enabled {
|
||||
let settings = {
|
||||
let curve = curve.map_or_else(FanCurve::default, FanCurve);
|
||||
let settings = match curve {
|
||||
Some(raw_curve) => {
|
||||
let curve = FanCurve(raw_curve);
|
||||
curve.validate()?;
|
||||
|
||||
let mut config_guard = self.config.write().map_err(|err| anyhow!("{err}"))?;
|
||||
@@ -154,18 +159,16 @@ impl<'a> Handler {
|
||||
|
||||
if let Some(mut existing_settings) = gpu_config.fan_control_settings.clone() {
|
||||
existing_settings.curve = curve;
|
||||
existing_settings
|
||||
Some(existing_settings)
|
||||
} else {
|
||||
FanControlSettings {
|
||||
Some(FanControlSettings {
|
||||
curve,
|
||||
temperature_key: "edge".to_owned(),
|
||||
interval_ms: 500,
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
Some(settings)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
self.edit_gpu_config(id.to_owned(), |config| {
|
||||
|
||||
@@ -315,16 +315,17 @@ impl App {
|
||||
.context("Failed to set power profile")?;
|
||||
}
|
||||
|
||||
let thermals_settings = self.root_stack.thermals_page.get_thermals_settings();
|
||||
debug!("applying thermal settings: {thermals_settings:?}");
|
||||
if let Some(thermals_settings) = self.root_stack.thermals_page.get_thermals_settings() {
|
||||
debug!("applying thermal settings: {thermals_settings:?}");
|
||||
|
||||
self.daemon_client
|
||||
.set_fan_control(
|
||||
&gpu_id,
|
||||
thermals_settings.manual_fan_control,
|
||||
thermals_settings.curve,
|
||||
)
|
||||
.context("Could not set fan control")?;
|
||||
self.daemon_client
|
||||
.set_fan_control(
|
||||
&gpu_id,
|
||||
thermals_settings.manual_fan_control,
|
||||
thermals_settings.curve,
|
||||
)
|
||||
.context("Could not set fan control")?;
|
||||
}
|
||||
|
||||
self.set_initial(&gpu_id);
|
||||
|
||||
|
||||
@@ -176,7 +176,7 @@ fn show_list_window(title: &str, items: &[FeatureModel]) {
|
||||
.build();
|
||||
|
||||
let base_model = gio::ListStore::new(FeatureModel::static_type());
|
||||
base_model.extend_from_slice(&items);
|
||||
base_model.extend_from_slice(items);
|
||||
|
||||
let expression = PropertyExpression::new(FeatureModel::static_type(), Expression::NONE, "name");
|
||||
let filter = StringFilter::builder()
|
||||
|
||||
@@ -181,17 +181,18 @@ impl ThermalsPage {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn get_thermals_settings(&self) -> ThermalsSettings {
|
||||
let manual_fan_control = !self.fan_control_enabled_switch.state();
|
||||
let curve = if manual_fan_control {
|
||||
Some(self.fan_curve_frame.get_curve())
|
||||
pub fn get_thermals_settings(&self) -> Option<ThermalsSettings> {
|
||||
if self.fan_control_enabled_switch.is_sensitive() {
|
||||
let manual_fan_control = !self.fan_control_enabled_switch.state();
|
||||
let curve = self.fan_curve_frame.get_curve();
|
||||
let curve = if curve.is_empty() { None } else { Some(curve) };
|
||||
|
||||
Some(ThermalsSettings {
|
||||
manual_fan_control,
|
||||
curve,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
ThermalsSettings {
|
||||
manual_fan_control,
|
||||
curve,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user