Add missing functionality needed for PowerTools drivers
This commit is contained in:
parent
95e52020f9
commit
867b937cd8
8 changed files with 427 additions and 21 deletions
|
@ -4,3 +4,8 @@ pub fn write_confirm_pp_od_clk_voltage(sysfs: &BasicEntityPath) -> Result<(), po
|
|||
sysfs.set(super::DEVICE_PP_OD_CLK_VOLTAGE, super::pp_od_clk_voltage::PpOdClkVoltageWriteValues::C.sysfs_str())
|
||||
.map_err(powerbox::PowerError::Io)
|
||||
}
|
||||
|
||||
pub fn write_reset_pp_od_clk_voltage(sysfs: &BasicEntityPath) -> Result<(), powerbox::PowerError> {
|
||||
sysfs.set(super::DEVICE_PP_OD_CLK_VOLTAGE, super::pp_od_clk_voltage::PpOdClkVoltageWriteValues::R.sysfs_str())
|
||||
.map_err(powerbox::PowerError::Io)
|
||||
}
|
||||
|
|
|
@ -8,14 +8,18 @@ use super::AmdGpu;
|
|||
|
||||
pub enum AmdGpuOp {
|
||||
PpDpm(super::AmdGpuPpDpm),
|
||||
PpOdClk(super::AmdGpuPpOdClkVoltage),
|
||||
Commit(AmdGpuCommit),
|
||||
Reset(AmdGpuReset),
|
||||
}
|
||||
|
||||
impl PowerOp for AmdGpuOp {
|
||||
fn is_eq_op(&self, other: &Self) -> bool {
|
||||
match self {
|
||||
Self::PpDpm(x) => if let Self::PpDpm(other) = other { x.is_eq_op(other) } else { false },
|
||||
Self::PpOdClk(x) => if let Self::PpOdClk(other) = other { x.is_eq_op(other) } else { false },
|
||||
Self::Commit(_) => matches!(other, Self::Commit(_)),
|
||||
Self::Reset(_) => matches!(other, Self::Reset(_)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,13 +36,20 @@ impl Power<AmdGpuOp> for AmdGpu {
|
|||
}
|
||||
|
||||
fn supported_operations(&self) -> Box<dyn core::iter::Iterator<Item=AmdGpuOp>> {
|
||||
// TODO
|
||||
Box::new(core::iter::empty())
|
||||
Box::new(
|
||||
Power::<super::AmdGpuPpDpm, _>::supported_operations(self).map(core::convert::Into::<AmdGpuOp>::into)
|
||||
.chain(Power::<super::AmdGpuPpOdClkVoltage, _>::supported_operations(self).map(core::convert::Into::<AmdGpuOp>::into))
|
||||
.chain(Power::<AmdGpuCommit, _>::supported_operations(self).map(core::convert::Into::<AmdGpuOp>::into))
|
||||
.chain(Power::<AmdGpuReset, _>::supported_operations(self).map(core::convert::Into::<AmdGpuOp>::into))
|
||||
)
|
||||
}
|
||||
|
||||
fn act(&self, op: AmdGpuOp) -> Result<powerbox::primitives::Value, powerbox::PowerError> {
|
||||
match op {
|
||||
_ => Err(powerbox::PowerError::Unknown),
|
||||
AmdGpuOp::PpDpm(freq) => self.act(freq).map(powerbox::primitives::Value::into_any),
|
||||
AmdGpuOp::PpOdClk(clk) => self.act(clk).map(powerbox::primitives::Value::into_any),
|
||||
AmdGpuOp::Commit(c) => self.act(c).map(|_| powerbox::primitives::Value::Unknown),
|
||||
AmdGpuOp::Reset(r) => self.act(r).map(|_| powerbox::primitives::Value::Unknown),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,3 +96,43 @@ impl Into<AmdGpuOp> for AmdGpuCommit {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct AmdGpuReset;
|
||||
|
||||
impl PowerOp for AmdGpuReset {
|
||||
fn is_eq_op(&self, _other: &Self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl GpuPowerOp for AmdGpuReset {}
|
||||
|
||||
impl Power<AmdGpuReset, ()> for AmdGpu {
|
||||
fn is_on(&self) -> bool {
|
||||
self.is_enabled()
|
||||
}
|
||||
|
||||
fn is_available(&self) -> bool {
|
||||
self.is_compatible()
|
||||
}
|
||||
|
||||
fn supported_operations(&self) -> Box<dyn core::iter::Iterator<Item=AmdGpuReset>> {
|
||||
if self.sysfs.exists(&super::DEVICE_PP_OD_CLK_VOLTAGE) {
|
||||
Box::new(core::iter::once(AmdGpuReset))
|
||||
} else {
|
||||
Box::new(core::iter::empty())
|
||||
}
|
||||
}
|
||||
|
||||
fn act(&self, _: AmdGpuReset) -> Result<(), powerbox::PowerError> {
|
||||
super::common::write_reset_pp_od_clk_voltage(&self.sysfs)
|
||||
}
|
||||
}
|
||||
|
||||
impl GpuPower<AmdGpuReset, ()> for AmdGpu {}
|
||||
|
||||
impl Into<AmdGpuOp> for AmdGpuReset {
|
||||
fn into(self) -> AmdGpuOp {
|
||||
AmdGpuOp::Reset(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ mod pp_dpm_star;
|
|||
mod pp_od_clk_voltage;
|
||||
|
||||
pub use cpus::{AmdGpuCpuOp, AmdGpuCpuFreq, GetCoreMinFrequency, GetCoreMaxFrequency, SetCoreMinFrequency, SetCoreMaxFrequency, SetCoreLimits};
|
||||
pub use gpu::{AmdGpuOp, AmdGpuCommit};
|
||||
//pub use pp_od_clk_voltage::MinMax;
|
||||
pub use gpu::{AmdGpuOp, AmdGpuCommit, AmdGpuReset};
|
||||
pub use pp_od_clk_voltage::{AmdGpuPpOdInfo, AmdGpuPpOdClkVoltage, AmdGpuPpOdSclk, SetAmdGpuPpOdSclk, GetAmdGpuPpOdSclk};
|
||||
pub use pp_dpm_star::{AmdGpuPpDpm, AmdGpuFclk, GetAmdGpuFclk, SetAmdGpuFclk, AmdGpuMclk, GetAmdGpuMclk, SetAmdGpuMclk, AmdGpuSclk, GetAmdGpuSclk, SetAmdGpuSclk, AmdGpuSocclk, GetAmdGpuSocclk, SetAmdGpuSocclk};
|
||||
|
||||
use sysfuss::{BasicEntityPath, SysEntityAttributesExt};
|
||||
|
@ -39,6 +39,10 @@ impl AmdGpu {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn sysfs_path(&self) -> &'_ std::path::Path {
|
||||
self.sysfs.as_ref()
|
||||
}
|
||||
|
||||
pub(super) fn is_enabled(&self) -> bool {
|
||||
self.sysfs.attribute::<String>(DEVICE_ENABLE).is_ok_and(|val: String| val == "1")
|
||||
}
|
||||
|
|
|
@ -62,10 +62,16 @@ impl Power<AmdGpuPpDpm, Value<ValueMap<usize, Selectable<ClockFrequency>>>> for
|
|||
|
||||
impl GpuPower<AmdGpuPpDpm, Value<ValueMap<usize, Selectable<ClockFrequency>>>> for AmdGpu {}
|
||||
|
||||
impl Into<super::AmdGpuOp> for AmdGpuPpDpm {
|
||||
fn into(self) -> super::AmdGpuOp {
|
||||
super::AmdGpuOp::PpDpm(self)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! get_set_gen_impl {
|
||||
($alias:ident, $getter:ident, $setter:ident, $device_const:ident) => {
|
||||
pub struct $getter;
|
||||
pub struct $setter(Vec<usize>);
|
||||
pub struct $setter(pub Vec<usize>);
|
||||
|
||||
pub type $alias = GetSet<$getter, $setter>;
|
||||
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
use std::{borrow::Cow, collections::HashMap};
|
||||
|
||||
use powerbox::primitives::{ValueMap, ClockFrequency, Selectable, SpacedList, ValueMapParseErr};
|
||||
use powerbox::primitives::{ValueMap, Value, ClockFrequency, Selectable, SpacedList, ValueMapParseErr, GetSet};
|
||||
use powerbox::{Power, PowerOp, RatifiedPower};
|
||||
use sysfuss::SysEntityAttributesExt;
|
||||
|
||||
use crate::gpu::{GpuPower, GpuPowerOp};
|
||||
use super::AmdGpu;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||
|
@ -55,6 +60,7 @@ impl OdTableName {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn table_name(&self) -> Cow<'_, str> {
|
||||
match self {
|
||||
Self::SCLK => Cow::from("OD_SCLK"),
|
||||
|
@ -115,10 +121,10 @@ impl std::str::FromStr for PpOdClkVoltageReadValues {
|
|||
let mut table_end = table_start;
|
||||
let table_name = table_name_line.trim_end().trim_end_matches(|c: char| c == ':');
|
||||
let table_name = OdTableName::from_table_name(table_name);
|
||||
println!("table name: {}", table_name.table_name());
|
||||
//println!("table name: {}", table_name.table_name());
|
||||
let next_table_name_line;
|
||||
if let OdTableName::RANGE = table_name {
|
||||
println!("range table special case!");
|
||||
//println!("range table special case!");
|
||||
'range_table_loop: loop {
|
||||
let line = lines_iter.next();
|
||||
if let Some(line) = line.and_then(|line| is_valid_range_table_entry_line(line).then_some(line)) {
|
||||
|
@ -130,7 +136,7 @@ impl std::str::FromStr for PpOdClkVoltageReadValues {
|
|||
}
|
||||
|
||||
let table_str = &s[table_start..table_end-1];
|
||||
println!("table str: '{}'", table_str);
|
||||
//println!("table str: '{}'", table_str);
|
||||
match table_str.parse() {
|
||||
Ok(r_t) => range_table = Some(r_t),
|
||||
Err(ValueMapParseErr::InnerVal(v)) => return Err(ValueMapParseErr::InnerVal(v)),
|
||||
|
@ -150,7 +156,7 @@ impl std::str::FromStr for PpOdClkVoltageReadValues {
|
|||
}
|
||||
|
||||
let table_str = &s[table_start..table_end-1];
|
||||
println!("table str: '{}'", table_str);
|
||||
//println!("table str: '{}'", table_str);
|
||||
let new_table = table_str.parse()?;
|
||||
tables.insert(table_name, new_table);
|
||||
table_start = table_end;
|
||||
|
@ -191,13 +197,15 @@ pub(super) enum MinMax {
|
|||
pub(super) enum PpOdClkVoltageWriteValues {
|
||||
/// Something clock
|
||||
SCLK {
|
||||
limit: MinMax,
|
||||
point: usize,
|
||||
clockspeed: ClockFrequency,
|
||||
millivolts: Option<usize>,
|
||||
},
|
||||
/// Memory clock
|
||||
MCLK {
|
||||
limit: MinMax,
|
||||
point: usize,
|
||||
clockspeed: ClockFrequency,
|
||||
millivolts: usize,
|
||||
},
|
||||
/// Core clock
|
||||
CCLK {
|
||||
|
@ -217,17 +225,24 @@ pub(super) enum PpOdClkVoltageWriteValues {
|
|||
},
|
||||
/// Confirm (required to apply another other written value)
|
||||
C,
|
||||
/// Reset all related settings
|
||||
R,
|
||||
}
|
||||
|
||||
impl PpOdClkVoltageWriteValues {
|
||||
pub fn sysfs_str(&self) -> String {
|
||||
match self {
|
||||
Self::SCLK { limit, clockspeed } => format!("s {} {}", Self::limit_num(limit), Self::mhz_clock(clockspeed)),
|
||||
Self::MCLK { limit, clockspeed } => format!("m {} {}", Self::limit_num(limit), Self::mhz_clock(clockspeed)),
|
||||
Self::SCLK { point, clockspeed, millivolts } => if let Some(millivolts) = millivolts {
|
||||
format!("s {} {} {}", point, Self::mhz_clock(clockspeed), millivolts)
|
||||
} else {
|
||||
format!("s {} {}", point, Self::mhz_clock(clockspeed))
|
||||
},
|
||||
Self::MCLK { point, clockspeed, millivolts } => format!("m {} {} {}", point, Self::mhz_clock(clockspeed), millivolts),
|
||||
Self::CCLK { core, limit, clockspeed } => format!("p {} {} {}", core, Self::limit_num(limit), Self::mhz_clock(clockspeed)),
|
||||
Self::VC { point, clockspeed, millivolts } => format!("vc {} {} {}", point, Self::mhz_clock(clockspeed), millivolts),
|
||||
Self::VO { millivolts } => format!("vo {}", millivolts),
|
||||
Self::C => "c".to_owned(),
|
||||
Self::R => "r".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,6 +262,318 @@ impl PpOdClkVoltageWriteValues {
|
|||
}
|
||||
}
|
||||
|
||||
// Power impls
|
||||
|
||||
pub struct AmdGpuPpOdInfo {
|
||||
pub range: Option<SpacedList<ClockFrequency>>,
|
||||
pub levels: ValueMap<usize, Selectable<ClockFrequency>>,
|
||||
}
|
||||
|
||||
macro_rules! get_set_gen_impl {
|
||||
($alias:ident, $getter:ident, $setter:ident, $table:ident, $variant:ident) => {
|
||||
pub struct $getter;
|
||||
|
||||
pub type $alias = GetSet<$getter, $setter>;
|
||||
|
||||
// GetSet impl
|
||||
impl GpuPowerOp for $alias {}
|
||||
|
||||
impl Power<$alias, Value<AmdGpuPpOdInfo>> for AmdGpu {
|
||||
fn is_on(&self) -> bool {
|
||||
self.is_enabled()
|
||||
}
|
||||
|
||||
fn is_available(&self) -> bool {
|
||||
self.is_compatible()
|
||||
}
|
||||
|
||||
fn supported_operations(&self) -> Box<dyn core::iter::Iterator<Item=$alias>> {
|
||||
Box::new(
|
||||
Power::<$getter, _>::supported_operations(self).map(core::convert::Into::<$alias>::into)
|
||||
.chain(Power::<$setter, _>::supported_operations(self).map(core::convert::Into::<$alias>::into))
|
||||
)
|
||||
}
|
||||
|
||||
fn act(&self, op: $alias) -> Result<Value<AmdGpuPpOdInfo>, powerbox::PowerError> {
|
||||
match op {
|
||||
$alias::Get(clk) => self.act(clk).map(Value::Custom),
|
||||
$alias::Set(clk) => self.act(clk).map(|_| Value::Unknown),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GpuPower<$alias, Value<AmdGpuPpOdInfo>> for AmdGpu {}
|
||||
|
||||
impl core::convert::Into<AmdGpuPpOdClkVoltage> for $alias {
|
||||
fn into(self) -> AmdGpuPpOdClkVoltage {
|
||||
AmdGpuPpOdClkVoltage::$variant(self)
|
||||
}
|
||||
}
|
||||
|
||||
// Get impl
|
||||
impl PowerOp for $getter {
|
||||
fn is_eq_op(&self, _: &Self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl GpuPowerOp for $getter {}
|
||||
|
||||
impl Power<$getter, AmdGpuPpOdInfo> for AmdGpu {
|
||||
fn is_on(&self) -> bool {
|
||||
self.is_enabled()
|
||||
}
|
||||
|
||||
fn is_available(&self) -> bool {
|
||||
self.is_compatible()
|
||||
}
|
||||
|
||||
fn supported_operations(&self) -> Box<dyn core::iter::Iterator<Item=$getter>> {
|
||||
if let Ok(rv) = self.read_pp_od_clk_voltage() {
|
||||
if rv.tables.contains_key(&OdTableName::$table) {
|
||||
Box::new(core::iter::once($getter))
|
||||
} else {
|
||||
Box::new(core::iter::empty())
|
||||
}
|
||||
} else { Box::new(core::iter::empty()) }
|
||||
}
|
||||
|
||||
fn act(&self, _: $getter) -> Result<AmdGpuPpOdInfo, powerbox::PowerError> {
|
||||
match self.read_pp_od_clk_voltage() {
|
||||
Ok(mut rv) => {
|
||||
Ok(AmdGpuPpOdInfo {
|
||||
range: rv.ranges.map(|mut ranges| ranges.0.remove(&OdTableName::$table)).flatten(),
|
||||
levels: rv.tables.remove(&OdTableName::$table).unwrap_or_else(|| ValueMap(Default::default()))
|
||||
})
|
||||
},
|
||||
Err(sysfuss::EitherErr2::First(e)) => Err(powerbox::PowerError::Io(e)),
|
||||
Err(sysfuss::EitherErr2::Second(_)) => Err(powerbox::PowerError::Unknown),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GpuPower<$getter, AmdGpuPpOdInfo> for AmdGpu {}
|
||||
|
||||
impl core::convert::Into<$alias> for $getter {
|
||||
fn into(self) -> $alias {
|
||||
$alias::Get(self)
|
||||
}
|
||||
}
|
||||
|
||||
// Set impl
|
||||
impl PowerOp for $setter {
|
||||
fn is_eq_op(&self, _: &Self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl GpuPowerOp for $setter {}
|
||||
|
||||
impl Power<$setter, ()> for AmdGpu {
|
||||
fn is_on(&self) -> bool {
|
||||
self.is_enabled()
|
||||
}
|
||||
|
||||
fn is_available(&self) -> bool {
|
||||
self.is_compatible()
|
||||
}
|
||||
|
||||
fn supported_operations(&self) -> Box<dyn core::iter::Iterator<Item=$setter>> {
|
||||
if let Ok(rv) = self.read_pp_od_clk_voltage() {
|
||||
if rv.ranges.is_some_and(|ranges| ranges.0.contains_key(&OdTableName::$table)) {
|
||||
Box::new(core::iter::once($setter::filler_default()))
|
||||
} else {
|
||||
Box::new(core::iter::empty())
|
||||
}
|
||||
} else { Box::new(core::iter::empty()) }
|
||||
}
|
||||
|
||||
fn act(&self, op: $setter) -> Result<(), powerbox::PowerError> {
|
||||
let payload = op.write_payload();
|
||||
if !self.is_pdfpl_manual() {
|
||||
self.sysfs.set(
|
||||
super::DEVICE_POWER_DPM_FORCE_LIMITS_ATTRIBUTE,
|
||||
super::power_dpm_force_performance_level::PowerDpmForcePerformanceLevel::Manual.sysfs_str())
|
||||
.map_err(powerbox::PowerError::Io)?;
|
||||
}
|
||||
self.sysfs.set(super::DEVICE_PP_OD_CLK_VOLTAGE, payload.sysfs_str())
|
||||
.map_err(powerbox::PowerError::Io)?;
|
||||
if op.should_commit() {
|
||||
super::common::write_confirm_pp_od_clk_voltage(&self.sysfs)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RatifiedPower<$setter> for AmdGpu {
|
||||
fn is_possible(&self, op: &$setter) -> bool {
|
||||
if let Ok(gotten) = self.act($getter) {
|
||||
op.is_within_range(&gotten)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn clamp(&self, op: &mut $setter) -> bool {
|
||||
if let Ok(gotten) = self.act($getter) {
|
||||
op.clamp_to(&gotten);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GpuPower<$setter, ()> for AmdGpu {}
|
||||
|
||||
impl core::convert::Into<$alias> for $setter {
|
||||
fn into(self) -> $alias {
|
||||
$alias::Set(self)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub enum AmdGpuPpOdClkVoltage {
|
||||
Sclk(AmdGpuPpOdSclk),
|
||||
//MCLK(AmdGpuPpOdMclk),
|
||||
//VC(AmdGpuPpOdVc),
|
||||
//VO(AmdGpuPpOdVo),
|
||||
}
|
||||
|
||||
impl PowerOp for AmdGpuPpOdClkVoltage {
|
||||
fn is_eq_op(&self, other: &Self) -> bool {
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
match self {
|
||||
//Self::Fclk(f) => if let Self::Fclk(other) = other { f.is_eq_op(other) } else { false },
|
||||
//Self::Mclk(m) => if let Self::Mclk(other) = other { m.is_eq_op(other) } else { false },
|
||||
Self::Sclk(s) => if let Self::Sclk(other) = other { s.is_eq_op(other) } else { false },
|
||||
//Self::Socclk(soc) => if let Self::Socclk(other) = other { soc.is_eq_op(other) } else { false },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GpuPowerOp for AmdGpuPpOdClkVoltage {}
|
||||
|
||||
impl Power<AmdGpuPpOdClkVoltage, Value<AmdGpuPpOdInfo>> for AmdGpu {
|
||||
fn is_on(&self) -> bool {
|
||||
self.is_enabled()
|
||||
}
|
||||
|
||||
fn is_available(&self) -> bool {
|
||||
self.is_compatible()
|
||||
}
|
||||
|
||||
fn supported_operations(&self) -> Box<dyn core::iter::Iterator<Item=AmdGpuPpOdClkVoltage>> {
|
||||
Box::new(
|
||||
Power::<AmdGpuPpOdSclk, _>::supported_operations(self).map(core::convert::Into::<AmdGpuPpOdClkVoltage>::into)
|
||||
//.chain(Power::<AmdGpuMclk, _>::supported_operations(self).map(core::convert::Into::<AmdGpuPpOdClkVoltage>::into))
|
||||
//.chain(Power::<AmdGpuFclk, _>::supported_operations(self).map(core::convert::Into::<AmdGpuPpOdClkVoltage>::into))
|
||||
//.chain(Power::<AmdGpuSocclk, _>::supported_operations(self).map(core::convert::Into::<AmdGpuPpOdClkVoltage>::into))
|
||||
)
|
||||
}
|
||||
|
||||
fn act(&self, op: AmdGpuPpOdClkVoltage) -> Result<Value<AmdGpuPpOdInfo>, powerbox::PowerError> {
|
||||
match op {
|
||||
//AmdGpuPpOdClkVoltage::Fclk(clk) => self.act(clk),
|
||||
//AmdGpuPpOdClkVoltage::Mclk(clk) => self.act(clk),
|
||||
AmdGpuPpOdClkVoltage::Sclk(clk) => self.act(clk),
|
||||
//AmdGpuPpOdClkVoltage::Socclk(clk) => self.act(clk),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GpuPower<AmdGpuPpOdClkVoltage, Value<AmdGpuPpOdInfo>> for AmdGpu {}
|
||||
|
||||
impl Into<super::AmdGpuOp> for AmdGpuPpOdClkVoltage {
|
||||
fn into(self) -> super::AmdGpuOp {
|
||||
super::AmdGpuOp::PpOdClk(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SetAmdGpuPpOdSclk {
|
||||
pub level: usize,
|
||||
pub clockspeed: ClockFrequency,
|
||||
pub millivolts: Option<usize>,
|
||||
pub no_commit: bool,
|
||||
}
|
||||
|
||||
impl SetAmdGpuPpOdSclk {
|
||||
fn filler_default() -> Self {
|
||||
Self {
|
||||
level: 0,
|
||||
clockspeed: ClockFrequency {
|
||||
value: 1_000,
|
||||
si_prefix: 1_000_000,
|
||||
},
|
||||
millivolts: None,
|
||||
no_commit: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn write_payload(&self) -> PpOdClkVoltageWriteValues {
|
||||
PpOdClkVoltageWriteValues::SCLK {
|
||||
point: self.level,
|
||||
clockspeed: self.clockspeed,
|
||||
millivolts: self.millivolts,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn should_commit(&self) -> bool {
|
||||
!self.no_commit
|
||||
}
|
||||
|
||||
fn is_within_range(&self, get: &AmdGpuPpOdInfo) -> bool {
|
||||
get.levels.0.contains_key(&self.level)
|
||||
&& get.range.as_ref().is_some_and(|range|
|
||||
!range.0.is_empty()
|
||||
&& self.clockspeed.in_hz() > range.0[0].in_hz()
|
||||
&& self.clockspeed.in_hz() > range.0[range.0.len()-1].in_hz()
|
||||
)
|
||||
}
|
||||
|
||||
fn clamp_to(&mut self, get: &AmdGpuPpOdInfo) {
|
||||
if !get.levels.0.contains_key(&self.level) {
|
||||
let min = get.levels.0.keys().min().map(|x| *x).unwrap_or_default();
|
||||
let max = get.levels.0.keys().max().map(|x| *x).unwrap_or_default();
|
||||
if self.level > max {
|
||||
self.level = max;
|
||||
} else {
|
||||
self.level = min;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get_set_gen_impl!(AmdGpuPpOdSclk, GetAmdGpuPpOdSclk, SetAmdGpuPpOdSclk, SCLK, Sclk);
|
||||
|
||||
/*
|
||||
// System/engine clock (SCLK)
|
||||
pub struct EngineClock {
|
||||
limit: MinMax,
|
||||
clockspeed: ClockFrequency,
|
||||
}
|
||||
|
||||
/// Memory clock (MCLK)
|
||||
pub struct MemoryClock {
|
||||
limit: MinMax,
|
||||
clockspeed: ClockFrequency,
|
||||
}
|
||||
|
||||
/// Voltage curve (VC)
|
||||
pub struct VoltageCurve {
|
||||
point: usize,
|
||||
clockspeed: ClockFrequency,
|
||||
millivolts: usize,
|
||||
}
|
||||
|
||||
/// Voltage offset (VO)
|
||||
pub struct VoltageOffset {
|
||||
millivolts: isize,
|
||||
}*/
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
|
|
@ -31,6 +31,15 @@ impl AmdCpu {
|
|||
#[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))]
|
||||
{false}
|
||||
}
|
||||
|
||||
pub fn as_basic(&self) -> &'_ BasicCpu {
|
||||
&self.basic
|
||||
}
|
||||
|
||||
/// Create an AmdCpu without checking if it's compatible (use try_into() instead)
|
||||
pub fn new(basic: BasicCpu) -> Self {
|
||||
Self { basic, }
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::Deref for AmdCpu {
|
||||
|
|
|
@ -140,7 +140,7 @@ impl Power<SetSMT, ()> for BasicCpus {
|
|||
}
|
||||
|
||||
fn is_available(&self) -> bool {
|
||||
self.is_exists()
|
||||
self.sysfs.exists(&CPUS_SMT_CONTROL)
|
||||
}
|
||||
|
||||
fn supported_operations(&self) -> Box<dyn core::iter::Iterator<Item=SetSMT>> {
|
||||
|
@ -195,7 +195,7 @@ impl Power<GetSMT, bool> for BasicCpus {
|
|||
}
|
||||
|
||||
fn is_available(&self) -> bool {
|
||||
self.is_exists()
|
||||
self.sysfs.exists(&CPUS_SMT_ACTIVE)
|
||||
}
|
||||
|
||||
fn supported_operations(&self) -> Box<dyn core::iter::Iterator<Item=GetSMT>> {
|
||||
|
|
|
@ -49,6 +49,10 @@ impl BasicCpu {
|
|||
index,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sysfs_path(&self) -> &std::path::Path {
|
||||
self.sysfs.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_cpu_index(path: &str) -> Option<usize> {
|
||||
|
@ -611,7 +615,7 @@ impl core::convert::Into<EnergyPerfPreference> for GetEnergyPerfPreference {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct SetEnergyPerfPreference(String);
|
||||
pub struct SetEnergyPerfPreference(pub String);
|
||||
|
||||
impl PowerOp for SetEnergyPerfPreference {
|
||||
fn is_eq_op(&self, _: &Self) -> bool {
|
||||
|
@ -906,7 +910,7 @@ impl core::convert::Into<ScalingGovernor> for GetScalingGovernor {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct SetScalingGovernor(String);
|
||||
pub struct SetScalingGovernor(pub String);
|
||||
|
||||
impl PowerOp for SetScalingGovernor {
|
||||
fn is_eq_op(&self, _: &Self) -> bool {
|
||||
|
@ -1024,7 +1028,7 @@ impl core::convert::Into<ScalingMaxFreq> for GetScalingMaxFreq {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct SetScalingMaxFreq(usize);
|
||||
pub struct SetScalingMaxFreq(pub usize);
|
||||
|
||||
impl PowerOp for SetScalingMaxFreq {
|
||||
fn is_eq_op(&self, _: &Self) -> bool {
|
||||
|
@ -1142,7 +1146,7 @@ impl core::convert::Into<ScalingMinFreq> for GetScalingMinFreq {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct SetScalingMinFreq(usize);
|
||||
pub struct SetScalingMinFreq(pub usize);
|
||||
|
||||
impl PowerOp for SetScalingMinFreq {
|
||||
fn is_eq_op(&self, _: &Self) -> bool {
|
||||
|
|
Loading…
Add table
Reference in a new issue