power: Add get/set_gpu_clocks and get_tdp_limit tests

This commit is contained in:
Vicki Pfau 2024-04-03 19:17:59 -07:00
parent 3c62c57d52
commit bc6af282eb

View file

@ -20,6 +20,9 @@ const GPU_PERFORMANCE_LEVEL_PATH: &str =
"/sys/class/drm/card0/device/power_dpm_force_performance_level"; "/sys/class/drm/card0/device/power_dpm_force_performance_level";
const GPU_CLOCKS_PATH: &str = "/sys/class/drm/card0/device/pp_od_clk_voltage"; const GPU_CLOCKS_PATH: &str = "/sys/class/drm/card0/device/pp_od_clk_voltage";
const TDP_LIMIT1: &str = "power1_cap";
const TDP_LIMIT2: &str = "power2_cap";
#[derive(PartialEq, Debug, Copy, Clone)] #[derive(PartialEq, Debug, Copy, Clone)]
#[repr(u32)] #[repr(u32)]
pub enum GPUPerformanceLevel { pub enum GPUPerformanceLevel {
@ -158,7 +161,7 @@ async fn find_hwmon() -> Result<PathBuf> {
Some(entry) => entry.path(), Some(entry) => entry.path(),
None => bail!("hwmon not found"), None => bail!("hwmon not found"),
}; };
if fs::try_exists(base.join("power1_cap")).await? { if fs::try_exists(base.join(TDP_LIMIT1)).await? {
return Ok(base); return Ok(base);
} }
} }
@ -166,7 +169,7 @@ async fn find_hwmon() -> Result<PathBuf> {
pub async fn get_tdp_limit() -> Result<u32> { pub async fn get_tdp_limit() -> Result<u32> {
let base = find_hwmon().await?; let base = find_hwmon().await?;
let power1cap = fs::read_to_string(base.join("power1_cap")).await?; let power1cap = fs::read_to_string(base.join(TDP_LIMIT1)).await?;
let power1cap: u32 = power1cap.parse()?; let power1cap: u32 = power1cap.parse()?;
Ok(power1cap / 1000000) Ok(power1cap / 1000000)
} }
@ -178,7 +181,7 @@ pub async fn set_tdp_limit(limit: u32) -> Result<()> {
let data = format!("{limit}000000"); let data = format!("{limit}000000");
let base = find_hwmon().await?; let base = find_hwmon().await?;
let mut power1file = File::create(base.join("power1_cap")) let mut power1file = File::create(base.join(TDP_LIMIT1))
.await .await
.inspect_err(|message| { .inspect_err(|message| {
error!("Error opening sysfs power1_cap file for writing TDP limits {message}") error!("Error opening sysfs power1_cap file for writing TDP limits {message}")
@ -188,7 +191,7 @@ pub async fn set_tdp_limit(limit: u32) -> Result<()> {
.await .await
.inspect_err(|message| error!("Error writing to power1_cap file: {message}"))?; .inspect_err(|message| error!("Error writing to power1_cap file: {message}"))?;
if let Ok(mut power2file) = File::create(base.join("power2_cap")).await { if let Ok(mut power2file) = File::create(base.join(TDP_LIMIT2)).await {
power2file power2file
.write(data.as_bytes()) .write(data.as_bytes())
.await .await
@ -300,6 +303,21 @@ mod test {
); );
} }
#[tokio::test]
async fn test_get_tdp_limit() {
let h = testing::start();
let hwmon = path(GPU_HWMON_PREFIX);
create_dir_all(hwmon.join("hwmon5").as_path())
.await
.expect("create_dir_all");
assert!(get_tdp_limit().await.is_err());
write(hwmon.join("hwmon5").join(TDP_LIMIT1), "15000000").await.expect("write");
assert_eq!(get_tdp_limit().await.unwrap(), 15);
}
#[tokio::test] #[tokio::test]
async fn test_set_tdp_limit() { async fn test_set_tdp_limit() {
let h = testing::start(); let h = testing::start();
@ -324,10 +342,10 @@ mod test {
); );
let hwmon = hwmon.join("hwmon5"); let hwmon = hwmon.join("hwmon5");
create_dir_all(hwmon.join("power1_cap")) create_dir_all(hwmon.join(TDP_LIMIT1))
.await .await
.expect("create_dir_all"); .expect("create_dir_all");
create_dir_all(hwmon.join("power2_cap")) create_dir_all(hwmon.join(TDP_LIMIT2))
.await .await
.expect("create_dir_all"); .expect("create_dir_all");
assert_eq!( assert_eq!(
@ -335,28 +353,74 @@ mod test {
anyhow!("Is a directory (os error 21)").to_string() anyhow!("Is a directory (os error 21)").to_string()
); );
remove_dir(hwmon.join("power1_cap")) remove_dir(hwmon.join(TDP_LIMIT1))
.await .await
.expect("remove_dir"); .expect("remove_dir");
write(hwmon.join("power1_cap"), "0").await.expect("write"); write(hwmon.join(TDP_LIMIT1), "0").await.expect("write");
assert!(set_tdp_limit(10).await.is_ok()); assert!(set_tdp_limit(10).await.is_ok());
let power1_cap = read_to_string(hwmon.join("power1_cap")) let power1_cap = read_to_string(hwmon.join(TDP_LIMIT1))
.await .await
.expect("power1_cap"); .expect("power1_cap");
assert_eq!(power1_cap, "10000000"); assert_eq!(power1_cap, "10000000");
remove_dir(hwmon.join("power2_cap")) remove_dir(hwmon.join(TDP_LIMIT2))
.await .await
.expect("remove_dir"); .expect("remove_dir");
write(hwmon.join("power2_cap"), "0").await.expect("write"); write(hwmon.join(TDP_LIMIT2), "0").await.expect("write");
assert!(set_tdp_limit(15).await.is_ok()); assert!(set_tdp_limit(15).await.is_ok());
let power1_cap = read_to_string(hwmon.join("power1_cap")) let power1_cap = read_to_string(hwmon.join(TDP_LIMIT1))
.await .await
.expect("power1_cap"); .expect("power1_cap");
assert_eq!(power1_cap, "15000000"); assert_eq!(power1_cap, "15000000");
let power2_cap = read_to_string(hwmon.join("power2_cap")) let power2_cap = read_to_string(hwmon.join(TDP_LIMIT2))
.await .await
.expect("power2_cap"); .expect("power2_cap");
assert_eq!(power2_cap, "15000000"); assert_eq!(power2_cap, "15000000");
} }
#[tokio::test]
async fn test_get_gpu_clocks() {
let h = testing::start();
const contents: &str = "OD_SCLK:
0: 1600Mhz
1: 1600Mhz
OD_RANGE:
SCLK: 200Mhz 1600Mhz
CCLK: 1400Mhz 3500Mhz
CCLK_RANGE in Core0:
0: 1400Mhz
1: 3500Mhz\n";
let filename = path(GPU_PERFORMANCE_LEVEL_PATH);
setup_test().await;
assert!(get_gpu_clocks().await.is_err());
write(path(GPU_CLOCKS_PATH), contents).await.expect("write");
assert_eq!(get_gpu_clocks().await.unwrap(), 1600);
}
#[tokio::test]
async fn test_set_gpu_clocks() {
let h = testing::start();
let filename = path(GPU_CLOCKS_PATH);
assert!(set_gpu_clocks(1600).await.is_err());
setup_test().await;
assert!(set_gpu_clocks(100).await.is_err());
assert!(set_gpu_clocks(2000).await.is_err());
assert!(set_gpu_clocks(200).await.is_ok());
assert_eq!(
read_to_string(filename.as_path()).await.expect("string"),
"s 0 200\ns 1 200\nc\n"
);
assert!(set_gpu_clocks(1600).await.is_ok());
assert_eq!(
read_to_string(filename.as_path()).await.expect("string"),
"s 0 1600\ns 1 1600\nc\n"
);
}
} }