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

This commit is contained in:
Vicki Pfau 2024-07-29 20:44:07 -07:00
parent 41382c7158
commit fc25da30af
6 changed files with 84 additions and 88 deletions

View file

@ -138,27 +138,6 @@
--> -->
<property name="WifiBackend" type="u" access="readwrite"/> <property name="WifiBackend" type="u" access="readwrite"/>
<!--
GpuPowerProfiles:
Enumerate the supported GPU power profiles available on the system.
A list of supported profiles, as a dictionary of values to names.
Since: 9
-->
<property name="GpuPowerProfiles" type="a{us}" access="read"/>
<!--
GpuPowerProfile:
The current GPU power profile. Valid values come from GpuPowerProfiles
property.
Since: 9
-->
<property name="GpuPowerProfile" type="u" access="readwrite"/>
</interface> </interface>
</node> </node>

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,
HdmiCec1Proxy, Manager2Proxy, ManagerProxy, Storage1Proxy, UpdateBios1Proxy, UpdateDock1Proxy, GpuPowerProfile1Proxy, HdmiCec1Proxy, Manager2Proxy, ManagerProxy, Storage1Proxy,
WifiPowerManagement1Proxy, 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;
@ -62,7 +62,7 @@ enum Commands {
}, },
/// Get the GPU power profiles supported on this device /// Get the GPU power profiles supported on this device
GetGPUPowerProfiles, GetAvailableGPUPowerProfiles,
/// Get the current GPU power profile /// Get the current GPU power profile
GetGPUPowerProfile, GetGPUPowerProfile,
@ -250,17 +250,18 @@ async fn main() -> Result<()> {
.set_cpu_scaling_governor(governor.to_string().as_str()) .set_cpu_scaling_governor(governor.to_string().as_str())
.await?; .await?;
} }
Commands::GetGPUPowerProfiles => { Commands::GetAvailableGPUPowerProfiles => {
let profiles = proxy.gpu_power_profiles().await?; let proxy = GpuPowerProfile1Proxy::new(&conn).await?;
let profiles = proxy.available_gpu_power_profiles().await?;
println!("Profiles:\n"); println!("Profiles:\n");
for key in profiles.keys().sorted() { for name in profiles.into_iter().sorted() {
let name = &profiles[key]; println!("- {name}");
println!("{key}: {name}");
} }
} }
Commands::GetGPUPowerProfile => { Commands::GetGPUPowerProfile => {
let proxy = GpuPowerProfile1Proxy::new(&conn).await?;
let profile = proxy.gpu_power_profile().await?; let profile = proxy.gpu_power_profile().await?;
let profile_type = GPUPowerProfile::try_from(profile); let profile_type = GPUPowerProfile::try_from(profile.as_str());
match profile_type { match profile_type {
Ok(t) => { Ok(t) => {
let name = t.to_string(); let name = t.to_string();
@ -272,7 +273,10 @@ async fn main() -> Result<()> {
} }
} }
Commands::SetGPUPowerProfile { profile } => { Commands::SetGPUPowerProfile { profile } => {
proxy.set_gpu_power_profile(*profile as u32).await?; let proxy = GpuPowerProfile1Proxy::new(&conn).await?;
proxy
.set_gpu_power_profile(profile.to_string().as_str())
.await?;
} }
Commands::SetGPUPerformanceLevel { level } => { Commands::SetGPUPerformanceLevel { level } => {
proxy.set_gpu_performance_level(*level as u32).await?; proxy.set_gpu_performance_level(*level as u32).await?;

View file

@ -184,7 +184,7 @@ impl SteamOSManager {
.await .await
} }
async fn set_gpu_power_profile(&self, value: u32) -> fdo::Result<()> { async fn set_gpu_power_profile(&self, value: &str) -> fdo::Result<()> {
let profile = GPUPowerProfile::try_from(value).map_err(to_zbus_fdo_error)?; let profile = GPUPowerProfile::try_from(value).map_err(to_zbus_fdo_error)?;
set_gpu_power_profile(profile) set_gpu_power_profile(profile)
.await .await

View file

@ -7,7 +7,6 @@
*/ */
use anyhow::Result; use anyhow::Result;
use std::collections::HashMap;
use tokio::sync::mpsc::{Sender, UnboundedSender}; use tokio::sync::mpsc::{Sender, UnboundedSender};
use tokio::sync::oneshot; use tokio::sync::oneshot;
use tracing::error; use tracing::error;
@ -22,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_cpu_scaling_governor, get_gpu_clocks, get_available_cpu_scaling_governors, get_available_gpu_power_profiles,
get_gpu_clocks_range, get_gpu_performance_level, get_gpu_power_profile, get_gpu_power_profiles, get_cpu_scaling_governor, get_gpu_clocks, get_gpu_clocks_range, get_gpu_performance_level,
get_tdp_limit, 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;
@ -111,6 +110,10 @@ struct FanControl1 {
proxy: Proxy<'static>, proxy: Proxy<'static>,
} }
struct GpuPowerProfile1 {
proxy: Proxy<'static>,
}
struct HdmiCec1 { struct HdmiCec1 {
hdmi_cec: HdmiCecControl<'static>, hdmi_cec: HdmiCecControl<'static>,
} }
@ -157,30 +160,6 @@ impl SteamOSManager {
API_VERSION API_VERSION
} }
#[zbus(property(emits_changed_signal = "false"))]
async fn gpu_power_profiles(&self) -> fdo::Result<HashMap<u32, String>> {
get_gpu_power_profiles().await.map_err(to_zbus_fdo_error)
}
#[zbus(property(emits_changed_signal = "false"))]
async fn gpu_power_profile(&self) -> fdo::Result<u32> {
match get_gpu_power_profile().await {
Ok(profile) => Ok(profile as u32),
Err(e) => {
error!("Error getting GPU power profile: {e}");
Err(to_zbus_fdo_error(e))
}
}
}
#[zbus(property)]
async fn set_gpu_power_profile(&self, profile: u32) -> zbus::Result<()> {
self.proxy
.call("SetGpuPowerProfile", &(profile))
.await
.map_err(to_zbus_error)
}
#[zbus(property(emits_changed_signal = "false"))] #[zbus(property(emits_changed_signal = "false"))]
async fn gpu_performance_level(&self) -> fdo::Result<u32> { async fn gpu_performance_level(&self) -> fdo::Result<u32> {
match get_gpu_performance_level().await { match get_gpu_performance_level().await {
@ -354,6 +333,38 @@ impl FanControl1 {
} }
} }
#[interface(name = "com.steampowered.SteamOSManager1.GpuPowerProfile1")]
impl GpuPowerProfile1 {
#[zbus(property(emits_changed_signal = "false"))]
async fn available_gpu_power_profiles(&self) -> fdo::Result<Vec<String>> {
let (_, names): (Vec<u32>, Vec<String>) = get_available_gpu_power_profiles()
.await
.map_err(to_zbus_fdo_error)?
.into_iter()
.unzip();
Ok(names)
}
#[zbus(property(emits_changed_signal = "false"))]
async fn gpu_power_profile(&self) -> fdo::Result<String> {
match get_gpu_power_profile().await {
Ok(profile) => Ok(profile.to_string()),
Err(e) => {
error!("Error getting GPU power profile: {e}");
Err(to_zbus_fdo_error(e))
}
}
}
#[zbus(property)]
async fn set_gpu_power_profile(&self, profile: &str) -> zbus::Result<()> {
self.proxy
.call("SetGpuPowerProfile", &(profile))
.await
.map_err(to_zbus_error)
}
}
impl HdmiCec1 { impl HdmiCec1 {
async fn new(connection: &Connection) -> Result<HdmiCec1> { async fn new(connection: &Connection) -> Result<HdmiCec1> {
let hdmi_cec = HdmiCecControl::new(connection).await?; let hdmi_cec = HdmiCecControl::new(connection).await?;
@ -482,6 +493,9 @@ pub(crate) async fn create_interfaces(
let fan_control = FanControl1 { let fan_control = FanControl1 {
proxy: proxy.clone(), proxy: proxy.clone(),
}; };
let gpu_power_profile = GpuPowerProfile1 {
proxy: proxy.clone(),
};
let hdmi_cec = HdmiCec1::new(&session).await?; let hdmi_cec = HdmiCec1::new(&session).await?;
let manager2 = Manager2 { let manager2 = Manager2 {
proxy: proxy.clone(), proxy: proxy.clone(),
@ -509,6 +523,7 @@ 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_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?;
object_server.at(MANAGER_PATH, storage).await?; object_server.at(MANAGER_PATH, storage).await?;
@ -621,6 +636,15 @@ mod test {
.unwrap()); .unwrap());
} }
#[tokio::test]
async fn interface_matches_gpu_power_profile1() {
let test = start().await.expect("start");
assert!(test_interface_matches::<GpuPowerProfile1>(&test.connection)
.await
.unwrap());
}
#[tokio::test] #[tokio::test]
async fn interface_matches_hdmi_cec1() { async fn interface_matches_hdmi_cec1() {
let test = start().await.expect("start"); let test = start().await.expect("start");

View file

@ -8,7 +8,6 @@
use anyhow::{anyhow, bail, ensure, Result}; use anyhow::{anyhow, bail, ensure, Result};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use regex::Regex; use regex::Regex;
use std::collections::HashMap;
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};
@ -195,11 +194,11 @@ pub(crate) async fn get_gpu_power_profile() -> Result<GPUPowerProfile> {
bail!("Unable to determine current GPU power profile"); bail!("Unable to determine current GPU power profile");
} }
pub(crate) async fn get_gpu_power_profiles() -> Result<HashMap<u32, String>> { pub(crate) async fn get_available_gpu_power_profiles() -> Result<Vec<(u32, String)>> {
let contents = read_gpu_sysfs_contents(GPU_POWER_PROFILE_SUFFIX).await?; let contents = read_gpu_sysfs_contents(GPU_POWER_PROFILE_SUFFIX).await?;
let deck = is_deck().await?; let deck = is_deck().await?;
let mut map = HashMap::new(); let mut map = Vec::new();
let lines = contents.lines(); let lines = contents.lines();
for line in lines { for line in lines {
let caps = GPU_POWER_PROFILE_REGEX.captures(line); let caps = GPU_POWER_PROFILE_REGEX.captures(line);
@ -216,13 +215,13 @@ pub(crate) async fn get_gpu_power_profiles() -> Result<HashMap<u32, String>> {
// the other profiles aren't correctly tuned for the hardware. // the other profiles aren't correctly tuned for the hardware.
if value == GPUPowerProfile::Capped as u32 || value == GPUPowerProfile::Uncapped as u32 if value == GPUPowerProfile::Capped as u32 || value == GPUPowerProfile::Uncapped as u32
{ {
map.insert(value, name.to_string()); map.push((value, name.to_string()));
} else { } else {
// Got unsupported value, so don't include it // Got unsupported value, so don't include it
} }
} else { } else {
// Do basic validation to ensure our enum is up to date? // Do basic validation to ensure our enum is up to date?
map.insert(value, name.to_string()); map.push((value, name.to_string()));
} }
} }
Ok(map) Ok(map)
@ -774,10 +773,10 @@ CCLK_RANGE in Core0:
.await .await
.expect("fake_model"); .expect("fake_model");
let profiles = get_gpu_power_profiles().await.expect("get"); let profiles = get_available_gpu_power_profiles().await.expect("get");
assert_eq!( assert_eq!(
profiles, profiles,
HashMap::from([ &[
( (
GPUPowerProfile::FullScreen as u32, GPUPowerProfile::FullScreen as u32,
String::from("3D_FULL_SCREEN") String::from("3D_FULL_SCREEN")
@ -788,20 +787,20 @@ CCLK_RANGE in Core0:
(GPUPowerProfile::Custom as u32, String::from("CUSTOM")), (GPUPowerProfile::Custom as u32, String::from("CUSTOM")),
(GPUPowerProfile::Capped as u32, String::from("CAPPED")), (GPUPowerProfile::Capped as u32, String::from("CAPPED")),
(GPUPowerProfile::Uncapped as u32, String::from("UNCAPPED")) (GPUPowerProfile::Uncapped as u32, String::from("UNCAPPED"))
]) ]
); );
fake_model(HardwareVariant::Jupiter) fake_model(HardwareVariant::Jupiter)
.await .await
.expect("fake_model"); .expect("fake_model");
let profiles = get_gpu_power_profiles().await.expect("get"); let profiles = get_available_gpu_power_profiles().await.expect("get");
assert_eq!( assert_eq!(
profiles, profiles,
HashMap::from([ &[
(GPUPowerProfile::Capped as u32, String::from("CAPPED")), (GPUPowerProfile::Capped as u32, String::from("CAPPED")),
(GPUPowerProfile::Uncapped as u32, String::from("UNCAPPED")) (GPUPowerProfile::Uncapped as u32, String::from("UNCAPPED"))
]) ]
); );
} }
@ -831,35 +830,35 @@ CCLK_RANGE in Core0:
.await .await
.expect("fake_model"); .expect("fake_model");
let profiles = get_gpu_power_profiles().await.expect("get"); let profiles = get_available_gpu_power_profiles().await.expect("get");
assert_eq!( assert_eq!(
profiles, profiles,
HashMap::from([ &[
(2, String::from("CGA")),
( (
GPUPowerProfile::FullScreen as u32, GPUPowerProfile::FullScreen as u32,
String::from("3D_FULL_SCREEN") String::from("3D_FULL_SCREEN")
), ),
(2, String::from("CGA")),
(GPUPowerProfile::Video as u32, String::from("VIDEO")), (GPUPowerProfile::Video as u32, String::from("VIDEO")),
(GPUPowerProfile::VR as u32, String::from("VR")), (GPUPowerProfile::VR as u32, String::from("VR")),
(GPUPowerProfile::Compute as u32, String::from("COMPUTE")), (GPUPowerProfile::Compute as u32, String::from("COMPUTE")),
(GPUPowerProfile::Custom as u32, String::from("CUSTOM")), (GPUPowerProfile::Custom as u32, String::from("CUSTOM")),
(GPUPowerProfile::Capped as u32, String::from("CAPPED")), (GPUPowerProfile::Capped as u32, String::from("CAPPED")),
(GPUPowerProfile::Uncapped as u32, String::from("UNCAPPED")) (GPUPowerProfile::Uncapped as u32, String::from("UNCAPPED"))
]) ]
); );
fake_model(HardwareVariant::Jupiter) fake_model(HardwareVariant::Jupiter)
.await .await
.expect("fake_model"); .expect("fake_model");
let profiles = get_gpu_power_profiles().await.expect("get"); let profiles = get_available_gpu_power_profiles().await.expect("get");
assert_eq!( assert_eq!(
profiles, profiles,
HashMap::from([ &[
(GPUPowerProfile::Capped as u32, String::from("CAPPED")), (GPUPowerProfile::Capped as u32, String::from("CAPPED")),
(GPUPowerProfile::Uncapped as u32, String::from("UNCAPPED")) (GPUPowerProfile::Uncapped as u32, String::from("UNCAPPED"))
]) ]
); );
} }

View file

@ -28,16 +28,6 @@ trait Manager {
#[zbus(property)] #[zbus(property)]
fn set_gpu_performance_level(&self, value: u32) -> zbus::Result<()>; fn set_gpu_performance_level(&self, value: u32) -> zbus::Result<()>;
/// GpuPowerProfile property
#[zbus(property)]
fn gpu_power_profile(&self) -> zbus::Result<u32>;
#[zbus(property)]
fn set_gpu_power_profile(&self, value: u32) -> zbus::Result<()>;
/// GpuPowerProfiles property
#[zbus(property)]
fn gpu_power_profiles(&self) -> zbus::Result<std::collections::HashMap<u32, String>>;
/// ManualGpuClock property /// ManualGpuClock property
#[zbus(property)] #[zbus(property)]
fn manual_gpu_clock(&self) -> zbus::Result<u32>; fn manual_gpu_clock(&self) -> zbus::Result<u32>;