From 14121a17f25586443a21b58c8244259d7e02d46d Mon Sep 17 00:00:00 2001 From: ilyazzz Date: Sun, 7 Mar 2021 14:31:50 +0200 Subject: [PATCH] Add support for more temperature sensors (#18) --- cli/src/main.rs | 2 +- daemon/src/gpu_controller.rs | 10 +- daemon/src/hw_mon.rs | 98 ++++++++++++++++---- gui/src/app/root_stack/oc_page/stats_grid.rs | 6 +- gui/src/app/root_stack/thermals_page.rs | 17 +++- 5 files changed, 101 insertions(+), 32 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 95ad27d..90cd376 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -186,7 +186,7 @@ fn print_stats(d: &DaemonConnection, gpu_id: u32) { println!( "{} {}{}", "Temperature:".green(), - gpu_stats.gpu_temp.unwrap_or_default().to_string().bold(), + gpu_stats.temperatures.get("edge").unwrap().current.to_string().bold(), "°C".bold(), ); println!( diff --git a/daemon/src/gpu_controller.rs b/daemon/src/gpu_controller.rs index e02690f..cfaed90 100644 --- a/daemon/src/gpu_controller.rs +++ b/daemon/src/gpu_controller.rs @@ -1,4 +1,4 @@ -use crate::config::{GpuConfig, GpuIdentifier}; +use crate::{config::{GpuConfig, GpuIdentifier}, hw_mon::Temperature}; use crate::hw_mon::{HWMon, HWMonError}; use pciid_parser::{PciDatabase, VendorData}; use serde::{Deserialize, Serialize}; @@ -97,7 +97,7 @@ pub struct GpuStats { pub mem_total: Option, pub mem_freq: Option, pub gpu_freq: Option, - pub gpu_temp: Option, + pub temperatures: HashMap, pub power_avg: Option, pub power_cap: Option, pub power_cap_max: Option, @@ -348,7 +348,7 @@ impl GpuController { let ( mem_freq, gpu_freq, - gpu_temp, + temperatures, power_avg, power_cap, power_cap_max, @@ -359,7 +359,7 @@ impl GpuController { Some(hw_mon) => ( hw_mon.get_mem_freq(), hw_mon.get_gpu_freq(), - hw_mon.get_gpu_temp(), + hw_mon.get_temps(), hw_mon.get_power_avg(), hw_mon.get_power_cap(), hw_mon.get_power_cap_max(), @@ -375,7 +375,7 @@ impl GpuController { mem_used, mem_freq, gpu_freq, - gpu_temp, + temperatures, power_avg, power_cap, power_cap_max, diff --git a/daemon/src/hw_mon.rs b/daemon/src/hw_mon.rs index cd22e9a..aa5c949 100644 --- a/daemon/src/hw_mon.rs +++ b/daemon/src/hw_mon.rs @@ -1,16 +1,17 @@ -use std::{ - collections::BTreeMap, - fs, - path::PathBuf, - sync::{ - atomic::{AtomicBool, Ordering}, - Arc, RwLock, - }, - thread, - time::Duration, -}; - use serde::{Deserialize, Serialize}; +use std::collections::{BTreeMap, HashMap}; +use std::path::PathBuf; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::{Arc, RwLock}; +use std::time::Duration; +use std::{fs, thread}; + +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] +pub struct Temperature { + pub current: i64, + pub crit: i64, + pub crit_hyst: i64, +} #[derive(Serialize, Deserialize, Debug)] pub enum HWMonError { @@ -101,13 +102,59 @@ impl HWMon { } } - pub fn get_gpu_temp(&self) -> Option { - let filename = self.hwmon_path.join("temp1_input"); + pub fn get_temps(&self) -> HashMap { + let mut temps = HashMap::new(); - match fs::read_to_string(filename) { - Ok(temp) => Some(temp.trim().parse::().unwrap() / 1000), - Err(_) => None, + for i in 1..3 { + let label_filename = self.hwmon_path.join(format!("temp{}_label", i)); + + match fs::read_to_string(label_filename) { + Ok(label) => { + // If there's a label identifying the sensor, there should always be input and crit files too. But just in case using .unwrap_or_default() + let current = { + let filename = self.hwmon_path.join(format!("temp{}_input", i)); + fs::read_to_string(filename) + .unwrap_or_default() + .trim() + .parse::() + .unwrap_or_default() + / 1000 + }; + + let crit = { + let filename = self.hwmon_path.join(format!("temp{}_crit", i)); + fs::read_to_string(filename) + .unwrap_or_default() + .trim() + .parse::() + .unwrap_or_default() + / 1000 + }; + + let crit_hyst = { + let filename = self.hwmon_path.join(format!("temp{}_crit_hyst", i)); + fs::read_to_string(filename) + .unwrap_or_default() + .trim() + .parse::() + .unwrap_or_default() + / 1000 + }; + + temps.insert( + label.trim().to_string(), + Temperature { + current, + crit, + crit_hyst, + }, + ); + } + Err(_) => break, + } } + + temps } pub fn get_voltage(&self) -> Option { @@ -187,11 +234,22 @@ impl HWMon { thread::spawn(move || { while s.fan_control.load(Ordering::SeqCst) { - let curve = s.fan_curve.read().unwrap(); + let temps = s.get_temps(); + log::trace!("Temps: {:?}", temps); + let edge_temps = temps.get("edge").unwrap(); + + let temp = edge_temps.current; + + if temp >= edge_temps.crit || temp <= edge_temps.crit_hyst { + println!("CRITICAL TEMPERATURE DETECTED! FORCING MAX FAN SPEED"); + fs::write(s.hwmon_path.join("pwm1"), 255.to_string()) + .expect("Failed to set gpu temp in critical scenario (Warning: GPU Overheating!)"); + } - let temp = s.get_gpu_temp().unwrap(); log::trace!("Current gpu temp: {}", temp); + let curve = s.fan_curve.read().unwrap(); + for (t_low, s_low) in curve.iter() { match curve.range(t_low..).nth(1) { Some((t_high, s_high)) => { @@ -210,7 +268,7 @@ impl HWMon { break; } } - None => (), + None => continue, } } drop(curve); //needed to release rwlock so that the curve can be changed diff --git a/gui/src/app/root_stack/oc_page/stats_grid.rs b/gui/src/app/root_stack/oc_page/stats_grid.rs index 7e148d9..a4b1dae 100644 --- a/gui/src/app/root_stack/oc_page/stats_grid.rs +++ b/gui/src/app/root_stack/oc_page/stats_grid.rs @@ -173,8 +173,10 @@ impl StatsGrid { stats.power_avg.unwrap_or_else(|| 0), stats.power_cap.unwrap_or_else(|| 0) )); - self.gpu_temperature_label - .set_markup(&format!("{}°C", stats.gpu_temp.unwrap_or_default())); + if let Some(temp) = stats.temperatures.get("edge") { + self.gpu_temperature_label + .set_markup(&format!("{}°C", temp.current)); + } self.gpu_usage_label .set_markup(&format!("{}%", stats.gpu_usage.unwrap_or_default())); } diff --git a/gui/src/app/root_stack/thermals_page.rs b/gui/src/app/root_stack/thermals_page.rs index 3600ffa..1dc4add 100644 --- a/gui/src/app/root_stack/thermals_page.rs +++ b/gui/src/app/root_stack/thermals_page.rs @@ -129,10 +129,19 @@ impl ThermalsPage { } pub fn set_thermals_info(&self, stats: &GpuStats) { - match stats.gpu_temp { - Some(temp) => self.temp_label.set_markup(&format!("{}°C", temp)), - None => self.temp_label.set_text("Sensor not found"), - } + self.temp_label.set_markup(&format!("{}", { + let mut temperatures = Vec::new(); + + for (label, temp) in stats.temperatures.iter() { + temperatures.push(format!("{}: {}°C", label, temp.current)); + } + + if !temperatures.is_empty() { + temperatures.join(" ") + } else { + String::from("No sensors found") + } + })); match stats.fan_speed { Some(fan_speed) => self.fan_speed_label.set_markup(&format!(