From 5614937012362066caafcc05808cd67059e84414 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Mon, 2 Jan 2023 09:04:07 -0500 Subject: [PATCH] Implement full generic driver to simplify custom implementations --- backend/Cargo.lock | 129 +++++++++++++++++++++ backend/Cargo.toml | 1 + backend/src/settings/detect/auto_detect.rs | 4 +- backend/src/settings/generic/cpu.rs | 75 ++++++++---- backend/src/settings/generic/gpu.rs | 43 +++++-- backend/src/settings/generic/mod.rs | 2 + backend/src/settings/generic/traits.rs | 8 ++ backend/src/settings/generic_amd/cpu.rs | 50 +++++++- backend/src/settings/generic_amd/gpu.rs | 6 +- 9 files changed, 278 insertions(+), 40 deletions(-) create mode 100644 backend/src/settings/generic/traits.rs diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 290e4a9..4a85e0f 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -102,6 +102,28 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "bindgen" +version = "0.63.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36d860121800b2a9a94f9b5604b332d5cffb234ce17609ea479d723dbc9d3885" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -149,6 +171,15 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -170,6 +201,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "clang-sys" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "cpufeatures" version = "0.2.5" @@ -217,6 +259,12 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + [[package]] name = "encoding_rs" version = "0.8.31" @@ -323,6 +371,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + [[package]] name = "h2" version = "0.3.15" @@ -481,12 +535,34 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + [[package]] name = "limits_core" version = "0.1.0" @@ -526,6 +602,12 @@ dependencies = [ "unicase", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.6.2" @@ -565,6 +647,16 @@ dependencies = [ "twoway", ] +[[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num_cpus" version = "1.14.0" @@ -602,6 +694,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "percent-encoding" version = "2.2.0" @@ -660,6 +758,7 @@ dependencies = [ "limits_core", "log", "regex", + "ryzenadj-rs", "serde", "serde_json", "simplelog", @@ -763,6 +862,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustls-pemfile" version = "0.2.1" @@ -778,6 +883,13 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +[[package]] +name = "ryzenadj-rs" +version = "0.1.0" +dependencies = [ + "bindgen", +] + [[package]] name = "safemem" version = "0.3.3" @@ -855,6 +967,12 @@ dependencies = [ "digest", ] +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + [[package]] name = "simplelog" version = "0.12.0" @@ -1265,6 +1383,17 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "which" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" +dependencies = [ + "either", + "libc", + "once_cell", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/backend/Cargo.toml b/backend/Cargo.toml index fab0846..8f8daec 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -21,6 +21,7 @@ simplelog = "0.12" # limits & driver functionality limits_core = { version = "0.1.0", path = "./limits_core" } regex = "1" +ryzenadj-rs = { version = "0.1", path = "../../ryzenadj-rs" } # ureq's tls feature does not like musl targets ureq = { version = "2.5", features = ["json", "gzip", "brotli", "charset"], default-features = false, optional = true } diff --git a/backend/src/settings/detect/auto_detect.rs b/backend/src/settings/detect/auto_detect.rs index e7fb679..a85e6a5 100644 --- a/backend/src/settings/detect/auto_detect.rs +++ b/backend/src/settings/detect/auto_detect.rs @@ -97,7 +97,7 @@ pub fn auto_detect0(settings_opt: Option, json_path: std::path::Pa let cpu_driver: Box = match cpus { CpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Cpus::from_json(settings.cpus.clone(), settings.version)), CpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Cpus::from_json(settings.cpus.clone(), settings.version)), - CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::from_json_and_limits(settings.cpus.clone(), settings.version, x)), + CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::::from_json_and_limits(settings.cpus.clone(), settings.version, x)), CpuLimit::GenericAMD(x) => Box::new(crate::settings::generic_amd::Cpus::from_json_and_limits(settings.cpus.clone(), settings.version, x)), CpuLimit::Unknown => Box::new(crate::settings::unknown::Cpus::from_json(settings.cpus.clone(), settings.version)), }; @@ -131,7 +131,7 @@ pub fn auto_detect0(settings_opt: Option, json_path: std::path::Pa let cpu_driver: Box = match cpus { CpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Cpus::system_default()), CpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Cpus::system_default()), - CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::from_limits(x)), + CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::::from_limits(x)), CpuLimit::GenericAMD(x) => Box::new(crate::settings::generic_amd::Cpus::from_limits(x)), CpuLimit::Unknown => Box::new(crate::settings::unknown::Cpus::system_default()), }; diff --git a/backend/src/settings/generic/cpu.rs b/backend/src/settings/generic/cpu.rs index f1df70e..fcf90c9 100644 --- a/backend/src/settings/generic/cpu.rs +++ b/backend/src/settings/generic/cpu.rs @@ -1,23 +1,24 @@ -use std::convert::Into; +use std::convert::{Into, AsMut, AsRef}; use limits_core::json::GenericCpuLimit; -use crate::settings::MinMax; +use crate::settings::{MinMax, min_max_from_json}; use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::{TCpus, TCpu}; use crate::persist::CpuJson; +use super::FromGenericCpuInfo; const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present"; const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control"; #[derive(Debug, Clone)] -pub struct Cpus { - pub cpus: Vec, +pub struct Cpus + AsRef + TCpu> { + pub cpus: Vec, pub smt: bool, pub smt_capable: bool, } -impl OnSet for Cpus { +impl + AsRef + TCpu + OnSet> OnSet for Cpus { fn on_set(&mut self) -> Result<(), SettingError> { if self.smt_capable { // toggle SMT @@ -44,14 +45,14 @@ impl OnSet for Cpus { } } for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() { - cpu.state.do_set_online = self.smt || i % 2 == 0 || !self.smt_capable; + cpu.as_mut().state.do_set_online = self.smt || i % 2 == 0 || !self.smt_capable; cpu.on_set()?; } Ok(()) } } -impl OnResume for Cpus { +impl + AsRef + TCpu + OnResume> OnResume for Cpus { fn on_resume(&self) -> Result<(), SettingError> { for cpu in &self.cpus { cpu.on_resume()?; @@ -60,7 +61,7 @@ impl OnResume for Cpus { } } -impl Cpus { +impl + AsRef + TCpu + FromGenericCpuInfo> Cpus { pub fn cpu_count() -> Option { let mut data: String = usdpl_back::api::files::read_single(CPU_PRESENT_PATH) .unwrap_or_else(|_| "0-7".to_string() /* Steam Deck's default */); @@ -86,7 +87,7 @@ impl Cpus { let (_, can_smt) = Self::system_smt_capabilities(); let mut new_cpus = Vec::with_capacity(cpu_count); for i in 0..cpu_count { - let new_cpu = Cpu::from_limits(i, limits.clone()); + let new_cpu = C::from_limits(i, limits.clone()); new_cpus.push(new_cpu); } Self { @@ -108,8 +109,8 @@ impl Cpus { break; } } - let new_cpu = Cpu::from_json_and_limits(cpu, version, i, limits.clone()); - smt_disabled &= new_cpu.online as usize != i % 2; + let mut new_cpu = C::from_json_and_limits(cpu, version, i, limits.clone()); + smt_disabled &= *new_cpu.online() as usize != i % 2; result.push(new_cpu); } if let Some(max_cpus) = max_cpus { @@ -128,17 +129,17 @@ impl Cpus { } } -impl TCpus for Cpus { +impl + AsRef + TCpu + OnResume + OnSet> TCpus for Cpus { fn limits(&self) -> crate::api::CpusLimits { crate::api::CpusLimits { - cpus: self.cpus.iter().map(|x| x.limits()).collect(), + cpus: self.cpus.iter().map(|x| x.as_ref().limits()).collect(), count: self.cpus.len(), smt_capable: self.smt_capable, } } fn json(&self) -> Vec { - self.cpus.iter().map(|x| x.to_owned().into()).collect() + self.cpus.iter().map(|x| x.as_ref().to_owned().into()).collect() } fn cpus(&mut self) -> Vec<&mut dyn TCpu> { @@ -162,18 +163,40 @@ impl TCpus for Cpus { pub struct Cpu { pub online: bool, pub governor: String, + pub clock_limits: Option>, limits: GenericCpuLimit, index: usize, state: crate::state::steam_deck::Cpu, } - impl Cpu { #[inline] - pub fn from_limits(cpu_index: usize, limits: GenericCpuLimit) -> Self { + pub fn index(&self) -> usize { + self.index + } +} + +impl AsRef for Cpu { + #[inline] + fn as_ref(&self) -> &Cpu { + self + } +} + +impl AsMut for Cpu { + #[inline] + fn as_mut(&mut self) -> &mut Cpu { + self + } +} + +impl FromGenericCpuInfo for Cpu { + #[inline] + fn from_limits(cpu_index: usize, limits: GenericCpuLimit) -> Self { Self { online: true, governor: "schedutil".to_owned(), + clock_limits: None, limits, index: cpu_index, state: crate::state::steam_deck::Cpu::default(), @@ -181,11 +204,17 @@ impl Cpu { } #[inline] - pub fn from_json_and_limits(other: CpuJson, version: u64, i: usize, limits: GenericCpuLimit) -> Self { + fn from_json_and_limits(other: CpuJson, version: u64, i: usize, limits: GenericCpuLimit) -> Self { + let clock_lims = if limits.clock_min.is_some() && limits.clock_max.is_some() { + other.clock_limits.map(|x| min_max_from_json(x, version)) + } else { + None + }; match version { 0 => Self { online: other.online, governor: other.governor, + clock_limits: clock_lims, limits, index: i, state: crate::state::steam_deck::Cpu::default(), @@ -193,13 +222,16 @@ impl Cpu { _ => Self { online: other.online, governor: other.governor, + clock_limits: clock_lims, limits, index: i, state: crate::state::steam_deck::Cpu::default(), }, } } +} +impl Cpu { fn set_all(&mut self) -> Result<(), SettingError> { // set cpu online/offline if self.index != 0 && self.state.do_set_online { // cpu0 cannot be disabled @@ -270,7 +302,7 @@ impl Into for Cpu { fn into(self) -> CpuJson { CpuJson { online: self.online, - clock_limits: None, + clock_limits: self.clock_limits.map(|x| x.into()), governor: self.governor, } } @@ -305,12 +337,13 @@ impl TCpu for Cpu { } fn clock_limits(&mut self, limits: Option>) { - self.limits.clock_min = limits.clone(); - self.limits.clock_max = limits.clone(); + if self.limits.clock_min.is_some() && self.limits.clock_max.is_some() { + self.clock_limits = limits; + } } fn get_clock_limits(&self) -> Option<&MinMax> { - self.limits.clock_max.as_ref() + self.clock_limits.as_ref() } } diff --git a/backend/src/settings/generic/gpu.rs b/backend/src/settings/generic/gpu.rs index 5a92bfd..aa1a111 100644 --- a/backend/src/settings/generic/gpu.rs +++ b/backend/src/settings/generic/gpu.rs @@ -2,14 +2,17 @@ use std::convert::Into; use limits_core::json::GenericGpuLimit; -use crate::settings::MinMax; +use crate::settings::{MinMax, min_max_from_json}; use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::TGpu; use crate::persist::GpuJson; #[derive(Debug, Clone)] pub struct Gpu { - slow_memory: bool, // ignored + slow_memory: bool, + fast_ppt: Option, + slow_ppt: Option, + clock_limits: Option>, limits: GenericGpuLimit, } @@ -30,13 +33,24 @@ impl Gpu { pub fn from_limits(limits: limits_core::json::GenericGpuLimit) -> Self { Self { slow_memory: false, + fast_ppt: None, + slow_ppt: None, + clock_limits: None, limits, } } - pub fn from_json_and_limits(_other: GpuJson, _version: u64, limits: limits_core::json::GenericGpuLimit) -> Self { + pub fn from_json_and_limits(other: GpuJson, version: u64, limits: limits_core::json::GenericGpuLimit) -> Self { + let clock_lims = if limits.clock_min.is_some() && limits.clock_max.is_some() { + other.clock_limits.map(|x| min_max_from_json(x, version)) + } else { + None + }; Self { slow_memory: false, + fast_ppt: if limits.fast_ppt.is_some() {other.fast_ppt} else {None}, + slow_ppt: if limits.slow_ppt.is_some() {other.slow_ppt} else {None}, + clock_limits: clock_lims, limits, } } @@ -46,9 +60,9 @@ impl Into for Gpu { #[inline] fn into(self) -> GpuJson { GpuJson { - fast_ppt: None, - slow_ppt: None, - clock_limits: None, + fast_ppt: self.fast_ppt, + slow_ppt: self.slow_ppt, + clock_limits: self.clock_limits.map(|x| x.into()), slow_memory: false, } } @@ -86,18 +100,27 @@ impl TGpu for Gpu { self.clone().into() } - fn ppt(&mut self, _fast: Option, _slow: Option) { + fn ppt(&mut self, fast: Option, slow: Option) { + if self.limits.fast_ppt.is_some() { + self.fast_ppt = fast; + } + if self.limits.slow_ppt.is_some() { + self.slow_ppt = slow; + } } fn get_ppt(&self) -> (Option, Option) { - (None, None) + (self.fast_ppt, self.slow_ppt) } - fn clock_limits(&mut self, _limits: Option>) { + fn clock_limits(&mut self, limits: Option>) { + if self.limits.clock_min.is_some() && self.limits.clock_max.is_some() { + self.clock_limits = limits; + } } fn get_clock_limits(&self) -> Option<&MinMax> { - None + self.clock_limits.as_ref() } fn slow_memory(&mut self) -> &mut bool { diff --git a/backend/src/settings/generic/mod.rs b/backend/src/settings/generic/mod.rs index 2039cae..6989a23 100644 --- a/backend/src/settings/generic/mod.rs +++ b/backend/src/settings/generic/mod.rs @@ -1,7 +1,9 @@ mod battery; mod cpu; mod gpu; +mod traits; pub use battery::Battery; pub use cpu::{Cpu, Cpus}; pub use gpu::Gpu; +pub use traits::FromGenericCpuInfo; diff --git a/backend/src/settings/generic/traits.rs b/backend/src/settings/generic/traits.rs new file mode 100644 index 0000000..bf51e7f --- /dev/null +++ b/backend/src/settings/generic/traits.rs @@ -0,0 +1,8 @@ +use limits_core::json::GenericCpuLimit; +use crate::persist::CpuJson; + +pub trait FromGenericCpuInfo { + fn from_limits(cpu_index: usize, limits: GenericCpuLimit) -> Self; + + fn from_json_and_limits(other: CpuJson, version: u64, cpu_index: usize, limits: GenericCpuLimit) -> Self; +} diff --git a/backend/src/settings/generic_amd/cpu.rs b/backend/src/settings/generic_amd/cpu.rs index 312f8e3..e698c72 100644 --- a/backend/src/settings/generic_amd/cpu.rs +++ b/backend/src/settings/generic_amd/cpu.rs @@ -1,12 +1,12 @@ use crate::persist::CpuJson; use crate::settings::MinMax; -use crate::settings::generic::{Cpu as GenericCpu, Cpus as GenericCpus}; +use crate::settings::generic::{Cpu as GenericCpu, Cpus as GenericCpus, FromGenericCpuInfo}; use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::{TCpus, TCpu}; #[derive(Debug)] pub struct Cpus { - generic: GenericCpus, + generic: GenericCpus, } impl Cpus { @@ -68,6 +68,48 @@ pub struct Cpu { generic: GenericCpu, } +impl FromGenericCpuInfo for Cpu { + fn from_limits(cpu_index: usize, limits: limits_core::json::GenericCpuLimit) -> Self { + let gen = GenericCpu::from_limits(cpu_index, limits.clone()); + Self { + generic: gen, + } + } + + fn from_json_and_limits(other: CpuJson, version: u64, cpu_index: usize, limits: limits_core::json::GenericCpuLimit) -> Self { + let gen = GenericCpu::from_json_and_limits(other, version, cpu_index, limits); + Self { + generic: gen, + } + } +} + +impl AsRef for Cpu { + fn as_ref(&self) -> &GenericCpu { + &self.generic + } +} + +impl AsMut for Cpu { + fn as_mut(&mut self) -> &mut GenericCpu { + &mut self.generic + } +} + +impl OnResume for Cpu { + fn on_resume(&self) -> Result<(), SettingError> { + self.generic.on_resume() + // TODO + } +} + +impl OnSet for Cpu { + fn on_set(&mut self) -> Result<(), SettingError> { + self.generic.on_set() + // TODO + } +} + impl TCpu for Cpu { fn online(&mut self) -> &mut bool { self.generic.online() @@ -82,10 +124,10 @@ impl TCpu for Cpu { } fn clock_limits(&mut self, limits: Option>) { - self.generic.clock_limits(limits) // TODO + self.generic.clock_limits(limits) } fn get_clock_limits(&self) -> Option<&MinMax> { - self.generic.get_clock_limits() // TODO + self.generic.get_clock_limits() } } diff --git a/backend/src/settings/generic_amd/gpu.rs b/backend/src/settings/generic_amd/gpu.rs index 18f8b94..8c9654c 100644 --- a/backend/src/settings/generic_amd/gpu.rs +++ b/backend/src/settings/generic_amd/gpu.rs @@ -47,15 +47,15 @@ impl TGpu for Gpu { } fn ppt(&mut self, fast: Option, slow: Option) { - // TODO + self.generic.ppt(fast, slow) } fn get_ppt(&self) -> (Option, Option) { - self.generic.get_ppt() // TODO + self.generic.get_ppt() } fn clock_limits(&mut self, limits: Option>) { - // TODO + self.generic.clock_limits(limits) } fn get_clock_limits(&self) -> Option<&MinMax> {