Skip to content

Commit f43eddb

Browse files
fix: correctly write power cap with alternative file name on intel (#747)
1 parent 9a30135 commit f43eddb

File tree

1 file changed

+40
-66
lines changed
  • lact-daemon/src/server/gpu_controller

1 file changed

+40
-66
lines changed

lact-daemon/src/server/gpu_controller/intel.rs

Lines changed: 40 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ const DRM_ENGINES: &[(&str, ProcessUtilizationType)] = &[
4343
("video", ProcessUtilizationType::Decode),
4444
];
4545
const FALLBACK_MAX_POWER_CAP: f64 = 400.0;
46+
const POWER_CAP_NAMES: &[&str] = &["power1_cap", "power2_cap", "power1_max", "power2_max"];
47+
const MAX_POWER_CAP_NAMES: &[&str] = &[
48+
"power1_rated_max",
49+
"power2_rated_max",
50+
"power1_crit",
51+
"power2_crit",
52+
];
4653

4754
#[derive(Clone, Copy)]
4855
enum DriverType {
@@ -189,7 +196,11 @@ impl IntelGpuController {
189196
}
190197

191198
fn write_file(&self, path: impl AsRef<Path>, contents: &str) -> anyhow::Result<()> {
192-
let file_path = self.common.sysfs_path.join(path);
199+
let file_path = if path.as_ref().is_absolute() {
200+
Cow::Borrowed(path.as_ref())
201+
} else {
202+
Cow::Owned(self.common.sysfs_path.join(path))
203+
};
193204

194205
if file_path.exists() {
195206
fs::write(&file_path, contents)
@@ -237,57 +248,31 @@ impl IntelGpuController {
237248
.flatten()
238249
}
239250

251+
fn match_hwmon_files<'a>(
252+
&'a self,
253+
possible_names: &'a [&str],
254+
) -> impl Iterator<Item = PathBuf> + 'a {
255+
self.hwmon_path
256+
.iter()
257+
.flat_map(|hwmon| possible_names.iter().map(|file| hwmon.join(file)))
258+
.filter(|path| path.exists())
259+
}
260+
240261
fn read_hwmon_file(&self, possible_names: &[&str], filter_zero: bool) -> Option<u64> {
241-
self.hwmon_path.as_ref().and_then(|hwmon| {
242-
let mut iter = possible_names
243-
.iter()
244-
.map(|file| hwmon.join(file))
245-
.filter_map(|path| self.read_file(path));
246-
247-
if filter_zero {
248-
iter.find(|value| *value != 0)
249-
} else {
250-
iter.next()
251-
}
252-
})
262+
self.match_hwmon_files(possible_names)
263+
.filter_map(|path| self.read_file::<u64>(path))
264+
.find(|value| !filter_zero || *value != 0)
253265
}
254266

255-
fn write_hwmon_file(
256-
&self,
257-
file_prefix: &str,
258-
file_suffix: &str,
259-
contents: &str,
260-
) -> anyhow::Result<()> {
261-
debug!("writing value '{contents}' to '{file_prefix}*{file_suffix}'");
267+
fn write_hwmon_file(&self, possible_names: &[&str], contents: &str) -> anyhow::Result<()> {
268+
let path = self
269+
.match_hwmon_files(possible_names)
270+
.next()
271+
.context("Cap file not found")?;
262272

263-
if let Some(hwmon_path) = &self.hwmon_path {
264-
let mut files = Vec::with_capacity(1);
273+
debug!("writing value '{contents}' to '{}'", path.display());
265274

266-
let entries = fs::read_dir(hwmon_path)?;
267-
for entry in entries.flatten() {
268-
if let Some(name) = entry.file_name().to_str() {
269-
if name.starts_with(file_prefix) && name.ends_with(file_suffix) {
270-
if let Some(infix) = name
271-
.strip_prefix(file_prefix)
272-
.and_then(|name| name.strip_suffix(file_suffix))
273-
{
274-
if !infix.contains('_') {
275-
files.push(entry.path());
276-
}
277-
}
278-
}
279-
}
280-
}
281-
files.sort_unstable();
282-
283-
if let Some(entry) = files.first() {
284-
self.write_file(entry, contents)
285-
} else {
286-
Err(anyhow!("File not found"))
287-
}
288-
} else {
289-
Err(anyhow!("No hwmon available"))
290-
}
275+
self.write_file(path, contents)
291276
}
292277

293278
fn get_drm_info_i915(&self) -> IntelDrmInfo {
@@ -579,28 +564,17 @@ impl IntelGpuController {
579564

580565
#[allow(clippy::cast_precision_loss)]
581566
fn get_power_cap(&self) -> Option<f64> {
582-
self.read_hwmon_file(
583-
&["power1_cap", "power2_cap", "power1_max", "power2_max"],
584-
true,
585-
)
586-
.map(|value| value / 1_000_000)
587-
.map(|value| value as f64) // Placeholder max value
567+
self.read_hwmon_file(POWER_CAP_NAMES, true)
568+
.map(|value| value / 1_000_000)
569+
.map(|value| value as f64)
588570
}
589571

590572
#[allow(clippy::cast_precision_loss)]
591573
fn get_power_cap_max(&self) -> Option<f64> {
592-
self.read_hwmon_file(
593-
&[
594-
"power1_rated_max",
595-
"power2_rated_max",
596-
"power1_crit",
597-
"power2_crit",
598-
],
599-
true,
600-
)
601-
.map(|cap| cap / 1_000_000)
602-
.map(|value| value as f64)
603-
.or_else(|| self.get_power_cap().map(|_| FALLBACK_MAX_POWER_CAP))
574+
self.read_hwmon_file(MAX_POWER_CAP_NAMES, true)
575+
.map(|cap| cap / 1_000_000)
576+
.map(|value| value as f64)
577+
.or_else(|| self.get_power_cap().map(|_| FALLBACK_MAX_POWER_CAP))
604578
}
605579
}
606580

@@ -665,7 +639,7 @@ impl GpuController for IntelGpuController {
665639
}
666640

667641
if let Some(cap) = config.power_cap {
668-
self.write_hwmon_file("power", "_max", &((cap * 1_000_000.0) as u64).to_string())
642+
self.write_hwmon_file(POWER_CAP_NAMES, &((cap * 1_000_000.0) as u64).to_string())
669643
.context("Could not set power cap")?;
670644
}
671645

0 commit comments

Comments
 (0)