manager/user: Move relevant methods to GpuPerformanceLevel1, update as specified

This commit is contained in:
Vicki Pfau 2024-07-29 22:01:53 -07:00
parent fc25da30af
commit 4f3a5547d6
6 changed files with 115 additions and 142 deletions

View file

@ -31,46 +31,6 @@
--> -->
<property name="Version" type="u" access="read"/> <property name="Version" type="u" access="read"/>
<!--
GpuPerformanceLevel:
The current GPU performance level.
Valid states: 0 = Auto, 1 = Low, 2 = High, 3 = Manual, 4 = Profile Peak
Since: 7
-->
<property name="GpuPerformanceLevel" type="u" access="readwrite"/>
<!--
ManualGpuClock:
Controls the GPU clock frequency in MHz when GPUPerformanceLevel is set
to Manual.
Since: 7
-->
<property name="ManualGpuClock" type="u" access="readwrite"/>
<!--
ManualGpuClockMin:
Minimum frequency allowed for GPU clocks.
Since: 7
-->
<property name="ManualGpuClockMin" type="u" access="read"/>
<!--
ManualGpuClockMax:
Maximum frequency allowed for GPU clocks.
Since: 7
-->
<property name="ManualGpuClockMax" type="u" access="read"/>
<!-- <!--
TdpLimit: TdpLimit:

View file

@ -14,8 +14,8 @@ use steamos_manager::hardware::FanControlState;
use steamos_manager::power::{CPUScalingGovernor, GPUPerformanceLevel, GPUPowerProfile}; use steamos_manager::power::{CPUScalingGovernor, GPUPerformanceLevel, GPUPowerProfile};
use steamos_manager::proxy::{ use steamos_manager::proxy::{
AmbientLightSensor1Proxy, CpuScaling1Proxy, FactoryReset1Proxy, FanControl1Proxy, AmbientLightSensor1Proxy, CpuScaling1Proxy, FactoryReset1Proxy, FanControl1Proxy,
GpuPowerProfile1Proxy, HdmiCec1Proxy, Manager2Proxy, ManagerProxy, Storage1Proxy, GpuPerformanceLevel1Proxy, GpuPowerProfile1Proxy, HdmiCec1Proxy, Manager2Proxy, ManagerProxy,
UpdateBios1Proxy, UpdateDock1Proxy, WifiPowerManagement1Proxy, Storage1Proxy, UpdateBios1Proxy, UpdateDock1Proxy, WifiPowerManagement1Proxy,
}; };
use steamos_manager::wifi::{WifiBackend, WifiDebugMode, WifiPowerManagement}; use steamos_manager::wifi::{WifiBackend, WifiDebugMode, WifiPowerManagement};
use zbus::fdo::PropertiesProxy; use zbus::fdo::PropertiesProxy;
@ -75,7 +75,7 @@ enum Commands {
/// Set the GPU performance level /// Set the GPU performance level
SetGPUPerformanceLevel { SetGPUPerformanceLevel {
/// Valid levels are auto, low, high, manual, peak_performance /// Valid levels are auto, low, high, manual, profile_peak
level: GPUPerformanceLevel, level: GPUPerformanceLevel,
}, },
@ -279,27 +279,35 @@ async fn main() -> Result<()> {
.await?; .await?;
} }
Commands::SetGPUPerformanceLevel { level } => { Commands::SetGPUPerformanceLevel { level } => {
proxy.set_gpu_performance_level(*level as u32).await?; let proxy = GpuPerformanceLevel1Proxy::new(&conn).await?;
proxy
.set_gpu_performance_level(level.to_string().as_str())
.await?;
} }
Commands::GetGPUPerformanceLevel => { Commands::GetGPUPerformanceLevel => {
let proxy = GpuPerformanceLevel1Proxy::new(&conn).await?;
let level = proxy.gpu_performance_level().await?; let level = proxy.gpu_performance_level().await?;
match GPUPerformanceLevel::try_from(level) { match GPUPerformanceLevel::try_from(level.as_str()) {
Ok(l) => println!("GPU performance level: {}", l), Ok(l) => println!("GPU performance level: {}", l),
Err(_) => println!("Got unknown value {level} from backend"), Err(_) => println!("Got unknown value {level} from backend"),
} }
} }
Commands::SetManualGPUClock { freq } => { Commands::SetManualGPUClock { freq } => {
let proxy = GpuPerformanceLevel1Proxy::new(&conn).await?;
proxy.set_manual_gpu_clock(*freq).await?; proxy.set_manual_gpu_clock(*freq).await?;
} }
Commands::GetManualGPUClock => { Commands::GetManualGPUClock => {
let proxy = GpuPerformanceLevel1Proxy::new(&conn).await?;
let clock = proxy.manual_gpu_clock().await?; let clock = proxy.manual_gpu_clock().await?;
println!("Manual GPU Clock: {clock}"); println!("Manual GPU Clock: {clock}");
} }
Commands::GetManualGPUClockMax => { Commands::GetManualGPUClockMax => {
let proxy = GpuPerformanceLevel1Proxy::new(&conn).await?;
let value = proxy.manual_gpu_clock_max().await?; let value = proxy.manual_gpu_clock_max().await?;
println!("Manual GPU Clock Max: {value}"); println!("Manual GPU Clock Max: {value}");
} }
Commands::GetManualGPUClockMin => { Commands::GetManualGPUClockMin => {
let proxy = GpuPerformanceLevel1Proxy::new(&conn).await?;
let value = proxy.manual_gpu_clock_min().await?; let value = proxy.manual_gpu_clock_min().await?;
println!("Manual GPU Clock Min: {value}"); println!("Manual GPU Clock Min: {value}");
} }

View file

@ -200,7 +200,7 @@ impl SteamOSManager {
.map_err(to_zbus_fdo_error) .map_err(to_zbus_fdo_error)
} }
async fn set_gpu_performance_level(&self, level: u32) -> fdo::Result<()> { async fn set_gpu_performance_level(&self, level: &str) -> fdo::Result<()> {
let level = match GPUPerformanceLevel::try_from(level) { let level = match GPUPerformanceLevel::try_from(level) {
Ok(level) => level, Ok(level) => level,
Err(e) => return Err(to_zbus_fdo_error(e)), Err(e) => return Err(to_zbus_fdo_error(e)),
@ -442,7 +442,7 @@ mod test {
default_path = "/com/steampowered/SteamOSManager1" default_path = "/com/steampowered/SteamOSManager1"
)] )]
trait GpuPerformanceLevel { trait GpuPerformanceLevel {
fn set_gpu_performance_level(&self, level: u32) -> zbus::Result<()>; fn set_gpu_performance_level(&self, level: String) -> zbus::Result<()>;
} }
#[tokio::test] #[tokio::test]
@ -455,7 +455,7 @@ mod test {
.await .await
.unwrap(); .unwrap();
proxy proxy
.set_gpu_performance_level(GPUPerformanceLevel::Low as u32) .set_gpu_performance_level(GPUPerformanceLevel::Low.to_string())
.await .await
.expect("proxy_set"); .expect("proxy_set");
assert_eq!( assert_eq!(

View file

@ -21,9 +21,9 @@ use crate::error::{to_zbus_error, to_zbus_fdo_error, zbus_to_zbus_fdo};
use crate::hardware::{check_support, HardwareCurrentlySupported}; use crate::hardware::{check_support, HardwareCurrentlySupported};
use crate::job::JobManagerCommand; use crate::job::JobManagerCommand;
use crate::power::{ use crate::power::{
get_available_cpu_scaling_governors, get_available_gpu_power_profiles, get_available_cpu_scaling_governors, get_available_gpu_performance_levels,
get_cpu_scaling_governor, get_gpu_clocks, get_gpu_clocks_range, get_gpu_performance_level, get_available_gpu_power_profiles, get_cpu_scaling_governor, get_gpu_clocks,
get_gpu_power_profile, get_tdp_limit, get_gpu_clocks_range, get_gpu_performance_level, get_gpu_power_profile, get_tdp_limit,
}; };
use crate::wifi::{get_wifi_backend, get_wifi_power_management_state}; use crate::wifi::{get_wifi_backend, get_wifi_power_management_state};
use crate::API_VERSION; use crate::API_VERSION;
@ -110,6 +110,10 @@ struct FanControl1 {
proxy: Proxy<'static>, proxy: Proxy<'static>,
} }
struct GpuPerformanceLevel1 {
proxy: Proxy<'static>,
}
struct GpuPowerProfile1 { struct GpuPowerProfile1 {
proxy: Proxy<'static>, proxy: Proxy<'static>,
} }
@ -160,48 +164,6 @@ impl SteamOSManager {
API_VERSION API_VERSION
} }
#[zbus(property(emits_changed_signal = "false"))]
async fn gpu_performance_level(&self) -> fdo::Result<u32> {
match get_gpu_performance_level().await {
Ok(level) => Ok(level as u32),
Err(e) => {
error!("Error getting GPU performance level: {e}");
Err(to_zbus_fdo_error(e))
}
}
}
#[zbus(property)]
async fn set_gpu_performance_level(&self, level: u32) -> zbus::Result<()> {
self.proxy
.call("SetGpuPerformanceLevel", &(level))
.await
.map_err(to_zbus_error)
}
#[zbus(property(emits_changed_signal = "false"))]
async fn manual_gpu_clock(&self) -> fdo::Result<u32> {
get_gpu_clocks()
.await
.inspect_err(|message| error!("Error getting manual GPU clock: {message}"))
.map_err(to_zbus_fdo_error)
}
#[zbus(property)]
async fn set_manual_gpu_clock(&self, clocks: u32) -> zbus::Result<()> {
setter!(self, "SetManualGpuClock", clocks)
}
#[zbus(property(emits_changed_signal = "const"))]
async fn manual_gpu_clock_min(&self) -> fdo::Result<u32> {
Ok(get_gpu_clocks_range().await.map_err(to_zbus_fdo_error)?.0)
}
#[zbus(property(emits_changed_signal = "const"))]
async fn manual_gpu_clock_max(&self) -> fdo::Result<u32> {
Ok(get_gpu_clocks_range().await.map_err(to_zbus_fdo_error)?.1)
}
#[zbus(property(emits_changed_signal = "false"))] #[zbus(property(emits_changed_signal = "false"))]
async fn tdp_limit(&self) -> fdo::Result<u32> { async fn tdp_limit(&self) -> fdo::Result<u32> {
get_tdp_limit().await.map_err(to_zbus_fdo_error) get_tdp_limit().await.map_err(to_zbus_fdo_error)
@ -333,6 +295,60 @@ impl FanControl1 {
} }
} }
#[interface(name = "com.steampowered.SteamOSManager1.GpuPerformanceLevel1")]
impl GpuPerformanceLevel1 {
#[zbus(property(emits_changed_signal = "false"))]
async fn available_gpu_performance_levels(&self) -> fdo::Result<Vec<String>> {
get_available_gpu_performance_levels()
.await
.inspect_err(|message| error!("Error getting GPU performance levels: {message}"))
.map(|levels| levels.into_iter().map(|level| level.to_string()).collect())
.map_err(to_zbus_fdo_error)
}
#[zbus(property(emits_changed_signal = "false"))]
async fn gpu_performance_level(&self) -> fdo::Result<String> {
match get_gpu_performance_level().await {
Ok(level) => Ok(level.to_string()),
Err(e) => {
error!("Error getting GPU performance level: {e}");
Err(to_zbus_fdo_error(e))
}
}
}
#[zbus(property)]
async fn set_gpu_performance_level(&self, level: &str) -> zbus::Result<()> {
self.proxy
.call("SetGpuPerformanceLevel", &(level))
.await
.map_err(to_zbus_error)
}
#[zbus(property(emits_changed_signal = "false"))]
async fn manual_gpu_clock(&self) -> fdo::Result<u32> {
get_gpu_clocks()
.await
.inspect_err(|message| error!("Error getting manual GPU clock: {message}"))
.map_err(to_zbus_fdo_error)
}
#[zbus(property)]
async fn set_manual_gpu_clock(&self, clocks: u32) -> zbus::Result<()> {
setter!(self, "SetManualGpuClock", clocks)
}
#[zbus(property(emits_changed_signal = "const"))]
async fn manual_gpu_clock_min(&self) -> fdo::Result<u32> {
Ok(get_gpu_clocks_range().await.map_err(to_zbus_fdo_error)?.0)
}
#[zbus(property(emits_changed_signal = "const"))]
async fn manual_gpu_clock_max(&self) -> fdo::Result<u32> {
Ok(get_gpu_clocks_range().await.map_err(to_zbus_fdo_error)?.1)
}
}
#[interface(name = "com.steampowered.SteamOSManager1.GpuPowerProfile1")] #[interface(name = "com.steampowered.SteamOSManager1.GpuPowerProfile1")]
impl GpuPowerProfile1 { impl GpuPowerProfile1 {
#[zbus(property(emits_changed_signal = "false"))] #[zbus(property(emits_changed_signal = "false"))]
@ -493,6 +509,9 @@ pub(crate) async fn create_interfaces(
let fan_control = FanControl1 { let fan_control = FanControl1 {
proxy: proxy.clone(), proxy: proxy.clone(),
}; };
let gpu_performance_level = GpuPerformanceLevel1 {
proxy: proxy.clone(),
};
let gpu_power_profile = GpuPowerProfile1 { let gpu_power_profile = GpuPowerProfile1 {
proxy: proxy.clone(), proxy: proxy.clone(),
}; };
@ -523,6 +542,9 @@ pub(crate) async fn create_interfaces(
object_server.at(MANAGER_PATH, cpu_scaling).await?; object_server.at(MANAGER_PATH, cpu_scaling).await?;
object_server.at(MANAGER_PATH, factory_reset).await?; object_server.at(MANAGER_PATH, factory_reset).await?;
object_server.at(MANAGER_PATH, fan_control).await?; object_server.at(MANAGER_PATH, fan_control).await?;
object_server
.at(MANAGER_PATH, gpu_performance_level)
.await?;
object_server.at(MANAGER_PATH, gpu_power_profile).await?; object_server.at(MANAGER_PATH, gpu_power_profile).await?;
object_server.at(MANAGER_PATH, hdmi_cec).await?; object_server.at(MANAGER_PATH, hdmi_cec).await?;
object_server.at(MANAGER_PATH, manager2).await?; object_server.at(MANAGER_PATH, manager2).await?;
@ -636,6 +658,17 @@ mod test {
.unwrap()); .unwrap());
} }
#[tokio::test]
async fn interface_matches_gpu_performance_level1() {
let test = start().await.expect("start");
assert!(
test_interface_matches::<GpuPerformanceLevel1>(&test.connection)
.await
.unwrap()
);
}
#[tokio::test] #[tokio::test]
async fn interface_matches_gpu_power_profile1() { async fn interface_matches_gpu_power_profile1() {
let test = start().await.expect("start"); let test = start().await.expect("start");

View file

@ -11,7 +11,7 @@ use regex::Regex;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::str::FromStr; use std::str::FromStr;
use strum::{Display, EnumString}; use strum::{Display, EnumString};
use tokio::fs::{self, File}; use tokio::fs::{self, try_exists, File};
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader}; use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
use tracing::{error, warn}; use tracing::{error, warn};
@ -77,29 +77,12 @@ impl TryFrom<u32> for GPUPowerProfile {
#[derive(Display, EnumString, PartialEq, Debug, Copy, Clone)] #[derive(Display, EnumString, PartialEq, Debug, Copy, Clone)]
#[strum(serialize_all = "snake_case")] #[strum(serialize_all = "snake_case")]
#[repr(u32)]
pub enum GPUPerformanceLevel { pub enum GPUPerformanceLevel {
Auto = 0, Auto,
Low = 1, Low,
High = 2, High,
Manual = 3, Manual,
ProfilePeak = 4, ProfilePeak,
}
impl TryFrom<u32> for GPUPerformanceLevel {
type Error = &'static str;
fn try_from(v: u32) -> Result<Self, Self::Error> {
match v {
x if x == GPUPerformanceLevel::Auto as u32 => Ok(GPUPerformanceLevel::Auto),
x if x == GPUPerformanceLevel::Low as u32 => Ok(GPUPerformanceLevel::Low),
x if x == GPUPerformanceLevel::High as u32 => Ok(GPUPerformanceLevel::High),
x if x == GPUPerformanceLevel::Manual as u32 => Ok(GPUPerformanceLevel::Manual),
x if x == GPUPerformanceLevel::ProfilePeak as u32 => {
Ok(GPUPerformanceLevel::ProfilePeak)
}
_ => Err("No enum match for value {v}"),
}
}
} }
#[derive(Display, EnumString, Hash, Eq, PartialEq, Debug, Copy, Clone)] #[derive(Display, EnumString, Hash, Eq, PartialEq, Debug, Copy, Clone)]
@ -232,6 +215,21 @@ pub(crate) async fn set_gpu_power_profile(value: GPUPowerProfile) -> Result<()>
write_gpu_sysfs_contents(GPU_POWER_PROFILE_SUFFIX, profile.as_bytes()).await write_gpu_sysfs_contents(GPU_POWER_PROFILE_SUFFIX, profile.as_bytes()).await
} }
pub(crate) async fn get_available_gpu_performance_levels() -> Result<Vec<GPUPerformanceLevel>> {
let base = find_hwmon().await?;
if !try_exists(base.join(GPU_PERFORMANCE_LEVEL_SUFFIX)).await? {
Ok(Vec::new())
} else {
Ok(vec![
GPUPerformanceLevel::Auto,
GPUPerformanceLevel::Low,
GPUPerformanceLevel::High,
GPUPerformanceLevel::Manual,
GPUPerformanceLevel::ProfilePeak,
])
}
}
pub(crate) async fn get_gpu_performance_level() -> Result<GPUPerformanceLevel> { pub(crate) async fn get_gpu_performance_level() -> Result<GPUPerformanceLevel> {
let level = read_gpu_sysfs_contents(GPU_PERFORMANCE_LEVEL_SUFFIX).await?; let level = read_gpu_sysfs_contents(GPU_PERFORMANCE_LEVEL_SUFFIX).await?;
Ok(GPUPerformanceLevel::from_str(level.trim())?) Ok(GPUPerformanceLevel::from_str(level.trim())?)
@ -733,18 +731,12 @@ CCLK_RANGE in Core0:
#[test] #[test]
fn gpu_performance_level_roundtrip() { fn gpu_performance_level_roundtrip() {
enum_roundtrip!(GPUPerformanceLevel { enum_roundtrip!(GPUPerformanceLevel {
0: u32 = Auto,
1: u32 = Low,
2: u32 = High,
3: u32 = Manual,
4: u32 = ProfilePeak,
"auto": str = Auto, "auto": str = Auto,
"low": str = Low, "low": str = Low,
"high": str = High, "high": str = High,
"manual": str = Manual, "manual": str = Manual,
"profile_peak": str = ProfilePeak, "profile_peak": str = ProfilePeak,
}); });
assert!(GPUPerformanceLevel::try_from(9).is_err());
assert!(GPUPerformanceLevel::from_str("peak_performance").is_err()); assert!(GPUPerformanceLevel::from_str("peak_performance").is_err());
} }

View file

@ -22,26 +22,6 @@ trait Manager {
/// SetWifiDebugMode method /// SetWifiDebugMode method
fn set_wifi_debug_mode(&self, mode: u32, buffer_size: u32) -> zbus::Result<()>; fn set_wifi_debug_mode(&self, mode: u32, buffer_size: u32) -> zbus::Result<()>;
/// GpuPerformanceLevel property
#[zbus(property)]
fn gpu_performance_level(&self) -> zbus::Result<u32>;
#[zbus(property)]
fn set_gpu_performance_level(&self, value: u32) -> zbus::Result<()>;
/// ManualGpuClock property
#[zbus(property)]
fn manual_gpu_clock(&self) -> zbus::Result<u32>;
#[zbus(property)]
fn set_manual_gpu_clock(&self, value: u32) -> zbus::Result<()>;
/// ManualGpuClockMax property
#[zbus(property)]
fn manual_gpu_clock_max(&self) -> zbus::Result<u32>;
/// ManualGpuClockMin property
#[zbus(property)]
fn manual_gpu_clock_min(&self) -> zbus::Result<u32>;
/// TdpLimit property /// TdpLimit property
#[zbus(property)] #[zbus(property)]
fn tdp_limit(&self) -> zbus::Result<u32>; fn tdp_limit(&self) -> zbus::Result<u32>;