Compare commits

...

5 Commits

Author SHA1 Message Date
Luke D Jones b8384c55c3 Bump changelog version 2021-03-10 11:21:09 +13:00
Luke D Jones dfe1f02101 Hotfix: Catch some edge-cases exposed on fedora 34 2021-03-10 11:20:19 +13:00
Luke D Jones 7c2fb0be81 Hotfix: Nvidia module handling improved 2021-03-10 10:15:59 +13:00
Luke D Jones b05f680650 Test and create /etc/X11/xorg.conf.d/ if not exist 2021-03-10 09:20:59 +13:00
Luke D Jones 2a9a436f9c Add nvidia-uvm to module list 2021-03-10 07:34:03 +13:00
9 changed files with 88 additions and 52 deletions
+9
View File
@@ -6,6 +6,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
# [3.1.2] - 2021-03-10
### Changed
- Test and create /etc/X11/xorg.conf.d/ if it doesn't exist
- Hotfix to better report module issues
# [3.1.1] - 2021-03-10
### Changed
- Add missing nvidia module nvidia_uvm to gfx ctrl list
# [3.1.0] - 2021-03-09 # [3.1.0] - 2021-03-09
### Added ### Added
- GU502LU led-modes - GU502LU led-modes
Generated
+1 -1
View File
@@ -187,7 +187,7 @@ dependencies = [
[[package]] [[package]]
name = "daemon" name = "daemon"
version = "3.1.0" version = "3.1.2"
dependencies = [ dependencies = [
"env_logger", "env_logger",
"intel-pstate", "intel-pstate",
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "daemon" name = "daemon"
version = "3.1.0" version = "3.1.2"
license = "MPL-2.0" license = "MPL-2.0"
readme = "README.md" readme = "README.md"
authors = ["Luke <luke@ljones.dev>"] authors = ["Luke <luke@ljones.dev>"]
-12
View File
@@ -6,13 +6,7 @@ use crate::error::RogError;
#[derive(Debug)] #[derive(Debug)]
pub enum GfxError { pub enum GfxError {
ParseVendor, ParseVendor,
Path(String, std::io::Error),
Read(String, std::io::Error),
Write(String, std::io::Error),
Module(String, std::io::Error),
Bus(String, std::io::Error), Bus(String, std::io::Error),
Command(String, std::io::Error),
Modprobe(String),
DisplayManager(String), DisplayManager(String),
} }
@@ -21,13 +15,7 @@ impl fmt::Display for GfxError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
GfxError::ParseVendor => write!(f, "Could not parse vendor name"), GfxError::ParseVendor => write!(f, "Could not parse vendor name"),
GfxError::Path(path, error) => write!(f, "Path {}: {}", path, error),
GfxError::Read(path, error) => write!(f, "Read {}: {}", path, error),
GfxError::Write(path, error) => write!(f, "Write {}: {}", path, error),
GfxError::Module(func, error) => write!(f, "Module error: {}: {}", func, error),
GfxError::Bus(func, error) => write!(f, "Bus error: {}: {}", func, error), GfxError::Bus(func, error) => write!(f, "Bus error: {}: {}", func, error),
GfxError::Command(func, error) => write!(f, "Command exec error: {}: {}", func, error),
GfxError::Modprobe(detail) => write!(f, "Modprobe error: {}", detail),
GfxError::DisplayManager(detail) => write!(f, "Display manager: {}", detail), GfxError::DisplayManager(detail) => write!(f, "Display manager: {}", detail),
} }
} }
+61 -31
View File
@@ -2,10 +2,10 @@ use ctrl_gfx::error::GfxError;
use ctrl_gfx::*; use ctrl_gfx::*;
use log::{error, info, warn}; use log::{error, info, warn};
use rog_types::gfx_vendors::GfxVendors; use rog_types::gfx_vendors::GfxVendors;
use std::io::Write;
use std::iter::FromIterator; use std::iter::FromIterator;
use std::process::Command; use std::process::Command;
use std::str::FromStr; use std::str::FromStr;
use std::{io::Write, ops::Add, path::Path};
use std::{sync::Arc, sync::Mutex}; use std::{sync::Arc, sync::Mutex};
use sysfs_class::{PciDevice, SysClass}; use sysfs_class::{PciDevice, SysClass};
use system::{GraphicsDevice, PciBus}; use system::{GraphicsDevice, PciBus};
@@ -47,8 +47,9 @@ impl Dbus for CtrlGraphics {
fn set_vendor(&mut self, vendor: String) { fn set_vendor(&mut self, vendor: String) {
if let Ok(tmp) = GfxVendors::from_str(&vendor) { if let Ok(tmp) = GfxVendors::from_str(&vendor) {
info!("Switching gfx mode to {}", vendor);
let msg = self.set_gfx_config(tmp).unwrap_or_else(|err| { let msg = self.set_gfx_config(tmp).unwrap_or_else(|err| {
warn!("{}", err); error!("{}", err);
format!("Failed: {}", err.to_string()) format!("Failed: {}", err.to_string())
}); });
self.notify_gfx(&vendor) self.notify_gfx(&vendor)
@@ -173,7 +174,7 @@ impl CtrlGraphics {
fn get_runtime_status() -> Result<String, RogError> { fn get_runtime_status() -> Result<String, RogError> {
const PATH: &str = "/sys/bus/pci/devices/0000:01:00.0/power/runtime_status"; const PATH: &str = "/sys/bus/pci/devices/0000:01:00.0/power/runtime_status";
let buf = std::fs::read_to_string(PATH).map_err(|err| GfxError::Read(PATH.into(), err))?; let buf = std::fs::read_to_string(PATH).map_err(|err| RogError::Read(PATH.into(), err))?;
Ok(buf) Ok(buf)
} }
@@ -190,7 +191,7 @@ impl CtrlGraphics {
.arg(action) .arg(action)
.arg("nvidia-fallback.service") .arg("nvidia-fallback.service")
.status() .status()
.map_err(|err| GfxError::Command("systemctl".into(), err))?; .map_err(|err| RogError::Command("systemctl".into(), err))?;
if !status.success() { if !status.success() {
// Error is ignored in case this service is removed // Error is ignored in case this service is removed
@@ -210,17 +211,22 @@ impl CtrlGraphics {
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_END].concat() [PRIMARY_GPU_BEGIN, PRIMARY_GPU_END].concat()
}; };
info!("Writing {}", PRIMARY_GPU_XORG_PATH); if !Path::new(XORG_PATH).exists() {
std::fs::create_dir(XORG_PATH).map_err(|err| RogError::Write(XORG_PATH.into(), err))?;
}
let file = XORG_PATH.to_string().add(XORG_FILE);
info!("Writing {}", file);
let mut file = std::fs::OpenOptions::new() let mut file = std::fs::OpenOptions::new()
.create(true) .create(true)
.truncate(true) .truncate(true)
.write(true) .write(true)
.open(PRIMARY_GPU_XORG_PATH) .open(&file)
.map_err(|err| GfxError::Write(PRIMARY_GPU_XORG_PATH.into(), err))?; .map_err(|err| RogError::Write(file, err))?;
file.write_all(&text) file.write_all(&text)
.and_then(|_| file.sync_all()) .and_then(|_| file.sync_all())
.map_err(|err| GfxError::Write(MODPROBE_PATH.into(), err))?; .map_err(|err| RogError::Write(MODPROBE_PATH.into(), err))?;
Ok(()) Ok(())
} }
@@ -232,11 +238,11 @@ impl CtrlGraphics {
.truncate(true) .truncate(true)
.write(true) .write(true)
.open(MODPROBE_PATH) .open(MODPROBE_PATH)
.map_err(|err| GfxError::Path(MODPROBE_PATH.into(), err))?; .map_err(|err| RogError::Path(MODPROBE_PATH.into(), err))?;
file.write_all(MODPROBE_BASE) file.write_all(MODPROBE_BASE)
.and_then(|_| file.sync_all()) .and_then(|_| file.sync_all())
.map_err(|err| GfxError::Write(MODPROBE_PATH.into(), err))?; .map_err(|err| RogError::Write(MODPROBE_PATH.into(), err))?;
Ok(()) Ok(())
} }
@@ -249,55 +255,70 @@ impl CtrlGraphics {
let removes = self.nvidia.iter().map(|dev| dev.remove()); let removes = self.nvidia.iter().map(|dev| dev.remove());
Result::from_iter(unbinds.chain(removes)) Result::from_iter(unbinds.chain(removes))
.map_err(|err| GfxError::Command("device unbind error".into(), err))?; .map_err(|err| RogError::Command("device unbind error".into(), err))?;
Ok(()) Ok(())
} }
fn do_driver_action(driver: &str, action: &str) -> Result<(), RogError> { fn do_driver_action(driver: &str, action: &str) -> Result<(), RogError> {
let mut cmd = Command::new(action); let mut cmd;
if Self::kmod_exists() {
info!("using kmod");
cmd = Command::new("kmod");
cmd.arg(action);
} else {
cmd = Command::new(action);
}
cmd.arg(driver); cmd.arg(driver);
let status = cmd let output = cmd
.status() .output()
.map_err(|err| GfxError::Command(format!("{:?}", cmd), err))?; .map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
if !status.success() { if !output.status.success() {
let msg = format!("{} {} failed: {:?}", action, driver, status); if output.stderr.ends_with("is not currently loaded\n".as_bytes()) {
error!("{}", msg); return Ok(())
return Err(GfxError::Modprobe(msg).into()); }
if output.stderr.ends_with("Permission denied\n".as_bytes()) {
let msg = format!("{} {} failed: {:?}", action, driver, String::from_utf8_lossy(&output.stderr));
warn!("{}", msg);
warn!("It may be safe to ignore the above error, run `lsmod |grep nvidia` to confirm modules loaded");
return Ok(())
}
let msg = format!("{} {} failed: {:?}", action, driver, String::from_utf8_lossy(&output.stderr));
return Err(RogError::Modprobe(msg));
} }
Ok(()) Ok(())
} }
fn do_display_manager_action(action: &str) -> Result<(), RogError> { fn do_display_manager_action(action: &str) -> Result<(), RogError> {
let service = "display-manager.service";
let mut cmd = Command::new("systemctl"); let mut cmd = Command::new("systemctl");
cmd.arg(action); cmd.arg(action);
cmd.arg(service); cmd.arg(DISPLAY_MANAGER);
let status = cmd let status = cmd
.status() .status()
.map_err(|err| GfxError::Command(format!("{:?}", cmd), err))?; .map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
if !status.success() { if !status.success() {
let msg = format!("systemctl {} {} failed: {:?}", action, service, status); let msg = format!(
error!("{}", msg); "systemctl {} {} failed: {:?}",
action, DISPLAY_MANAGER, status
);
return Err(GfxError::DisplayManager(msg).into()); return Err(GfxError::DisplayManager(msg).into());
} }
Ok(()) Ok(())
} }
fn wait_display_manager_inactive() -> Result<(), RogError> { fn wait_display_manager_inactive() -> Result<(), RogError> {
let service = "display-manager.service";
let mut cmd = Command::new("systemctl"); let mut cmd = Command::new("systemctl");
cmd.arg("is-active"); cmd.arg("is-active");
cmd.arg(service); cmd.arg(DISPLAY_MANAGER);
let mut count = 0; let mut count = 0;
while count <= 4 { while count <= 4 {
let output = cmd let output = cmd
.output() .output()
.map_err(|err| GfxError::Command(format!("{:?}", cmd), err))?; .map_err(|err| RogError::Command(format!("{:?}", cmd), err))?;
if output.stdout.starts_with("inactive".as_bytes()) { if output.stdout.starts_with("inactive".as_bytes()) {
return Ok(()); return Ok(());
} }
@@ -309,6 +330,17 @@ impl CtrlGraphics {
); );
} }
fn kmod_exists() -> bool {
let mut cmd = Command::new("which");
cmd.arg("kmod");
if let Ok(output) = cmd
.output() {
return output.status.success() && output.stdout.ends_with("kmod".as_bytes())
}
//Path::new("/usr/bin/kmod").exists()
false
}
pub fn do_vendor_tasks(&mut self, vendor: GfxVendors) -> Result<(), RogError> { pub fn do_vendor_tasks(&mut self, vendor: GfxVendors) -> Result<(), RogError> {
Self::write_xorg_conf(vendor)?; Self::write_xorg_conf(vendor)?;
Self::write_modprobe_conf()?; // TODO: Not required here, should put in startup? Self::write_modprobe_conf()?; // TODO: Not required here, should put in startup?
@@ -318,18 +350,16 @@ impl CtrlGraphics {
.rescan() .rescan()
.map_err(|err| GfxError::Bus("bus rescan error".into(), err))?; .map_err(|err| GfxError::Bus("bus rescan error".into(), err))?;
let drivers = vec!["nvidia_drm", "nvidia_modeset", "nvidia"]; // i2c_nvidia_gpu?
match vendor { match vendor {
GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => { GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => {
for driver in drivers { for driver in NVIDIA_DRIVERS.iter() {
Self::do_driver_action(driver, "modprobe")?; Self::do_driver_action(driver, "modprobe")?;
} }
} }
// TODO: compute mode, needs different setup // TODO: compute mode, needs different setup
// GfxVendors::Compute => {} // GfxVendors::Compute => {}
GfxVendors::Integrated => { GfxVendors::Integrated => {
for driver in drivers { for driver in NVIDIA_DRIVERS.iter() {
Self::do_driver_action(driver, "rmmod")?; Self::do_driver_action(driver, "rmmod")?;
} }
self.unbind_remove_nvidia()?; self.unbind_remove_nvidia()?;
+6 -1
View File
@@ -4,6 +4,10 @@ pub mod gfx;
pub mod system; pub mod system;
const NVIDIA_DRIVERS: [&str; 4] = ["nvidia_drm", "nvidia_modeset", "nvidia_uvm", "nvidia"];
const DISPLAY_MANAGER: &str = "display-manager.service";
const MODPROBE_PATH: &str = "/etc/modprobe.d/asusd.conf"; const MODPROBE_PATH: &str = "/etc/modprobe.d/asusd.conf";
static MODPROBE_BASE: &[u8] = br#"# Automatically generated by asusd static MODPROBE_BASE: &[u8] = br#"# Automatically generated by asusd
@@ -15,7 +19,8 @@ options nvidia NVreg_DynamicPowerManagement=0x02
options nvidia-drm modeset=1 options nvidia-drm modeset=1
"#; "#;
const PRIMARY_GPU_XORG_PATH: &str = "/etc/X11/xorg.conf.d/90-nvidia-primary.conf"; const XORG_FILE: &str = "90-nvidia-primary.conf";
const XORG_PATH: &str = "/etc/X11/xorg.conf.d/";
static PRIMARY_GPU_BEGIN: &[u8] = br#"# Automatically generated by asusd static PRIMARY_GPU_BEGIN: &[u8] = br#"# Automatically generated by asusd
Section "OutputClass" Section "OutputClass"
+4 -4
View File
@@ -31,9 +31,9 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
.filter(None, LevelFilter::Info) .filter(None, LevelFilter::Info)
.init(); .init();
info!("daemon version {}", daemon::VERSION); info!(" daemon v{}", daemon::VERSION);
info!(" rog-dbus version {}", rog_dbus::VERSION); info!(" rog-dbus v{}", rog_dbus::VERSION);
info!("rog-types version {}", rog_types::VERSION); info!("rog-types v{}", rog_types::VERSION);
start_daemon()?; start_daemon()?;
Ok(()) Ok(())
@@ -121,7 +121,7 @@ fn start_daemon() -> Result<(), Box<dyn Error>> {
} }
} }
ctrl.reload() ctrl.reload()
.unwrap_or_else(|err| warn!("Gfx controller: {}", err)); .unwrap_or_else(|err| error!("Gfx controller: {}", err));
ctrl.add_to_server(&mut object_server); ctrl.add_to_server(&mut object_server);
} }
Err(err) => { Err(err) => {
+4
View File
@@ -26,6 +26,8 @@ pub enum RogError {
ReloadFail(String), ReloadFail(String),
GfxSwitching(GfxError), GfxSwitching(GfxError),
Initramfs(String), Initramfs(String),
Modprobe(String),
Command(String, std::io::Error),
} }
impl fmt::Display for RogError { impl fmt::Display for RogError {
@@ -50,6 +52,8 @@ impl fmt::Display for RogError {
RogError::ReloadFail(deets) => write!(f, "Task error: {}", deets), RogError::ReloadFail(deets) => write!(f, "Task error: {}", deets),
RogError::GfxSwitching(deets) => write!(f, "Graphics switching error: {}", deets), RogError::GfxSwitching(deets) => write!(f, "Graphics switching error: {}", deets),
RogError::Initramfs(detail) => write!(f, "Initiramfs error: {}", detail), RogError::Initramfs(detail) => write!(f, "Initiramfs error: {}", detail),
RogError::Modprobe(detail) => write!(f, "Modprobe error: {}", detail),
RogError::Command(func, error) => write!(f, "Command exec error: {}: {}", func, error),
} }
} }
} }
+2 -2
View File
@@ -2,6 +2,7 @@
Description=ASUS Notebook Control Description=ASUS Notebook Control
StartLimitInterval=200 StartLimitInterval=200
StartLimitBurst=2 StartLimitBurst=2
Before=display-manager.service
[Service] [Service]
ExecStart=/usr/bin/asusd ExecStart=/usr/bin/asusd
@@ -9,5 +10,4 @@ Restart=on-failure
Restart=always Restart=always
RestartSec=1 RestartSec=1
Type=dbus Type=dbus
BusName=org.asuslinux.Daemon BusName=org.asuslinux.Daemon
Before=display-manager.service