mirror of
https://gitlab.steamos.cloud/holo/steamos-manager.git
synced 2025-07-05 14:10:34 -04:00
power: Add sysfs writer service
This commit is contained in:
parent
631f30bc94
commit
4f691bf053
2 changed files with 81 additions and 1 deletions
|
@ -21,6 +21,7 @@ use crate::ds_inhibit::Inhibitor;
|
||||||
use crate::inputplumber::DeckService;
|
use crate::inputplumber::DeckService;
|
||||||
use crate::manager::root::SteamOSManager;
|
use crate::manager::root::SteamOSManager;
|
||||||
use crate::path;
|
use crate::path;
|
||||||
|
use crate::power::SysfsWriterService;
|
||||||
use crate::sls::ftrace::Ftrace;
|
use crate::sls::ftrace::Ftrace;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default, Deserialize, Debug)]
|
#[derive(Copy, Clone, Default, Deserialize, Debug)]
|
||||||
|
@ -127,6 +128,9 @@ impl DaemonContext for RootContext {
|
||||||
let ip = DeckService::init(connection);
|
let ip = DeckService::init(connection);
|
||||||
daemon.add_service(ip);
|
daemon.add_service(ip);
|
||||||
|
|
||||||
|
let sysfs = SysfsWriterService::init()?;
|
||||||
|
daemon.add_service(sysfs);
|
||||||
|
|
||||||
self.reload_ds_inhibit(daemon).await?;
|
self.reload_ds_inhibit(daemon).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
78
src/power.rs
78
src/power.rs
|
@ -17,12 +17,13 @@ use std::ops::RangeInclusive;
|
||||||
use std::os::fd::OwnedFd;
|
use std::os::fd::OwnedFd;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use std::sync::Arc;
|
||||||
use strum::{Display, EnumString, VariantNames};
|
use strum::{Display, EnumString, VariantNames};
|
||||||
use tokio::fs::{self, try_exists, File};
|
use tokio::fs::{self, try_exists, File};
|
||||||
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader, Interest};
|
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader, Interest};
|
||||||
use tokio::net::unix::pipe;
|
use tokio::net::unix::pipe;
|
||||||
use tokio::sync::mpsc::UnboundedReceiver;
|
use tokio::sync::mpsc::UnboundedReceiver;
|
||||||
use tokio::sync::oneshot;
|
use tokio::sync::{oneshot, Mutex, Notify, OnceCell};
|
||||||
use tokio::task::JoinSet;
|
use tokio::task::JoinSet;
|
||||||
use tracing::{debug, error, warn};
|
use tracing::{debug, error, warn};
|
||||||
use zbus::Connection;
|
use zbus::Connection;
|
||||||
|
@ -61,6 +62,8 @@ lazy_static! {
|
||||||
Regex::new(r"^\s*(?<index>[0-9]+): (?<value>[0-9]+)Mhz").unwrap();
|
Regex::new(r"^\s*(?<index>[0-9]+): (?<value>[0-9]+)Mhz").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SYSFS_WRITER: OnceCell<Arc<SysfsWriterQueue>> = OnceCell::const_new();
|
||||||
|
|
||||||
#[derive(Display, EnumString, PartialEq, Debug, Copy, Clone, TryFromPrimitive)]
|
#[derive(Display, EnumString, PartialEq, Debug, Copy, Clone, TryFromPrimitive)]
|
||||||
#[strum(serialize_all = "snake_case")]
|
#[strum(serialize_all = "snake_case")]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
|
@ -168,6 +171,79 @@ pub(crate) enum TdpManagerCommand {
|
||||||
ListDownloadModeHandles(oneshot::Sender<HashMap<String, u32>>),
|
ListDownloadModeHandles(oneshot::Sender<HashMap<String, u32>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) enum SysfsWritten {
|
||||||
|
Written(Result<()>),
|
||||||
|
Superseded,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct SysfsWriterQueue {
|
||||||
|
values: Mutex<HashMap<PathBuf, (Vec<u8>, oneshot::Sender<SysfsWritten>)>>,
|
||||||
|
notify: Notify,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SysfsWriterQueue {
|
||||||
|
fn new() -> SysfsWriterQueue {
|
||||||
|
SysfsWriterQueue {
|
||||||
|
values: Mutex::new(HashMap::new()),
|
||||||
|
notify: Notify::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn send(&self, path: PathBuf, contents: Vec<u8>) -> oneshot::Receiver<SysfsWritten> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
if let Some((_, old_tx)) = self.values.lock().await.insert(path, (contents, tx)) {
|
||||||
|
let _ = old_tx.send(SysfsWritten::Superseded);
|
||||||
|
}
|
||||||
|
self.notify.notify_one();
|
||||||
|
rx
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn recv(&self) -> Option<(PathBuf, Vec<u8>, oneshot::Sender<SysfsWritten>)> {
|
||||||
|
// Take an arbitrary file from the map
|
||||||
|
self.notify.notified().await;
|
||||||
|
let mut values = self.values.lock().await;
|
||||||
|
if let Some(path) = values.keys().next().cloned() {
|
||||||
|
values
|
||||||
|
.remove_entry(&path)
|
||||||
|
.map(|(path, (contents, tx))| (path, contents, tx))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct SysfsWriterService {
|
||||||
|
queue: Arc<SysfsWriterQueue>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SysfsWriterService {
|
||||||
|
pub fn init() -> Result<SysfsWriterService> {
|
||||||
|
ensure!(!SYSFS_WRITER.initialized(), "sysfs writer already active");
|
||||||
|
let queue = Arc::new(SysfsWriterQueue::new());
|
||||||
|
SYSFS_WRITER.set(queue.clone())?;
|
||||||
|
Ok(SysfsWriterService { queue })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Service for SysfsWriterService {
|
||||||
|
const NAME: &'static str = "sysfs-writer";
|
||||||
|
|
||||||
|
async fn run(&mut self) -> Result<()> {
|
||||||
|
loop {
|
||||||
|
let Some((path, contents, tx)) = self.queue.recv().await else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let res = write_synced(path, &contents)
|
||||||
|
.await
|
||||||
|
.inspect_err(|message| error!("Error writing to sysfs file: {message}"));
|
||||||
|
let _ = tx.send(SysfsWritten::Written(res));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn read_gpu_sysfs_contents<S: AsRef<Path>>(suffix: S) -> Result<String> {
|
async fn read_gpu_sysfs_contents<S: AsRef<Path>>(suffix: S) -> Result<String> {
|
||||||
// Read a given suffix for the GPU
|
// Read a given suffix for the GPU
|
||||||
let base = find_hwmon(GPU_HWMON_NAME).await?;
|
let base = find_hwmon(GPU_HWMON_NAME).await?;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue