use std::path::{Path, PathBuf};
const PCIE_DPM: &str = "pp_dpm_pcie";
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
pub struct LINK {
pub r#gen: u8,
pub width: u8,
}
use super::STATUS;
impl LINK {
pub fn get_from_sysfs_with_status<P: Into<PathBuf>>(
sysfs_path: P,
status: STATUS,
) -> Option<Self> {
let base_path = sysfs_path.into();
let [s_speed, s_width] = status.to_sysfs_file_name().map(|name| {
let mut s = std::fs::read_to_string(base_path.join(name)).ok()?;
s.pop();
Some(s)
});
let r#gen = Self::speed_to_gen(&s_speed?)?;
let width = s_width?.parse::<u8>().ok()?;
Some(Self { r#gen, width })
}
pub fn speed_to_gen(speed: &str) -> Option<u8> {
let r#gen = match speed {
"2.5 GT/s PCIe" => 1,
"5.0 GT/s PCIe" => 2,
"8.0 GT/s PCIe" => 3,
"16.0 GT/s PCIe" => 4,
"32.0 GT/s PCIe" => 5,
"64.0 GT/s PCIe" => 6,
_ => return None,
};
Some(r#gen)
}
fn parse_dpm_line(s: &str) -> Option<Self> {
let mut r#gen: Option<u8> = None;
let mut width: Option<u8> = None;
for tmp in s.split(", ") {
if tmp.ends_with("GT/s") {
let Some(pos) = tmp.find(' ') else { continue };
r#gen = {
let tmp = match tmp.get(pos+1..)? {
"2.5GT/s" => 1,
"5.0GT/s" => 2,
"8.0GT/s" => 3,
"16.0GT/s" => 4,
"32.0GT/s" => 5,
"64.0GT/s" => 6,
_ => 0,
};
(tmp != 0).then_some(tmp)
};
continue;
}
if tmp.starts_with('x') {
let tmp = tmp.trim_start_matches('x');
let Some(space_pos) = tmp.find(' ') else { continue };
width = tmp.get(..space_pos)?.parse().ok();
continue;
}
}
Some(Self { r#gen: r#gen?, width: width? })
}
pub fn get_min_max_link_info_from_dpm<P: Into<PathBuf>>(sysfs_path: P) -> Option<[LINK; 2]> {
use crate::AMDGPU::get_min_max_from_dpm;
get_min_max_from_dpm(sysfs_path.into().join(PCIE_DPM), Self::parse_dpm_line)
}
pub fn get_current_link_info_from_dpm<P: Into<PathBuf>>(sysfs_path: P) -> Option<LINK> {
let sysfs_path = sysfs_path.into();
let s = std::fs::read_to_string(sysfs_path.join(PCIE_DPM)).ok()?;
let cur = s.lines().find(|&line| line.ends_with(" *"))?;
Self::parse_dpm_line(cur)
}
pub(crate) fn get_max_link(sysfs_path: &Path) -> Option<Self> {
let [s_speed, s_width] = STATUS::Max.to_sysfs_file_name().map(|name| {
let mut s = std::fs::read_to_string(sysfs_path.join(name)).ok()?;
s.pop();
Some(s)
});
let r#gen = Self::speed_to_gen(&s_speed?)?;
let width = s_width?.parse::<u8>().ok()?;
Some(Self { r#gen, width })
}
}