diff --git a/Cargo.lock b/Cargo.lock index 77a462f..f184377 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1621,11 +1621,12 @@ checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "libdrm_amdgpu_sys" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b138fce021c047c76625cd701e8efb2450d8677551f79d8b5574581b9533f107" +checksum = "239a084aa81eb01317fe32f41a9ba7d284acf13f079523e3b9406339f4ba7c0c" dependencies = [ "libc", + "libloading 0.8.5", ] [[package]] diff --git a/lact-daemon/Cargo.toml b/lact-daemon/Cargo.toml index 647274e..6d3e497 100644 --- a/lact-daemon/Cargo.toml +++ b/lact-daemon/Cargo.toml @@ -37,8 +37,8 @@ pciid-parser = { version = "0.7", features = ["serde"] } serde_yaml = "0.9" vulkano = { version = "0.34.1", default-features = false } zbus = { version = "4.1.2", default-features = false, features = ["tokio"] } -libdrm_amdgpu_sys = { version = "0.7.5", default-features = false, features = [ - "std", +libdrm_amdgpu_sys = { version = "0.8.1", default-features = false, features = [ + "dynamic_loading", ] } tar = "0.4.40" libflate = "2.0.0" diff --git a/lact-daemon/src/server/gpu_controller/amd.rs b/lact-daemon/src/server/gpu_controller/amd.rs index d0b727a..c5bf27b 100644 --- a/lact-daemon/src/server/gpu_controller/amd.rs +++ b/lact-daemon/src/server/gpu_controller/amd.rs @@ -19,6 +19,7 @@ use lact_schema::{ ClocksInfo, ClockspeedStats, DeviceInfo, DeviceStats, DrmInfo, FanStats, IntelDrmInfo, LinkInfo, PmfwInfo, PowerState, PowerStates, PowerStats, VoltageStats, VramStats, }; +use libdrm_amdgpu_sys::LibDrmAmdgpu; use libdrm_amdgpu_sys::AMDGPU::{ThrottleStatus, ThrottlerBit}; use std::{ cell::RefCell, @@ -54,15 +55,18 @@ pub struct AmdGpuController { } impl AmdGpuController { - pub fn new_from_path(common: CommonControllerInfo) -> anyhow::Result { + pub fn new_from_path( + common: CommonControllerInfo, + libdrm_amdgpu: Option<&LibDrmAmdgpu>, + ) -> anyhow::Result { let handle = GpuHandle::new_from_path(common.sysfs_path.clone()) .map_err(|error| anyhow!("failed to initialize gpu handle: {error}"))?; #[allow(unused_mut)] let mut drm_handle = None; #[cfg(not(test))] - if matches!(handle.get_driver(), "amdgpu" | "radeon") { - match get_drm_handle(&handle) { + if matches!(handle.get_driver(), "amdgpu" | "radeon") && libdrm_amdgpu.is_some() { + match get_drm_handle(&handle, libdrm_amdgpu.as_ref().unwrap()) { Ok(handle) => { drm_handle = Some(handle); } @@ -957,8 +961,8 @@ impl GpuController for AmdGpuController { } #[cfg(not(test))] -fn get_drm_handle(handle: &GpuHandle) -> anyhow::Result { - use std::os::fd::IntoRawFd; +fn get_drm_handle(handle: &GpuHandle, libdrm_amdgpu: &LibDrmAmdgpu) -> anyhow::Result { + use std::os::unix::io::IntoRawFd; let slot_name = handle .get_pci_slot_name() @@ -969,7 +973,8 @@ fn get_drm_handle(handle: &GpuHandle) -> anyhow::Result { .write(true) .open(&path) .with_context(|| format!("Could not open drm file at {path}"))?; - let (handle, _, _) = DrmHandle::init(drm_file.into_raw_fd()) + let (handle, _, _) = libdrm_amdgpu + .init_device_handle(drm_file.into_raw_fd()) .map_err(|err| anyhow!("Could not open drm handle, error code {err}"))?; Ok(handle) } diff --git a/lact-daemon/src/server/gpu_controller/mod.rs b/lact-daemon/src/server/gpu_controller/mod.rs index 7032c0a..60822e2 100644 --- a/lact-daemon/src/server/gpu_controller/mod.rs +++ b/lact-daemon/src/server/gpu_controller/mod.rs @@ -7,16 +7,17 @@ mod nvidia; use amd::AmdGpuController; use intel::IntelGpuController; use nvidia::NvidiaGpuController; -use tracing::{error, info, warn}; use crate::config::{self}; use amdgpu_sysfs::gpu_handle::power_profile_mode::PowerProfileModesTable; use anyhow::Context; use futures::future::LocalBoxFuture; use lact_schema::{ClocksInfo, DeviceInfo, DeviceStats, GpuPciInfo, PciInfo, PowerStates}; +use libdrm_amdgpu_sys::LibDrmAmdgpu; use nvml_wrapper::Nvml; -use std::{cell::OnceCell, collections::HashMap, fs, path::PathBuf, rc::Rc}; +use std::{cell::LazyCell, collections::HashMap, fs, path::PathBuf, rc::Rc}; use tokio::{sync::Notify, task::JoinHandle}; +use tracing::{error, warn}; type FanControlHandle = (Rc, JoinHandle<()>); @@ -74,7 +75,8 @@ impl CommonControllerInfo { pub(crate) fn init_controller( path: PathBuf, pci_db: &pciid_parser::Database, - nvml: &OnceCell>>, + nvml: &LazyCell>>, + amd_drm: &LazyCell>, ) -> anyhow::Result> { let uevent_path = path.join("uevent"); let uevent = fs::read_to_string(uevent_path).context("Could not read 'uevent'")?; @@ -138,27 +140,19 @@ pub(crate) fn init_controller( }; match common.driver.as_str() { - "amdgpu" | "radeon" => match AmdGpuController::new_from_path(common.clone()) { - Ok(controller) => return Ok(Box::new(controller)), - Err(err) => error!("could not initialize AMD controller: {err:#}"), - }, + "amdgpu" | "radeon" => { + match AmdGpuController::new_from_path(common.clone(), amd_drm.as_ref()) { + Ok(controller) => return Ok(Box::new(controller)), + Err(err) => error!("could not initialize AMD controller: {err:#}"), + } + } "i915" | "xe" => match IntelGpuController::new(common.clone()) { Ok(controller) => return Ok(Box::new(controller)), Err(err) => error!("could not initialize Intel controller: {err:#}"), }, "nvidia" => { - let nvml = nvml.get_or_init(|| match Nvml::init() { - Ok(nvml) => { - info!("Nvidia management library loaded"); - Some(Rc::new(nvml)) - } - Err(err) => { - error!("could not load Nvidia management library: {err}, Nvidia controls will not be available"); - None - } - }); - if let Some(nvml) = nvml { - match NvidiaGpuController::new(common.clone(), nvml.clone()) { + if let Some(nvml) = nvml.as_ref().cloned() { + match NvidiaGpuController::new(common.clone(), nvml) { Ok(controller) => { return Ok(Box::new(controller)); } @@ -178,7 +172,8 @@ pub(crate) fn init_controller( // We use the AMD controller as the fallback even for non-AMD devices, it will at least // display basic device information from the SysFS Ok(Box::new( - AmdGpuController::new_from_path(common).context("Could initialize fallback controller")?, + AmdGpuController::new_from_path(common, amd_drm.as_ref()) + .context("Could initialize fallback controller")?, )) } diff --git a/lact-daemon/src/server/handler.rs b/lact-daemon/src/server/handler.rs index 42e897a..ca91451 100644 --- a/lact-daemon/src/server/handler.rs +++ b/lact-daemon/src/server/handler.rs @@ -17,13 +17,15 @@ use lact_schema::{ ClocksInfo, DeviceInfo, DeviceListEntry, DeviceStats, FanControlMode, FanOptions, PmfwOptions, PowerStates, ProfileRule, ProfileWatcherState, ProfilesInfo, }; +use libdrm_amdgpu_sys::LibDrmAmdgpu; use libflate::gzip; use nix::libc; +use nvml_wrapper::Nvml; use os_release::OS_RELEASE; use pciid_parser::Database; use serde_json::json; use std::{ - cell::{Cell, OnceCell, RefCell}, + cell::{Cell, LazyCell, RefCell}, collections::{BTreeMap, HashMap}, env, fs::{self, File, Permissions}, @@ -919,7 +921,27 @@ fn load_controllers(base_path: &Path) -> anyhow::Result>> = LazyCell::new(|| match Nvml::init() { + Ok(nvml) => { + info!("Nvidia management library loaded"); + Some(Rc::new(nvml)) + } + Err(err) => { + error!("could not load Nvidia management library: {err}, Nvidia controls will not be available"); + None + } + }); + + let amd_drm: LazyCell> = LazyCell::new(|| match LibDrmAmdgpu::new() { + Ok(drm) => { + info!("AMDGPU DRM initialized"); + Some(drm) + } + Err(err) => { + error!("failed to initialize AMDGPU DRM: {err}"); + None + } + }); for entry in base_path .read_dir() @@ -935,7 +957,7 @@ fn load_controllers(base_path: &Path) -> anyhow::Result { let info = controller.controller_info(); let id = info.build_id(); diff --git a/pkg/recipes/lact-headless/recipe.yml b/pkg/recipes/lact-headless/recipe.yml index 5d927b9..d58ff83 100644 --- a/pkg/recipes/lact-headless/recipe.yml +++ b/pkg/recipes/lact-headless/recipe.yml @@ -28,7 +28,7 @@ env: configure: steps: - cmd: curl -o /tmp/install_rust.sh $RUSTUP_URL - - cmd: sh /tmp/install_rust.sh -y --default-toolchain 1.78 + - cmd: sh /tmp/install_rust.sh -y --default-toolchain 1.80 - cmd: pacman -Syu --noconfirm pkg: true build: diff --git a/pkg/recipes/lact-libadwaita/recipe.yml b/pkg/recipes/lact-libadwaita/recipe.yml index 2cd5dce..cfd65e8 100644 --- a/pkg/recipes/lact-libadwaita/recipe.yml +++ b/pkg/recipes/lact-libadwaita/recipe.yml @@ -26,7 +26,7 @@ env: configure: steps: - cmd: curl -o /tmp/install_rust.sh $RUSTUP_URL - - cmd: sh /tmp/install_rust.sh -y --default-toolchain 1.78 + - cmd: sh /tmp/install_rust.sh -y --default-toolchain 1.80 - cmd: >- curl -o /tmp/blueprint-compiler.deb http://de.archive.ubuntu.com/ubuntu/pool/universe/b/blueprint-compiler/blueprint-compiler_0.14.0-1_all.deb && apt install -y /tmp/blueprint-compiler.deb diff --git a/pkg/recipes/lact/recipe.yml b/pkg/recipes/lact/recipe.yml index db7423a..c0c658b 100644 --- a/pkg/recipes/lact/recipe.yml +++ b/pkg/recipes/lact/recipe.yml @@ -28,7 +28,7 @@ env: configure: steps: - cmd: curl -o /tmp/install_rust.sh $RUSTUP_URL - - cmd: sh /tmp/install_rust.sh -y --default-toolchain 1.78 + - cmd: sh /tmp/install_rust.sh -y --default-toolchain 1.80 - cmd: >- curl -o /tmp/blueprint-compiler.deb http://de.archive.ubuntu.com/ubuntu/pool/universe/b/blueprint-compiler/blueprint-compiler_0.14.0-1_all.deb && apt install -y /tmp/blueprint-compiler.deb diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 5198580..2e2b8c8 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "1.78.0" +channel = "1.82.0"