diff --git a/src/main.rs b/src/main.rs index a15bebd..85672b9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ use crate::dbus::gpu::get_gpus; mod constants; mod performance; -#[tokio::main] +#[tokio::main(flavor = "multi_thread", worker_threads = 2)] async fn main() -> Result<(), Box> { SimpleLogger::new().init().unwrap(); log::info!("Starting PowerStation"); @@ -33,23 +33,27 @@ async fn main() -> Result<(), Box> { // Discover all GPUs and Generate GPU objects to serve let mut gpu_obj_paths: Vec = Vec::new(); - for mut card in get_gpus() { + for mut card in get_gpus().await { // Build the DBus object path for this card - let card_name = card.name().as_str().title(); - let gpu_path = card.gpu_path(); + let gpu_name = card.name().await; + let card_name = gpu_name.as_str().title(); + let gpu_path = card.gpu_path().await; gpu_obj_paths.push(gpu_path.clone()); // Get the TDP interface from the card and serve it on DBus - let tdp = card.get_tdp_interface(); - if tdp.is_some() { - log::debug!("Discovered TDP interface on card: {}", card_name); - let tdp = tdp.unwrap(); - connection.object_server().at(gpu_path.clone(), tdp).await?; + match card.get_tdp_interface().await { + Some(tdp) => { + log::debug!("Discovered TDP interface on card: {}", card_name); + connection.object_server().at(gpu_path.clone(), tdp).await?; + }, + None => { + log::warn!("Card {} does not have a TDP interface", card_name); + } } // Get GPU connectors from the card and serve them on DBus let mut connector_paths: Vec = Vec::new(); - let connectors = get_connectors(card.name()); + let connectors = get_connectors(gpu_name); for connector in connectors { let name = connector.name.clone().replace('-', "/"); let port_path = format!("{0}/{1}", gpu_path, name); @@ -57,7 +61,7 @@ async fn main() -> Result<(), Box> { log::debug!("Discovered connector on {}: {}", card_name, port_path); connection.object_server().at(port_path, connector).await?; } - card.set_connector_paths(connector_paths); + card.set_connector_paths(connector_paths).await; // Serve the GPU interface on DBus connection diff --git a/src/performance/gpu/amd/amdgpu.rs b/src/performance/gpu/amd/amdgpu.rs index 8dfbf26..171e6d4 100644 --- a/src/performance/gpu/amd/amdgpu.rs +++ b/src/performance/gpu/amd/amdgpu.rs @@ -1,14 +1,15 @@ use std::{ fs::{self, OpenOptions}, io::Write, - sync::{ - Arc, Mutex - } + sync::Arc }; +use tokio::sync::Mutex; + use crate::constants::GPU_PATH; -use crate::performance::gpu::interface::GPUIface; -use crate::performance::gpu::{amd, tdp::TDPDevice}; +use crate::performance::gpu::interface::GPUDevice; +use crate::performance::gpu::amd; +use crate::performance::gpu::dbus::devices::TDPDevices; use crate::performance::gpu::interface::{GPUError, GPUResult}; #[derive(Debug, Clone)] @@ -29,22 +30,24 @@ pub struct AMDGPU { } -impl GPUIface for AMDGPU { +impl GPUDevice for AMDGPU { - fn get_gpu_path(&self) -> String { - format!("{0}/{1}", GPU_PATH, self.name()) + async fn get_gpu_path(&self) -> String { + format!("{0}/{1}", GPU_PATH, self.name().await) } /// Returns the TDP DBus interface for this GPU - fn get_tdp_interface(&self) -> Option>> { - // TODO: if asusd is present, or asus-wmi is present this is where it is bound to the GPU + async fn get_tdp_interface(&self) -> Option>> { + // if asusd is present, or asus-wmi is present this is where it is bound to the GPU match self.class.as_str() { "integrated" => Some( Arc::new( Mutex::new( - amd::tdp::TDP::new( - self.path.clone(), - self.device_id.clone() + TDPDevices::AMD( + amd::tdp::TDP::new( + self.path.clone(), + self.device_id.clone() + ) ) ) ) @@ -53,85 +56,85 @@ impl GPUIface for AMDGPU { } } - fn name(&self) -> String { + async fn name(&self) -> String { self.name.clone() } - fn path(&self) -> String { + async fn path(&self) -> String { self.path.clone() } - fn class(&self) -> String { + async fn class(&self) -> String { self.class.clone() } - fn class_id(&self) -> String { + async fn class_id(&self) -> String { self.class_id.clone() } - fn vendor(&self) -> String { + async fn vendor(&self) -> String { self.vendor.clone() } - fn vendor_id(&self) -> String { + async fn vendor_id(&self) -> String { self.vendor_id.clone() } - fn device(&self) -> String { + async fn device(&self) -> String { self.device.clone() } - fn device_id(&self) -> String { + async fn device_id(&self) -> String { self.device_id.clone() } - fn subdevice(&self) -> String { + async fn subdevice(&self) -> String { self.subdevice.clone() } - fn subdevice_id(&self) -> String { + async fn subdevice_id(&self) -> String { self.subdevice_id.clone() } - fn subvendor_id(&self) -> String { + async fn subvendor_id(&self) -> String { self.subvendor_id.clone() } - fn revision_id(&self) -> String { + async fn revision_id(&self) -> String { self.revision_id.clone() } - fn clock_limit_mhz_min(&self) -> GPUResult { - let limits = get_clock_limits(self.path()) + async fn clock_limit_mhz_min(&self) -> GPUResult { + let limits = get_clock_limits(self.path().await) .map_err(|err| GPUError::IOError(err.to_string()))?; let (min, _) = limits; Ok(min) } - fn clock_limit_mhz_max(&self) -> GPUResult { - let limits = get_clock_limits(self.path()) + async fn clock_limit_mhz_max(&self) -> GPUResult { + let limits = get_clock_limits(self.path().await) .map_err(|err| GPUError::IOError(err.to_string()))?; let (_, max) = limits; Ok(max) } - fn clock_value_mhz_min(&self) -> GPUResult { - let values = get_clock_values(self.path()) + async fn clock_value_mhz_min(&self) -> GPUResult { + let values = get_clock_values(self.path().await) .map_err(|err| GPUError::IOError(err.to_string()))?; let (min, _) = values; Ok(min) } - fn set_clock_value_mhz_min(&mut self, value: f64) -> GPUResult<()> { + async fn set_clock_value_mhz_min(&mut self, value: f64) -> GPUResult<()> { // Build the clock command to send // https://www.kernel.org/doc/html/v5.9/gpu/amdgpu.html#pp-od-clk-voltage let command = format!("s 0 {}\n", value); // Open the sysfs file to write to - let path = format!("{0}/{1}", self.path(), "device/pp_od_clk_voltage"); + let path = format!("{0}/{1}", self.path().await, "device/pp_od_clk_voltage"); let file = OpenOptions::new().write(true).open(path.clone()); // Write the value @@ -156,21 +159,21 @@ impl GPUIface for AMDGPU { ) } - fn clock_value_mhz_max(&self) -> GPUResult { - let values = get_clock_values(self.path()) + async fn clock_value_mhz_max(&self) -> GPUResult { + let values = get_clock_values(self.path().await) .map_err(|err| GPUError::IOError(err.to_string()))?; let (_, max) = values; Ok(max) } - fn set_clock_value_mhz_max(&mut self, value: f64) -> GPUResult<()> { + async fn set_clock_value_mhz_max(&mut self, value: f64) -> GPUResult<()> { // Build the clock command to send // https://www.kernel.org/doc/html/v5.9/gpu/amdgpu.html#pp-od-clk-voltage let command = format!("s 1 {}\n", value); // Open the sysfs file to write to - let path = format!("{0}/{1}", self.path(), "device/pp_od_clk_voltage"); + let path = format!("{0}/{1}", self.path().await, "device/pp_od_clk_voltage"); let file = OpenOptions::new().write(true).open(path.clone()); // Write the value @@ -188,10 +191,10 @@ impl GPUIface for AMDGPU { ) } - fn manual_clock(&self) -> GPUResult { + async fn manual_clock(&self) -> GPUResult { let path = format!( "{0}/{1}", - self.path(), + self.path().await, "device/power_dpm_force_performance_level" ); @@ -204,13 +207,13 @@ impl GPUIface for AMDGPU { Ok(status == "manual") } - fn set_manual_clock(&mut self, enabled: bool) -> GPUResult<()> { + async fn set_manual_clock(&mut self, enabled: bool) -> GPUResult<()> { let status = if enabled { "manual" } else { "auto" }; // Open the sysfs file to write to let path = format!( "{0}/{1}", - self.path(), + self.path().await, "device/power_dpm_force_performance_level" ); diff --git a/src/performance/gpu/amd/asus.rs b/src/performance/gpu/amd/asus.rs new file mode 100644 index 0000000..ac440cc --- /dev/null +++ b/src/performance/gpu/amd/asus.rs @@ -0,0 +1,95 @@ +use std::sync::Arc; +use udev::{Enumerator, Device}; + +use crate::performance::gpu::tdp::{TDPDevice, TDPResult, TDPError}; +use crate::performance::gpu::dbus::devices::TDPDevices; + +use zbus::{Connection, Result}; + +use rog_dbus::RogDbusClientBlocking; +use rog_dbus::DbusProxies; +use rog_platform::{platform::RogPlatform, error::PlatformError}; +use rog_platform::platform::{GpuMode, Properties, ThrottlePolicy}; +use rog_profiles::error::ProfileError; + +use std::sync::Mutex; + +/// Implementation of asusd with a fallback to asus-wmi sysfs +/// See https://www.kernel.org/doc/html/v6.8-rc4/admin-guide/abi-testing.html#abi-sys-devices-platform-platform-ppt-apu-sppt +pub struct ASUS { + platform: Arc>, +} + +impl ASUS { + + /// test if we are in an asus system with asus-wmi loaded + pub async fn new() -> Option { + match RogPlatform::new() { + Ok(platform) => { + log::info!("Module asus-wmi WAS found"); + Some(Self { + platform: Arc::new(Mutex::new(platform)) + }) + }, + Err(err) => { + log::info!("Module asus-wmi not found: {}", err); + None + } + } + } + +} + +impl TDPDevice for ASUS { + async fn tdp(&self) -> TDPResult { + match RogDbusClientBlocking::new() { + Ok((dbus, _)) => { + let supported_properties = dbus.proxies().platform().supported_properties().unwrap(); + let supported_interfaces = dbus.proxies().platform().supported_interfaces().unwrap(); + + match dbus.proxies().platform().ppt_apu_sppt() { + Ok(result) => { + log::info!("Initial ppt_apu_sppt: {}", result); + Ok(result as f64) + }, + Err(err) => { + log::warn!("Error fetching ppt_apu_sppt: {}", err); + Err(TDPError::FailedOperation(format!(""))) + } + } + }, + Err(err) => { + log::warn!("Unable to use asusd to read tdp, asus-wmi interface will be used"); + Err(TDPError::FailedOperation(format!(""))) + } + } + } + + async fn set_tdp(&mut self, value: f64) -> TDPResult<()> { + todo!() + } + + async fn boost(&self) -> TDPResult { + todo!() + } + + async fn set_boost(&mut self, value: f64) -> TDPResult<()> { + todo!() + } + + async fn thermal_throttle_limit_c(&self) -> TDPResult { + todo!() + } + + async fn set_thermal_throttle_limit_c(&mut self, limit: f64) -> TDPResult<()> { + todo!() + } + + async fn power_profile(&self) -> TDPResult { + todo!() + } + + async fn set_power_profile(&mut self, profile: String) -> TDPResult<()> { + todo!() + } +} diff --git a/src/performance/gpu/amd/tdp.rs b/src/performance/gpu/amd/tdp.rs index 2093d49..4f83cf0 100644 --- a/src/performance/gpu/amd/tdp.rs +++ b/src/performance/gpu/amd/tdp.rs @@ -221,8 +221,7 @@ impl TDP { } impl TDPDevice for TDP { - - fn tdp(&self) -> TDPResult { + async fn tdp(&self) -> TDPResult { // Get the current stapm limit from ryzenadj match TDP::get_stapm_limit(&self) { Ok(result) => Ok(result.into()), @@ -230,14 +229,13 @@ impl TDPDevice for TDP { } } - fn set_tdp(&mut self, value: f64) -> TDPResult<()> { + async fn set_tdp(&mut self, value: f64) -> TDPResult<()> { log::debug!("Setting TDP to: {}", value); if value < 1.0 { log::warn!("Cowardly refusing to set TDP less than 1W"); return Err(TDPError::InvalidArgument(format!("Cowardly refusing to set TDP less than 1W: provided {}W", value))); } - // Get the current boost value before updating the STAPM limit. We will // use this value to also adjust the Fast PPT Limit. let fast_ppt_limit = @@ -270,7 +268,7 @@ impl TDPDevice for TDP { Ok(()) } - fn boost(&self) -> TDPResult { + async fn boost(&self) -> TDPResult { let fast_ppt_limit = TDP::get_ppt_limit_fast(&self).map_err(|err| TDPError::FailedOperation(String::from(err)))?; let fast_ppt_limit = fast_ppt_limit as f64; @@ -283,7 +281,7 @@ impl TDPDevice for TDP { Ok(boost) } - fn set_boost(&mut self, value: f64) -> TDPResult<()> { + async fn set_boost(&mut self, value: f64) -> TDPResult<()> { log::debug!("Setting boost to: {}", value); if value < 0.0 { log::warn!("Cowardly refusing to set TDP Boost less than 0W"); @@ -301,22 +299,22 @@ impl TDPDevice for TDP { Ok(()) } - fn thermal_throttle_limit_c(&self) -> TDPResult { + async fn thermal_throttle_limit_c(&self) -> TDPResult { let limit = TDP::get_thm_limit(&self).map_err(|err| TDPError::FailedOperation(err.to_string()))?; Ok(limit.into()) } - fn set_thermal_throttle_limit_c(&mut self, limit: f64) -> TDPResult<()> { + async fn set_thermal_throttle_limit_c(&mut self, limit: f64) -> TDPResult<()> { log::debug!("Setting thermal throttle limit to: {}", limit); let limit = limit as u32; TDP::set_thm_limit(self, limit).map_err(|err| TDPError::FailedOperation(err.to_string())) } - fn power_profile(&self) -> TDPResult { + async fn power_profile(&self) -> TDPResult { Ok(self.profile.clone()) } - fn set_power_profile(&mut self, profile: String) -> TDPResult<()> { + async fn set_power_profile(&mut self, profile: String) -> TDPResult<()> { log::debug!("Setting power profile to: {}", profile); TDP::set_power_profile(&self, profile.clone()) .map_err(|err| TDPError::FailedOperation(err.to_string()))?; diff --git a/src/performance/gpu/dbus/devices.rs b/src/performance/gpu/dbus/devices.rs new file mode 100644 index 0000000..591b5a8 --- /dev/null +++ b/src/performance/gpu/dbus/devices.rs @@ -0,0 +1,241 @@ +use std::sync::Arc; + +use tokio::sync::Mutex; + +use crate::performance::gpu::{interface::GPUDevice, tdp::{TDPDevice, TDPResult}}; +use crate::performance::gpu::interface::GPUResult; + +pub enum TDPDevices { + //ASUS(crate::performance::gpu::amd::asus::ASUS), + AMD(crate::performance::gpu::amd::tdp::TDP), + INTEL(crate::performance::gpu::intel::tdp::TDP) +} + +impl TDPDevices { + pub async fn tdp(&self) -> TDPResult { + match self { + //Self::ASUS(dev) => dev.tdp().await, + Self::AMD(dev) => dev.tdp().await, + Self::INTEL(dev) => dev.tdp().await, + } + } + + pub async fn set_tdp(&mut self, value: f64) -> TDPResult<()> { + match self { + //Self::ASUS(dev) => dev.set_tdp(value).await, + Self::AMD(dev) => dev.set_tdp(value).await, + Self::INTEL(dev) => dev.set_tdp(value).await, + } + } + + pub async fn boost(&self) -> TDPResult { + match self { + //Self::ASUS(dev) => dev.boost().await, + Self::AMD(dev) => dev.boost().await, + Self::INTEL(dev) => dev.boost().await, + } + } + + pub async fn set_boost(&mut self, value: f64) -> TDPResult<()> { + match self { + //Self::ASUS(dev) => dev.set_boost(value).await, + Self::AMD(dev) => dev.set_boost(value).await, + Self::INTEL(dev) => dev.set_boost(value).await, + } + } + + pub async fn thermal_throttle_limit_c(&self) -> TDPResult { + match self { + //Self::ASUS(dev) => dev.thermal_throttle_limit_c().await, + Self::AMD(dev) => dev.thermal_throttle_limit_c().await, + Self::INTEL(dev) => dev.thermal_throttle_limit_c().await, + } + } + + pub async fn set_thermal_throttle_limit_c(&mut self, limit: f64) -> TDPResult<()> { + match self { + //Self::ASUS(dev) => dev.set_thermal_throttle_limit_c(limit).await, + Self::AMD(dev) => dev.set_thermal_throttle_limit_c(limit).await, + Self::INTEL(dev) => dev.set_thermal_throttle_limit_c(limit).await, + } + } + + pub async fn power_profile(&self) -> TDPResult { + match self { + //Self::ASUS(dev) => dev.power_profile().await, + Self::AMD(dev) => dev.power_profile().await, + Self::INTEL(dev) => dev.power_profile().await, + } + } + + pub async fn set_power_profile(&mut self, profile: String) -> TDPResult<()> { + match self { + //Self::ASUS(dev) => dev.set_power_profile(profile).await, + Self::AMD(dev) => dev.set_power_profile(profile).await, + Self::INTEL(dev) => dev.set_power_profile(profile).await, + } + } + +} + +pub enum GPUDevices { + AMDGPU(crate::performance::gpu::amd::amdgpu::AMDGPU), + INTELGPU(crate::performance::gpu::intel::intelgpu::IntelGPU), +} + +impl GPUDevices { + pub async fn get_tdp_interface(&self) -> Option>> { + match self { + Self::AMDGPU(dev) => dev.get_tdp_interface().await, + Self::INTELGPU(dev) => dev.get_tdp_interface().await, + } + } + + pub async fn get_gpu_path(&self) -> String { + match self { + Self::AMDGPU(dev) => dev.get_gpu_path().await, + Self::INTELGPU(dev) => dev.get_gpu_path().await, + } + } + + pub async fn name(&self) -> String { + match self { + Self::AMDGPU(dev) => dev.name().await, + Self::INTELGPU(dev) => dev.name().await, + } + } + + pub async fn path(&self) -> String { + match self { + Self::AMDGPU(dev) => dev.path().await, + Self::INTELGPU(dev) => dev.path().await, + } + } + + pub async fn class(&self) -> String { + match self { + Self::AMDGPU(dev) => dev.class().await, + Self::INTELGPU(dev) => dev.class().await, + } + } + + pub async fn class_id(&self) -> String { + match self { + Self::AMDGPU(dev) => dev.class_id().await, + Self::INTELGPU(dev) => dev.class_id().await, + } + } + + pub async fn vendor(&self) -> String { + match self { + Self::AMDGPU(dev) => dev.vendor().await, + Self::INTELGPU(dev) => dev.vendor().await, + } + } + + pub async fn vendor_id(&self) -> String { + match self { + Self::AMDGPU(dev) => dev.vendor_id().await, + Self::INTELGPU(dev) => dev.vendor_id().await, + } + } + + pub async fn device(&self) -> String { + match self { + Self::AMDGPU(dev) => dev.device().await, + Self::INTELGPU(dev) => dev.device().await, + } + } + + pub async fn device_id(&self) -> String { + match self { + Self::AMDGPU(dev) => dev.device_id().await, + Self::INTELGPU(dev) => dev.device_id().await, + } + } + + pub async fn subdevice(&self) -> String { + match self { + Self::AMDGPU(dev) => dev.subdevice().await, + Self::INTELGPU(dev) => dev.subdevice().await, + } + } + + pub async fn subdevice_id(&self) -> String { + match self { + Self::AMDGPU(dev) => dev.subdevice_id().await, + Self::INTELGPU(dev) => dev.subdevice_id().await, + } + } + + pub async fn subvendor_id(&self) -> String { + match self { + Self::AMDGPU(dev) => dev.subvendor_id().await, + Self::INTELGPU(dev) => dev.subvendor_id().await, + } + } + + pub async fn revision_id(&self) -> String { + match self { + Self::AMDGPU(dev) => dev.revision_id().await, + Self::INTELGPU(dev) => dev.revision_id().await, + } + } + + pub async fn clock_limit_mhz_min(&self) -> GPUResult { + match self { + Self::AMDGPU(dev) => dev.clock_limit_mhz_min().await, + Self::INTELGPU(dev) => dev.clock_limit_mhz_min().await, + } + } + + pub async fn clock_limit_mhz_max(&self) -> GPUResult { + match self { + Self::AMDGPU(dev) => dev.clock_limit_mhz_max().await, + Self::INTELGPU(dev) => dev.clock_limit_mhz_max().await, + } + } + + pub async fn clock_value_mhz_min(&self) -> GPUResult { + match self { + Self::AMDGPU(dev) => dev.clock_value_mhz_min().await, + Self::INTELGPU(dev) => dev.clock_value_mhz_min().await, + } + } + + pub async fn set_clock_value_mhz_min(&mut self, value: f64) -> GPUResult<()> { + match self { + Self::AMDGPU(dev) => dev.set_clock_value_mhz_min(value).await, + Self::INTELGPU(dev) => dev.set_clock_value_mhz_min(value).await, + } + } + + pub async fn clock_value_mhz_max(&self) -> GPUResult { + match self { + Self::AMDGPU(dev) => dev.clock_value_mhz_max().await, + Self::INTELGPU(dev) => dev.clock_value_mhz_max().await, + } + } + + pub async fn set_clock_value_mhz_max(&mut self, value: f64) -> GPUResult<()> { + match self { + Self::AMDGPU(dev) => dev.set_clock_value_mhz_max(value).await, + Self::INTELGPU(dev) => dev.set_clock_value_mhz_max(value).await, + } + } + + pub async fn manual_clock(&self) -> GPUResult { + match self { + Self::AMDGPU(dev) => dev.manual_clock().await, + Self::INTELGPU(dev) => dev.manual_clock().await, + } + } + + pub async fn set_manual_clock(&mut self, enabled: bool) -> GPUResult<()> { + match self { + Self::AMDGPU(dev) => dev.set_manual_clock(enabled).await, + Self::INTELGPU(dev) => dev.set_manual_clock(enabled).await, + } + } + +} diff --git a/src/performance/gpu/dbus/gpu.rs b/src/performance/gpu/dbus/gpu.rs index 5db2ba2..cfe91f8 100644 --- a/src/performance/gpu/dbus/gpu.rs +++ b/src/performance/gpu/dbus/gpu.rs @@ -1,11 +1,14 @@ use std::fs::{self, File}; use std::io::{prelude::*, BufReader}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use zbus::fdo; use zbus::zvariant::ObjectPath; use zbus_macros::dbus_interface; -use crate::performance::gpu::interface::{GPUError, GPUIface}; +use tokio::sync::Mutex; + +use crate::performance::gpu::interface::GPUError; +use crate::performance::gpu::dbus::devices::GPUDevices; use crate::performance::gpu::dbus::tdp::GPUTDPDBusIface; use crate::performance::gpu::amd::amdgpu::AMDGPU; use crate::performance::gpu::connector::Connector; @@ -29,27 +32,27 @@ impl Into for GPUError { #[derive(Clone)] pub struct GPUDBusInterface { connector_paths: Vec, - gpu_obj: Arc> + gpu_obj: Arc> } impl GPUDBusInterface { - pub fn new(gpu: Arc>) -> Self { + pub async fn new(gpu: Arc>) -> Self { Self { gpu_obj: gpu, connector_paths: vec![] } } - pub fn gpu_path(&self) -> String { - self.gpu_obj.lock().unwrap().get_gpu_path() + pub async fn gpu_path(&self) -> String { + self.gpu_obj.lock().await.get_gpu_path().await } - pub fn set_connector_paths(&mut self, connector_paths: Vec) { + pub async fn set_connector_paths(&mut self, connector_paths: Vec) { self.connector_paths = connector_paths } - pub fn get_tdp_interface(&self) -> Option { - match self.gpu_obj.lock().unwrap().get_tdp_interface() { + pub async fn get_tdp_interface(&self) -> Option { + match self.gpu_obj.lock().await.get_tdp_interface().await { Some(tdp) => Some(GPUTDPDBusIface::new(tdp)), None => None } @@ -70,103 +73,103 @@ impl GPUDBusInterface { } #[dbus_interface(property)] - pub fn name(&self) -> String { - self.gpu_obj.lock().unwrap().name() + pub async fn name(&self) -> String { + self.gpu_obj.lock().await.name().await } #[dbus_interface(property)] - fn path(&self) -> String { - self.gpu_obj.lock().unwrap().path() + async fn path(&self) -> String { + self.gpu_obj.lock().await.path().await } #[dbus_interface(property)] - fn class(&self) -> String { - self.gpu_obj.lock().unwrap().class() + async fn class(&self) -> String { + self.gpu_obj.lock().await.class().await } #[dbus_interface(property)] - fn class_id(&self) -> String { - self.gpu_obj.lock().unwrap().class_id() + async fn class_id(&self) -> String { + self.gpu_obj.lock().await.class_id().await } #[dbus_interface(property)] - fn vendor(&self) -> String { - self.gpu_obj.lock().unwrap().vendor() + async fn vendor(&self) -> String { + self.gpu_obj.lock().await.vendor().await } #[dbus_interface(property)] - fn vendor_id(&self) -> String { - self.gpu_obj.lock().unwrap().vendor_id() + async fn vendor_id(&self) -> String { + self.gpu_obj.lock().await.vendor_id().await } #[dbus_interface(property)] - fn device(&self) -> String { - self.gpu_obj.lock().unwrap().device() + async fn device(&self) -> String { + self.gpu_obj.lock().await.device().await } #[dbus_interface(property)] - fn device_id(&self) -> String { - self.gpu_obj.lock().unwrap().device_id() + async fn device_id(&self) -> String { + self.gpu_obj.lock().await.device_id().await } #[dbus_interface(property)] - fn subdevice(&self) -> String { - self.gpu_obj.lock().unwrap().subdevice() + async fn subdevice(&self) -> String { + self.gpu_obj.lock().await.subdevice().await } #[dbus_interface(property)] - fn subdevice_id(&self) -> String { - self.gpu_obj.lock().unwrap().subdevice_id() + async fn subdevice_id(&self) -> String { + self.gpu_obj.lock().await.subdevice_id().await } #[dbus_interface(property)] - fn subvendor_id(&self) -> String { - self.gpu_obj.lock().unwrap().subvendor_id() + async fn subvendor_id(&self) -> String { + self.gpu_obj.lock().await.subvendor_id().await } #[dbus_interface(property)] - fn revision_id(&self) -> String { - self.gpu_obj.lock().unwrap().revision_id() + async fn revision_id(&self) -> String { + self.gpu_obj.lock().await.revision_id().await } #[dbus_interface(property)] - fn clock_limit_mhz_min(&self) -> fdo::Result { - self.gpu_obj.lock().unwrap().clock_limit_mhz_min().map_err(|err| err.into()) + async fn clock_limit_mhz_min(&self) -> fdo::Result { + self.gpu_obj.lock().await.clock_limit_mhz_min().await.map_err(|err| err.into()) } #[dbus_interface(property)] - fn clock_limit_mhz_max(&self) -> fdo::Result { - self.gpu_obj.lock().unwrap().clock_limit_mhz_max().map_err(|err| err.into()) + async fn clock_limit_mhz_max(&self) -> fdo::Result { + self.gpu_obj.lock().await.clock_limit_mhz_max().await.map_err(|err| err.into()) } #[dbus_interface(property)] - fn clock_value_mhz_min(&self) -> fdo::Result { - self.gpu_obj.lock().unwrap().clock_value_mhz_min().map_err(|err| err.into()) + async fn clock_value_mhz_min(&self) -> fdo::Result { + self.gpu_obj.lock().await.clock_value_mhz_min().await.map_err(|err| err.into()) } #[dbus_interface(property)] - fn set_clock_value_mhz_min(&mut self, value: f64) -> fdo::Result<()> { - self.gpu_obj.lock().unwrap().set_clock_value_mhz_min(value).map_err(|err| err.into()) + async fn set_clock_value_mhz_min(&mut self, value: f64) -> fdo::Result<()> { + self.gpu_obj.lock().await.set_clock_value_mhz_min(value).await.map_err(|err| err.into()) } #[dbus_interface(property)] - fn clock_value_mhz_max(&self) -> fdo::Result { - self.gpu_obj.lock().unwrap().clock_value_mhz_max().map_err(|err| err.into()) + async fn clock_value_mhz_max(&self) -> fdo::Result { + self.gpu_obj.lock().await.clock_value_mhz_max().await.map_err(|err| err.into()) } #[dbus_interface(property)] - fn set_clock_value_mhz_max(&mut self, value: f64) -> fdo::Result<()> { - self.gpu_obj.lock().unwrap().set_clock_value_mhz_max(value).map_err(|err| err.into()) + async fn set_clock_value_mhz_max(&mut self, value: f64) -> fdo::Result<()> { + self.gpu_obj.lock().await.set_clock_value_mhz_max(value).await.map_err(|err| err.into()) } #[dbus_interface(property)] - fn manual_clock(&self) -> fdo::Result { - self.gpu_obj.lock().unwrap().manual_clock().map_err(|err| err.into()) + async fn manual_clock(&self) -> fdo::Result { + self.gpu_obj.lock().await.manual_clock().await.map_err(|err| err.into()) } #[dbus_interface(property)] - fn set_manual_clock(&mut self, enabled: bool) -> fdo::Result<()> { - self.gpu_obj.lock().unwrap().set_manual_clock(enabled).map_err(|err| err.into()) + async fn set_manual_clock(&mut self, enabled: bool) -> fdo::Result<()> { + self.gpu_obj.lock().await.set_manual_clock(enabled).await.map_err(|err| err.into()) } } @@ -187,7 +190,7 @@ impl GPUBus { #[dbus_interface(name = "org.shadowblip.GPU")] impl GPUBus { /// Returns a list of DBus paths to all GPU cards - pub fn enumerate_cards(&self) -> fdo::Result> { + pub async fn enumerate_cards(&self) -> fdo::Result> { let mut paths: Vec = Vec::new(); for item in &self.gpu_object_paths { @@ -200,7 +203,7 @@ impl GPUBus { } /// Returns a list of all detected gpu devices -pub fn get_gpus() -> Vec { +pub async fn get_gpus() -> Vec { let mut gpus = vec![]; let paths = fs::read_dir(DRM_PATH).unwrap(); for path in paths { @@ -216,19 +219,22 @@ pub fn get_gpus() -> Vec { } log::info!("Discovered gpu: {}", file_path); - let gpu = get_gpu(file_path); - if gpu.is_err() { - continue; + match get_gpu(file_path).await { + Ok(gpu) => { + gpus.push(gpu) + }, + Err(err) => { + log::error!("Error in get_gpu: {}", err); + continue; + } } - - gpus.push(gpu.unwrap()); } return gpus; } /// Returns the GPU instance for the given path in /sys/class/drm -pub fn get_gpu(path: String) -> Result { +pub async fn get_gpu(path: String) -> Result { let filename = path.split("/").last().unwrap(); let file_prefix = format!("{0}/{1}", path, "device"); let class_id = fs::read_to_string(format!("{0}/{1}", file_prefix, "class"))? @@ -343,49 +349,53 @@ pub fn get_gpu(path: String) -> Result { GPUDBusInterface::new( Arc::new( Mutex::new( - AMDGPU { - name: filename.to_string(), - path: path.clone(), - class: class.to_string(), - class_id, - vendor: "AMD".to_string(), - vendor_id, - device: device.unwrap_or("".to_string()), - device_id, - device_type: "".to_string(), - subdevice: subdevice.unwrap_or("".to_string()), - subdevice_id, - subvendor_id, - revision_id, - } + GPUDevices::AMDGPU( + AMDGPU { + name: filename.to_string(), + path: path.clone(), + class: class.to_string(), + class_id, + vendor: "AMD".to_string(), + vendor_id, + device: device.unwrap_or("".to_string()), + device_id, + device_type: "".to_string(), + subdevice: subdevice.unwrap_or("".to_string()), + subdevice_id, + subvendor_id, + revision_id, + } + ) ) ) - ) + ).await ), // Intel Implementation "Intel" | "GenuineIntel" | "Intel Corporation" => Ok( GPUDBusInterface::new( Arc::new( Mutex::new( - IntelGPU { - name: filename.to_string(), - path: path.clone(), - class: class.to_string(), - class_id, - vendor: "Intel".to_string(), - vendor_id, - device: device.unwrap_or("".to_string()), - device_id, - device_type: "".to_string(), - subdevice: subdevice.unwrap_or("".to_string()), - subdevice_id, - subvendor_id, - revision_id, - manual_clock: true, - } + GPUDevices::INTELGPU( + IntelGPU { + name: filename.to_string(), + path: path.clone(), + class: class.to_string(), + class_id, + vendor: "Intel".to_string(), + vendor_id, + device: device.unwrap_or("".to_string()), + device_id, + device_type: "".to_string(), + subdevice: subdevice.unwrap_or("".to_string()), + subdevice_id, + subvendor_id, + revision_id, + manual_clock: true, + } + ) ) ) - ) + ).await ), _ => { Err(std::io::Error::new( diff --git a/src/performance/gpu/dbus/mod.rs b/src/performance/gpu/dbus/mod.rs index 81bda77..0857e9d 100644 --- a/src/performance/gpu/dbus/mod.rs +++ b/src/performance/gpu/dbus/mod.rs @@ -1,2 +1,3 @@ pub mod tdp; -pub mod gpu; \ No newline at end of file +pub mod gpu; +pub mod devices; \ No newline at end of file diff --git a/src/performance/gpu/dbus/tdp.rs b/src/performance/gpu/dbus/tdp.rs index 68b8777..fd0250b 100644 --- a/src/performance/gpu/dbus/tdp.rs +++ b/src/performance/gpu/dbus/tdp.rs @@ -1,14 +1,15 @@ use std::sync::Arc; -use std::sync::Mutex; -use zbus::fdo::Error; use zbus::fdo; use zbus_macros::dbus_interface; +use tokio::sync::Mutex; + use crate::performance::gpu::tdp::TDPError; -use crate::performance::gpu::tdp::{TDPDevice, TDPResult}; +use crate::performance::gpu::tdp::TDPResult; +use crate::performance::gpu::dbus::devices::TDPDevices; pub struct GPUTDPDBusIface { - dev: Arc> + dev: Arc> } impl Into for TDPError { @@ -23,7 +24,7 @@ impl Into for TDPError { } impl GPUTDPDBusIface { - pub fn new(dev: Arc>) -> GPUTDPDBusIface { + pub fn new(dev: Arc>) -> GPUTDPDBusIface { GPUTDPDBusIface { dev } @@ -35,125 +36,69 @@ impl GPUTDPDBusIface { /// Get the currently set TDP value #[dbus_interface(property, name = "TDP")] - fn tdp(&self) -> fdo::Result { - match self.dev.lock() { - Ok(lck) => { - match lck.tdp() { - TDPResult::Ok(result) => Ok(result), - TDPResult::Err(err) => Err(err.into()) - } - }, - Err(err) => { - Err(Error::Failed(format!("Unable to lock mutex: {}", err))) - } + async fn tdp(&self) -> fdo::Result { + match self.dev.lock().await.tdp().await { + TDPResult::Ok(result) => Ok(result), + TDPResult::Err(err) => Err(err.into()) } } /// Sets the given TDP value #[dbus_interface(property, name = "TDP")] - fn set_tdp(&mut self, value: f64) -> fdo::Result<()> { - match self.dev.lock() { - Ok(mut lck) => { - match lck.set_tdp(value) { - TDPResult::Ok(result) => Ok(result), - TDPResult::Err(err) => Err(err.into()) - } - }, - Err(err) => { - Err(Error::Failed(format!("Unable to lock mutex: {}", err))) - } + async fn set_tdp(&mut self, value: f64) -> fdo::Result<()> { + match self.dev.lock().await.set_tdp(value).await { + TDPResult::Ok(result) => Ok(result), + TDPResult::Err(err) => Err(err.into()) } } /// The TDP boost for AMD is the total difference between the Fast PPT Limit /// and the STAPM limit. #[dbus_interface(property)] - fn boost(&self) -> fdo::Result { - match self.dev.lock() { - Ok(lck) => { - match lck.boost() { - TDPResult::Ok(result) => Ok(result), - TDPResult::Err(err) => Err(err.into()) - } - }, - Err(err) => { - Err(Error::Failed(format!("Unable to lock mutex: {}", err))) - } + async fn boost(&self) -> fdo::Result { + match self.dev.lock().await.boost().await { + TDPResult::Ok(result) => Ok(result), + TDPResult::Err(err) => Err(err.into()) } } #[dbus_interface(property)] - fn set_boost(&mut self, value: f64) -> fdo::Result<()> { - match self.dev.lock() { - Ok(mut lck) => { - match lck.set_boost(value) { - TDPResult::Ok(result) => Ok(result), - TDPResult::Err(err) => Err(err.into()) - } - }, - Err(err) => { - Err(Error::Failed(format!("Unable to lock mutex: {}", err))) - } + async fn set_boost(&mut self, value: f64) -> fdo::Result<()> { + match self.dev.lock().await.set_boost(value).await { + TDPResult::Ok(result) => Ok(result), + TDPResult::Err(err) => Err(err.into()) } } #[dbus_interface(property)] - fn thermal_throttle_limit_c(&self) -> fdo::Result { - match self.dev.lock() { - Ok(lck) => { - match lck.thermal_throttle_limit_c() { - TDPResult::Ok(result) => Ok(result), - TDPResult::Err(err) => Err(err.into()) - } - }, - Err(err) => { - Err(Error::Failed(format!("Unable to lock mutex: {}", err))) - } + async fn thermal_throttle_limit_c(&self) -> fdo::Result { + match self.dev.lock().await.thermal_throttle_limit_c().await { + TDPResult::Ok(result) => Ok(result), + TDPResult::Err(err) => Err(err.into()) } } #[dbus_interface(property)] - fn set_thermal_throttle_limit_c(&mut self, limit: f64) -> fdo::Result<()> { - match self.dev.lock() { - Ok(mut lck) => { - match lck.set_thermal_throttle_limit_c(limit) { - TDPResult::Ok(result) => Ok(result), - TDPResult::Err(err) => Err(err.into()) - } - }, - Err(err) => { - Err(Error::Failed(format!("Unable to lock mutex: {}", err))) - } + async fn set_thermal_throttle_limit_c(&mut self, limit: f64) -> fdo::Result<()> { + match self.dev.lock().await.set_thermal_throttle_limit_c(limit).await { + TDPResult::Ok(result) => Ok(result), + TDPResult::Err(err) => Err(err.into()) } } #[dbus_interface(property)] - fn power_profile(&self) -> fdo::Result { - match self.dev.lock() { - Ok(lck) => { - match lck.power_profile() { - TDPResult::Ok(result) => Ok(result), - TDPResult::Err(err) => Err(err.into()) - } - }, - Err(err) => { - Err(Error::Failed(format!("Unable to lock mutex: {}", err))) - } + async fn power_profile(&self) -> fdo::Result { + match self.dev.lock().await.power_profile().await { + TDPResult::Ok(result) => Ok(result), + TDPResult::Err(err) => Err(err.into()) } } #[dbus_interface(property)] - fn set_power_profile(&mut self, profile: String) -> fdo::Result<()> { - match self.dev.lock() { - Ok(mut lck) => { - match lck.set_power_profile(profile) { - TDPResult::Ok(result) => Ok(result), - TDPResult::Err(err) => Err(err.into()) - } - }, - Err(err) => { - Err(Error::Failed(format!("Unable to lock mutex: {}", err))) - } + async fn set_power_profile(&mut self, profile: String) -> fdo::Result<()> { + match self.dev.lock().await.set_power_profile(profile).await { + TDPResult::Ok(result) => Ok(result), + TDPResult::Err(err) => Err(err.into()) } } diff --git a/src/performance/gpu/intel/intelgpu.rs b/src/performance/gpu/intel/intelgpu.rs index 95aa84c..020993f 100644 --- a/src/performance/gpu/intel/intelgpu.rs +++ b/src/performance/gpu/intel/intelgpu.rs @@ -1,15 +1,16 @@ use std::{ fs::{self, OpenOptions}, io::Write, - sync::{ - Arc, Mutex - } + sync::Arc }; +use tokio::sync::Mutex; + use crate::constants::PREFIX; -use crate::performance::gpu::interface::GPUIface; -use crate::performance::gpu::{intel, tdp::TDPDevice}; +use crate::performance::gpu::interface::GPUDevice; +use crate::performance::gpu::intel; use crate::performance::gpu::interface::{GPUError, GPUResult}; +use crate::performance::gpu::dbus::devices::TDPDevices; #[derive(Debug, Clone)] pub struct IntelGPU { @@ -30,20 +31,22 @@ pub struct IntelGPU { } -impl GPUIface for IntelGPU { +impl GPUDevice for IntelGPU { - fn get_gpu_path(&self) -> String { - format!("{0}/GPU/{1}", PREFIX, self.name()) + async fn get_gpu_path(&self) -> String { + format!("{0}/GPU/{1}", PREFIX, self.name().await) } /// Returns the TDP DBus interface for this GPU - fn get_tdp_interface(&self) -> Option>> { + async fn get_tdp_interface(&self) -> Option>> { match self.class.as_str() { "integrated" => Some( Arc::new( Mutex::new( - intel::tdp::TDP::new( - self.path.clone() + TDPDevices::INTEL( + intel::tdp::TDP::new( + self.path.clone() + ) ) ) ) @@ -52,56 +55,56 @@ impl GPUIface for IntelGPU { } } - fn name(&self) -> String { + async fn name(&self) -> String { self.name.clone() } - fn path(&self) -> String { + async fn path(&self) -> String { self.path.clone() } - fn class(&self) -> String { + async fn class(&self) -> String { self.class.clone() } - fn class_id(&self) -> String { + async fn class_id(&self) -> String { self.class_id.clone() } - fn vendor(&self) -> String { + async fn vendor(&self) -> String { self.vendor.clone() } - fn vendor_id(&self) -> String { + async fn vendor_id(&self) -> String { self.vendor_id.clone() } - fn device(&self) -> String { + async fn device(&self) -> String { self.device.clone() } - fn device_id(&self) -> String { + async fn device_id(&self) -> String { self.device_id.clone() } - fn subdevice(&self) -> String { + async fn subdevice(&self) -> String { self.subdevice.clone() } - fn subdevice_id(&self) -> String { + async fn subdevice_id(&self) -> String { self.subdevice_id.clone() } - fn subvendor_id(&self) -> String { + async fn subvendor_id(&self) -> String { self.subvendor_id.clone() } - fn revision_id(&self) -> String { + async fn revision_id(&self) -> String { self.revision_id.clone() } - fn clock_limit_mhz_min(&self) -> GPUResult { - let path = format!("{0}/{1}", self.path(), "gt_RPn_freq_mhz"); + async fn clock_limit_mhz_min(&self) -> GPUResult { + let path = format!("{0}/{1}", self.path().await, "gt_RPn_freq_mhz"); let result = fs::read_to_string(path); let limit = result .map_err(|err| GPUError::IOError(err.to_string()))? @@ -112,8 +115,8 @@ impl GPUIface for IntelGPU { return Ok(limit); } - fn clock_limit_mhz_max(&self) -> GPUResult { - let path = format!("{0}/{1}", self.path(), "gt_RP0_freq_mhz"); + async fn clock_limit_mhz_max(&self) -> GPUResult { + let path = format!("{0}/{1}", self.path().await, "gt_RP0_freq_mhz"); let limit = fs::read_to_string(path) .map_err(|err| GPUError::IOError(err.to_string()))? .trim() @@ -123,8 +126,8 @@ impl GPUIface for IntelGPU { return Ok(limit); } - fn clock_value_mhz_min(&self) -> GPUResult { - let path = format!("{0}/{1}", self.path(), "gt_min_freq_mhz"); + async fn clock_value_mhz_min(&self) -> GPUResult { + let path = format!("{0}/{1}", self.path().await, "gt_min_freq_mhz"); let result = fs::read_to_string(path); let value = result .map_err(|err| GPUError::IOError(err.to_string()))? @@ -135,7 +138,7 @@ impl GPUIface for IntelGPU { return Ok(value); } - fn set_clock_value_mhz_min(&mut self, value: f64) -> GPUResult<()> { + async fn set_clock_value_mhz_min(&mut self, value: f64) -> GPUResult<()> { if value == 0.0 { return Err(GPUError::InvalidArgument( "Cowardly refusing to set clock to 0MHz".to_string(), @@ -143,7 +146,7 @@ impl GPUIface for IntelGPU { } // Open the sysfs file to write to - let path = format!("{0}/{1}", self.path(), "gt_min_freq_mhz"); + let path = format!("{0}/{1}", self.path().await, "gt_min_freq_mhz"); let file = OpenOptions::new().write(true).open(path); // Write the value @@ -155,8 +158,8 @@ impl GPUIface for IntelGPU { return Ok(()); } - fn clock_value_mhz_max(&self) -> GPUResult { - let path = format!("{0}/{1}", self.path(), "gt_max_freq_mhz"); + async fn clock_value_mhz_max(&self) -> GPUResult { + let path = format!("{0}/{1}", self.path().await, "gt_max_freq_mhz"); let result = fs::read_to_string(path); let value = result .map_err(|err| GPUError::IOError(err.to_string()))? @@ -167,7 +170,7 @@ impl GPUIface for IntelGPU { return Ok(value); } - fn set_clock_value_mhz_max(&mut self, value: f64) -> GPUResult<()> { + async fn set_clock_value_mhz_max(&mut self, value: f64) -> GPUResult<()> { if value == 0.0 { return Err(GPUError::InvalidArgument( "Cowardly refusing to set clock to 0MHz".to_string(), @@ -175,7 +178,7 @@ impl GPUIface for IntelGPU { } // Open the sysfs file to write to - let path = format!("{0}/{1}", self.path(), "gt_max_freq_mhz"); + let path = format!("{0}/{1}", self.path().await, "gt_max_freq_mhz"); let file = OpenOptions::new().write(true).open(path); // Write the value @@ -187,11 +190,11 @@ impl GPUIface for IntelGPU { return Ok(()); } - fn manual_clock(&self) -> GPUResult { + async fn manual_clock(&self) -> GPUResult { return Ok(self.manual_clock.clone()); } - fn set_manual_clock(&mut self, enabled: bool) -> GPUResult<()> { + async fn set_manual_clock(&mut self, enabled: bool) -> GPUResult<()> { self.manual_clock = enabled; return Ok(()); } diff --git a/src/performance/gpu/intel/tdp.rs b/src/performance/gpu/intel/tdp.rs index cb92a75..c56b517 100644 --- a/src/performance/gpu/intel/tdp.rs +++ b/src/performance/gpu/intel/tdp.rs @@ -15,8 +15,7 @@ impl TDP { } impl TDPDevice for TDP { - - fn tdp(&self) -> TDPResult { + async fn tdp(&self) -> TDPResult { let path = "/sys/class/powercap/intel-rapl/intel-rapl:0/constraint_0_power_limit_uw"; let result = fs::read_to_string(path); let content = result.map_err(|err| TDPError::IOError(err.to_string()))?; @@ -33,7 +32,7 @@ impl TDPDevice for TDP { Ok(long_tdp / 1000000.0) } - fn set_tdp(&mut self, value: f64) -> TDPResult<()> { + async fn set_tdp(&mut self, value: f64) -> TDPResult<()> { if value < 1.0 { let err = "Cowardly refusing to set TDP less than 1"; log::warn!("{}", err); @@ -42,7 +41,7 @@ impl TDPDevice for TDP { // Get the current boost value so the peak tdp can be set *boost* // distance away. - let boost = self.boost()?; + let boost = self.boost().await?; // Open the sysfs file to write to let path = "/sys/class/powercap/intel-rapl/intel-rapl:0/constraint_0_power_limit_uw"; @@ -58,10 +57,10 @@ impl TDPDevice for TDP { .map_err(|err| TDPError::IOError(err.to_string()))?; // Update the boost value - Ok(self.set_boost(boost)?) + Ok(self.set_boost(boost).await?) } - fn boost(&self) -> TDPResult { + async fn boost(&self) -> TDPResult { let path = "/sys/class/powercap/intel-rapl/intel-rapl:0/constraint_2_power_limit_uw"; let result = fs::read_to_string(path); let content = result @@ -76,18 +75,18 @@ impl TDPDevice for TDP { } }; - let tdp = self.tdp()?; + let tdp = self.tdp().await?; Ok((peak_tdp / 1000000.0) - tdp) } - fn set_boost(&mut self, value: f64) -> TDPResult<()> { + async fn set_boost(&mut self, value: f64) -> TDPResult<()> { if value < 0.0 { let err = "Cowardly refusing to set TDP Boost less than 0"; log::warn!("{}", err); return Err(TDPError::InvalidArgument(String::from(err))); } - let tdp = self.tdp()?; + let tdp = self.tdp().await?; let boost = value.clone(); let short_tdp = if boost > 0.0 { ((boost / 2.0) + tdp) * 1000000.0 @@ -114,22 +113,22 @@ impl TDPDevice for TDP { .map_err(|err| TDPError::IOError(err.to_string())) } - fn thermal_throttle_limit_c(&self) -> TDPResult { + async fn thermal_throttle_limit_c(&self) -> TDPResult { log::error!("Thermal throttling not supported on intel gpu"); Err(TDPError::FeatureUnsupported) } - fn set_thermal_throttle_limit_c(&mut self, _limit: f64) -> TDPResult<()> { + async fn set_thermal_throttle_limit_c(&mut self, _limit: f64) -> TDPResult<()> { log::error!("Thermal throttling not supported on intel gpu"); Err(TDPError::FeatureUnsupported) } - fn power_profile(&self) -> TDPResult { + async fn power_profile(&self) -> TDPResult { log::error!("Power profiles not supported on intel gpu"); Err(TDPError::FeatureUnsupported) } - fn set_power_profile(&mut self, _profile: String) -> TDPResult<()> { + async fn set_power_profile(&mut self, _profile: String) -> TDPResult<()> { log::error!("Power profiles not supported on intel gpu"); Err(TDPError::FeatureUnsupported) } diff --git a/src/performance/gpu/interface.rs b/src/performance/gpu/interface.rs index aaa7de2..71d49ab 100644 --- a/src/performance/gpu/interface.rs +++ b/src/performance/gpu/interface.rs @@ -1,5 +1,8 @@ -use std::sync::{Arc, Mutex}; -use crate::performance::gpu::tdp::TDPDevice; +use std::sync::Arc; + +use tokio::sync::Mutex; + +use crate::performance::gpu::dbus::devices::TDPDevices; pub enum GPUError { //FeatureUnsupported, @@ -17,30 +20,29 @@ impl Into for GPUError { pub type GPUResult = Result; /// Represents the data contained in /sys/class/drm/cardX -pub trait GPUIface: Send + Sync { - - fn get_tdp_interface(&self) -> Option>>; - - fn get_gpu_path(&self) -> String; +pub trait GPUDevice: Send + Sync { + async fn get_tdp_interface(&self) -> Option>>; - fn name(&self) -> String; - fn path(&self) -> String; - fn class(&self) -> String; - fn class_id(&self) -> String; - fn vendor(&self) -> String; - fn vendor_id(&self) -> String; - fn device(&self) -> String; - fn device_id(&self) -> String; - fn subdevice(&self) -> String; - fn subdevice_id(&self) -> String; - fn subvendor_id(&self) -> String; - fn revision_id(&self) -> String; - fn clock_limit_mhz_min(&self) -> GPUResult; - fn clock_limit_mhz_max(&self) -> GPUResult; - fn clock_value_mhz_min(&self) -> GPUResult; - fn set_clock_value_mhz_min(&mut self, value: f64) -> GPUResult<()>; - fn clock_value_mhz_max(&self) -> GPUResult; - fn set_clock_value_mhz_max(&mut self, value: f64) -> GPUResult<()>; - fn manual_clock(&self) -> GPUResult; - fn set_manual_clock(&mut self, enabled: bool) -> GPUResult<()>; + async fn get_gpu_path(&self) -> String; + + async fn name(&self) -> String; + async fn path(&self) -> String; + async fn class(&self) -> String; + async fn class_id(&self) -> String; + async fn vendor(&self) -> String; + async fn vendor_id(&self) -> String; + async fn device(&self) -> String; + async fn device_id(&self) -> String; + async fn subdevice(&self) -> String; + async fn subdevice_id(&self) -> String; + async fn subvendor_id(&self) -> String; + async fn revision_id(&self) -> String; + async fn clock_limit_mhz_min(&self) -> GPUResult; + async fn clock_limit_mhz_max(&self) -> GPUResult; + async fn clock_value_mhz_min(&self) -> GPUResult; + async fn set_clock_value_mhz_min(&mut self, value: f64) -> GPUResult<()>; + async fn clock_value_mhz_max(&self) -> GPUResult; + async fn set_clock_value_mhz_max(&mut self, value: f64) -> GPUResult<()>; + async fn manual_clock(&self) -> GPUResult; + async fn set_manual_clock(&mut self, enabled: bool) -> GPUResult<()>; } diff --git a/src/performance/gpu/tdp.rs b/src/performance/gpu/tdp.rs index 6f78411..fc1febc 100644 --- a/src/performance/gpu/tdp.rs +++ b/src/performance/gpu/tdp.rs @@ -14,14 +14,12 @@ impl Into for TDPError { pub type TDPResult = Result; pub trait TDPDevice : Sync + Send { - - fn tdp(&self) -> TDPResult; - fn set_tdp(&mut self, value: f64) -> TDPResult<()>; - fn boost(&self) -> TDPResult; - fn set_boost(&mut self, value: f64) -> TDPResult<()>; - fn thermal_throttle_limit_c(&self) -> TDPResult; - fn set_thermal_throttle_limit_c(&mut self, limit: f64) -> TDPResult<()>; - fn power_profile(&self) -> TDPResult; - fn set_power_profile(&mut self, profile: String) -> TDPResult<()>; - + async fn tdp(&self) -> TDPResult; + async fn set_tdp(&mut self, value: f64) -> TDPResult<()>; + async fn boost(&self) -> TDPResult; + async fn set_boost(&mut self, value: f64) -> TDPResult<()>; + async fn thermal_throttle_limit_c(&self) -> TDPResult; + async fn set_thermal_throttle_limit_c(&mut self, limit: f64) -> TDPResult<()>; + async fn power_profile(&self) -> TDPResult; + async fn set_power_profile(&mut self, profile: String) -> TDPResult<()>; } \ No newline at end of file