Added pci.ids path for ubuntu and fixed crash for GPUs without hwmon interface

This commit is contained in:
Ilya Zlobintsev 2020-11-11 17:25:37 +02:00
parent 55bc2ee468
commit d5d0829e4e
4 changed files with 191 additions and 137 deletions

View File

@ -1,7 +1,7 @@
use crate::config::Config; use crate::config::Config;
use crate::hw_mon::{HWMon, HWMonError}; use crate::hw_mon::{HWMon, HWMonError};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::path::PathBuf; use std::path::{Path, PathBuf};
use std::{collections::BTreeMap, fs}; use std::{collections::BTreeMap, fs};
use vulkano::instance::{Instance, InstanceExtensions, PhysicalDevice}; use vulkano::instance::{Instance, InstanceExtensions, PhysicalDevice};
@ -27,7 +27,7 @@ pub struct FanControlInfo {
#[derive(Clone)] #[derive(Clone)]
pub struct GpuController { pub struct GpuController {
hw_path: PathBuf, hw_path: PathBuf,
hw_mon: HWMon, hw_mon: Option<HWMon>,
pub gpu_info: GpuInfo, pub gpu_info: GpuInfo,
config: Config, config: Config,
config_path: PathBuf, config_path: PathBuf,
@ -58,18 +58,19 @@ pub struct GpuInfo {
impl GpuController { impl GpuController {
pub fn new(hw_path: PathBuf, config: Config, config_path: PathBuf) -> Self { pub fn new(hw_path: PathBuf, config: Config, config_path: PathBuf) -> Self {
let hwmon_path = fs::read_dir(&hw_path.join("hwmon")) let hw_mon = match fs::read_dir(&hw_path.join("hwmon")) {
.unwrap() Ok(mut path) => {
.next() let path = path.next().unwrap().unwrap().path();
.unwrap()
.unwrap()
.path();
let hw_mon = HWMon::new( let hw_mon = HWMon::new(
&hwmon_path, &path,
config.fan_control_enabled, config.fan_control_enabled,
config.fan_curve.clone(), config.fan_curve.clone(),
); );
Some(hw_mon)
},
_ => None,
};
let mut controller = GpuController { let mut controller = GpuController {
hw_path: hw_path.clone(), hw_path: hw_path.clone(),
@ -95,17 +96,17 @@ impl GpuController {
for line in uevent.split('\n') { for line in uevent.split('\n') {
let split = line.split('=').collect::<Vec<&str>>(); let split = line.split('=').collect::<Vec<&str>>();
match split[0] { match split.get(0).unwrap() {
"DRIVER" => driver = split[1].to_string(), &"DRIVER" => driver = split.get(1).unwrap().to_string(),
"PCI_ID" => { &"PCI_ID" => {
let ids = split[1].split(':').collect::<Vec<&str>>(); let ids = split.last().expect("failed to get split").split(':').collect::<Vec<&str>>();
vendor_id = ids[0].to_string(); vendor_id = ids.get(0).unwrap().to_string();
model_id = ids[1].to_string(); model_id = ids.get(0).unwrap().to_string();
} }
"PCI_SUBSYS_ID" => { &"PCI_SUBSYS_ID" => {
let ids = split[1].split(':').collect::<Vec<&str>>(); let ids = split.last().expect("failed to get split").split(':').collect::<Vec<&str>>();
card_vendor_id = ids[0].to_string(); card_vendor_id = ids.get(0).unwrap().to_string();
card_model_id = ids[1].to_string(); card_model_id = ids.get(1).unwrap().to_string();
} }
_ => (), _ => (),
} }
@ -116,9 +117,14 @@ impl GpuController {
let mut card_vendor = String::new(); let mut card_vendor = String::new();
let mut card_model = String::new(); let mut card_model = String::new();
let full_hwid_list = fs::read_to_string("/usr/share/hwdata/pci.ids") let mut full_hwid_list = String::new();
.expect("Could not read pci.ids. Perhaps the \"hwids\" package is not installed?"); if Path::exists(&PathBuf::from("/usr/share/hwdata/pci.ids")) {
full_hwid_list = fs::read_to_string("/usr/share/hwdata/pci.ids").unwrap();
} else if Path::exists(&PathBuf::from("/usr/share/misc/pci.ids")) {
full_hwid_list = fs::read_to_string("/usr/share/misc/pci.ids").unwrap();
}
if !full_hwid_list.is_empty() {
//some weird space character, don't touch //some weird space character, don't touch
let pci_id_line = format!(" {}", model_id.to_lowercase()); let pci_id_line = format!(" {}", model_id.to_lowercase());
let card_ids_line = format!( let card_ids_line = format!(
@ -135,7 +141,7 @@ impl GpuController {
if line.len() > card_vendor_id.len() { if line.len() > card_vendor_id.len() {
if line[0..card_vendor_id.len()] == card_vendor_id.to_lowercase() { if line[0..card_vendor_id.len()] == card_vendor_id.to_lowercase() {
card_vendor = line.splitn(2, ' ').collect::<Vec<&str>>()[1] card_vendor = line.splitn(2, ' ').collect::<Vec<&str>>().last().unwrap()
.trim_start() .trim_start()
.to_string(); .to_string();
} }
@ -147,6 +153,9 @@ impl GpuController {
card_model = line[card_ids_line.len()..].trim_start().to_string(); card_model = line[card_ids_line.len()..].trim_start().to_string();
} }
} }
}
let vbios_version = match fs::read_to_string(self.hw_path.join("vbios_version")) { let vbios_version = match fs::read_to_string(self.hw_path.join("vbios_version")) {
Ok(v) => v, Ok(v) => v,
@ -199,11 +208,10 @@ impl GpuController {
Err(_) => 0, Err(_) => 0,
}; };
let (mem_freq, gpu_freq) = (self.hw_mon.get_mem_freq(), self.hw_mon.get_gpu_freq()); let (mem_freq, gpu_freq, gpu_temp, power_avg, power_max, fan_speed, max_fan_speed) = match &self.hw_mon {
let gpu_temp = self.hw_mon.get_gpu_temp(); Some(hw_mon) => (hw_mon.get_mem_freq(), hw_mon.get_gpu_freq(), hw_mon.get_gpu_temp(), hw_mon.get_power_avg(), hw_mon.get_power_cap(), hw_mon.get_fan_speed(), hw_mon.fan_max_speed),
let (power_avg, power_max) = (self.hw_mon.get_power_avg(), self.hw_mon.get_power_cap()); None => (0, 0, 0, 0, 0, 0, 0),
let fan_speed = self.hw_mon.get_fan_speed(); };
let max_fan_speed = self.hw_mon.fan_max_speed;
GpuStats { GpuStats {
mem_total, mem_total,
@ -219,7 +227,10 @@ impl GpuController {
} }
pub fn start_fan_control(&mut self) -> Result<(), HWMonError> { pub fn start_fan_control(&mut self) -> Result<(), HWMonError> {
match self.hw_mon.start_fan_control() { match &self.hw_mon {
Some(hw_mon) => {
match hw_mon.start_fan_control() {
Ok(_) => { Ok(_) => {
self.config.fan_control_enabled = true; self.config.fan_control_enabled = true;
self.config self.config
@ -229,10 +240,15 @@ impl GpuController {
} }
Err(e) => Err(e), Err(e) => Err(e),
} }
},
None => Err(HWMonError::NoHWMon),
}
} }
pub fn stop_fan_control(&mut self) -> Result<(), HWMonError> { pub fn stop_fan_control(&mut self) -> Result<(), HWMonError> {
match self.hw_mon.stop_fan_control() { match &self.hw_mon {
Some(hw_mon) => {
match hw_mon.stop_fan_control() {
Ok(_) => { Ok(_) => {
self.config.fan_control_enabled = false; self.config.fan_control_enabled = false;
self.config self.config
@ -242,23 +258,37 @@ impl GpuController {
} }
Err(e) => Err(e), Err(e) => Err(e),
} }
},
None => Err(HWMonError::NoHWMon),
}
} }
pub fn get_fan_control(&self) -> FanControlInfo { pub fn get_fan_control(&self) -> Result<FanControlInfo, HWMonError> {
let control = self.hw_mon.get_fan_control(); match &self.hw_mon {
Some(hw_mon) => {
FanControlInfo { let control = hw_mon.get_fan_control();
Ok(FanControlInfo {
enabled: control.0, enabled: control.0,
curve: control.1, curve: control.1,
} })
},
None => Err(HWMonError::NoHWMon),
} }
pub fn set_fan_curve(&mut self, curve: BTreeMap<i32, f64>) { }
self.hw_mon.set_fan_curve(curve.clone());
pub fn set_fan_curve(&mut self, curve: BTreeMap<i32, f64>) -> Result<(), HWMonError> {
match &self.hw_mon {
Some(hw_mon) => {
hw_mon.set_fan_curve(curve.clone());
self.config.fan_curve = curve; self.config.fan_curve = curve;
self.config self.config
.save(&self.config_path) .save(&self.config_path)
.expect("Failed to save config"); .expect("Failed to save config");
Ok(())
},
None => Err(HWMonError::NoHWMon),
}
} }
fn get_vulkan_info(pci_id: &str) -> VulkanInfo { fn get_vulkan_info(pci_id: &str) -> VulkanInfo {

View File

@ -15,6 +15,7 @@ use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub enum HWMonError { pub enum HWMonError {
PermissionDenied, PermissionDenied,
NoHWMon,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View File

@ -150,7 +150,10 @@ impl Daemon {
None => Err(DaemonError::InvalidID), None => Err(DaemonError::InvalidID),
}, },
Action::GetFanControl(i) => match gpu_controllers.get(&i) { Action::GetFanControl(i) => match gpu_controllers.get(&i) {
Some(controller) => Ok(DaemonResponse::FanControlInfo(controller.get_fan_control())), Some(controller) => match controller.get_fan_control() {
Ok(info) => Ok(DaemonResponse::FanControlInfo(info)),
Err(_) => Err(DaemonError::HWMonError),
}
None => Err(DaemonError::InvalidID), None => Err(DaemonError::InvalidID),
} }
Action::SetFanCurve(i, curve) => match gpu_controllers.get_mut(&i) { Action::SetFanCurve(i, curve) => match gpu_controllers.get_mut(&i) {
@ -159,9 +162,11 @@ impl Daemon {
let mut buffer = Vec::new(); let mut buffer = Vec::new();
stream.read_to_end(&mut buffer).unwrap(); stream.read_to_end(&mut buffer).unwrap();
controller.set_fan_curve(curve); match controller.set_fan_curve(curve) {
Ok(_) => Ok(DaemonResponse::OK),
Err(_) => Err(DaemonError::HWMonError),
}
Ok(DaemonResponse::OK)
}, },
None => Err(DaemonError::InvalidID), None => Err(DaemonError::InvalidID),
} }

View File

@ -146,8 +146,10 @@ fn build_ui(application: &gtk::Application) {
glib::Continue(true) glib::Continue(true)
}); });
let fan_control = d.get_fan_control(current_gpu_id).unwrap(); let fan_control = d.get_fan_control(current_gpu_id);
match fan_control {
Ok(ref fan_control) => {
if fan_control.enabled { if fan_control.enabled {
println!("Automatic fan control disabled!"); println!("Automatic fan control disabled!");
automatic_fan_control_switch.set_active(false); automatic_fan_control_switch.set_active(false);
@ -156,6 +158,15 @@ fn build_ui(application: &gtk::Application) {
println!("Automatic fan control enabled"); println!("Automatic fan control enabled");
fan_curve_frame.set_visible(false); fan_curve_frame.set_visible(false);
} }
},
Err(_) => {
automatic_fan_control_switch.set_sensitive(false);
automatic_fan_control_switch.set_tooltip_text(Some("Unavailable"));
fan_curve_frame.set_visible(false);
}
}
let b = apply_button.clone(); let b = apply_button.clone();
@ -173,6 +184,9 @@ fn build_ui(application: &gtk::Application) {
b.set_sensitive(true); b.set_sensitive(true);
}); });
match fan_control {
Ok(fan_control) => {
let curve: Arc<RwLock<BTreeMap<i32, f64>>> = Arc::new(RwLock::new(fan_control.curve)); let curve: Arc<RwLock<BTreeMap<i32, f64>>> = Arc::new(RwLock::new(fan_control.curve));
for i in 1..6 { for i in 1..6 {
@ -222,6 +236,10 @@ fn build_ui(application: &gtk::Application) {
} }
} }
}); });
},
Err(_) => (),
}
main_window.set_application(Some(application)); main_window.set_application(Some(application));