pcid: read REDBEAR_DRIVER_PCI_IRQ_MODE / DISABLE_ACCEL env vars
The pcid_interface crate now reads the two env vars emitted by driver-manager's SpawnDecision committee: - REDBEAR_DRIVER_PCI_IRQ_MODE: lets the spawned child know whether to fall back to MSI / INTx instead of MSI-X - REDBEAR_DRIVER_DISABLE_ACCEL: lets the spawned child suppress hardware acceleration (matches PciQuirkFlags::DISABLE_ACCEL) Both values are stored on PciFunctionHandle and exposed via accessors (irq_mode_hint / disable_accel_hint) so the driver daemons can read them at startup. 6 new unit tests cover the env-var parsing. Refs: local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md § 5.2 D2.7.
This commit is contained in:
@@ -302,6 +302,23 @@ pub struct PciFunctionHandle {
|
|||||||
channel: File,
|
channel: File,
|
||||||
config: SubdriverArguments,
|
config: SubdriverArguments,
|
||||||
mapped_bars: [Option<MappedBar>; 6],
|
mapped_bars: [Option<MappedBar>; 6],
|
||||||
|
irq_mode_hint: Option<String>,
|
||||||
|
disable_accel_hint: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_irq_mode_hint() -> Option<String> {
|
||||||
|
match env::var("REDBEAR_DRIVER_PCI_IRQ_MODE") {
|
||||||
|
Ok(v) if !v.is_empty() => Some(v),
|
||||||
|
Ok(_) => None,
|
||||||
|
Err(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_disable_accel_hint() -> bool {
|
||||||
|
match env::var("REDBEAR_DRIVER_DISABLE_ACCEL") {
|
||||||
|
Ok(v) if v == "1" || v.eq_ignore_ascii_case("true") || v == "yes" => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send<T: Serialize>(w: &mut File, message: &T) {
|
fn send<T: Serialize>(w: &mut File, message: &T) {
|
||||||
@@ -378,9 +395,26 @@ impl PciFunctionHandle {
|
|||||||
channel,
|
channel,
|
||||||
config,
|
config,
|
||||||
mapped_bars: [const { None }; 6],
|
mapped_bars: [const { None }; 6],
|
||||||
|
irq_mode_hint: read_irq_mode_hint(),
|
||||||
|
disable_accel_hint: read_disable_accel_hint(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the IRQ-mode hint read from `REDBEAR_DRIVER_PCI_IRQ_MODE` at
|
||||||
|
/// connect time, or `None` if the env var was unset. Drivers should
|
||||||
|
/// honour this hint when allocating interrupt vectors.
|
||||||
|
pub fn irq_mode_hint(&self) -> Option<&str> {
|
||||||
|
self.irq_mode_hint.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the disable-acceleration hint read from
|
||||||
|
/// `REDBEAR_DRIVER_DISABLE_ACCEL` at connect time. Drivers (notably
|
||||||
|
/// GPU drivers) should suppress hardware acceleration paths when this
|
||||||
|
/// returns `true`.
|
||||||
|
pub fn disable_accel_hint(&self) -> bool {
|
||||||
|
self.disable_accel_hint
|
||||||
|
}
|
||||||
|
|
||||||
pub fn into_inner_fd(self) -> RawFd {
|
pub fn into_inner_fd(self) -> RawFd {
|
||||||
self.channel.into_raw_fd()
|
self.channel.into_raw_fd()
|
||||||
}
|
}
|
||||||
@@ -544,3 +578,65 @@ pub fn pci_daemon<F: FnOnce(Daemon, PciFunctionHandle) -> !>(f: F) -> ! {
|
|||||||
f(daemon, pcid_handle)
|
f(daemon, pcid_handle)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod hint_tests {
|
||||||
|
use super::{read_disable_accel_hint, read_irq_mode_hint};
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
static ENV_LOCK: Mutex<()> = Mutex::new(());
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn irq_mode_hint_returns_none_when_unset() {
|
||||||
|
let _g = ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner());
|
||||||
|
unsafe { std::env::remove_var("REDBEAR_DRIVER_PCI_IRQ_MODE") };
|
||||||
|
assert!(read_irq_mode_hint().is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn irq_mode_hint_returns_some_when_set() {
|
||||||
|
let _g = ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner());
|
||||||
|
unsafe { std::env::set_var("REDBEAR_DRIVER_PCI_IRQ_MODE", "intx_or_msi") };
|
||||||
|
let v = read_irq_mode_hint();
|
||||||
|
unsafe { std::env::remove_var("REDBEAR_DRIVER_PCI_IRQ_MODE") };
|
||||||
|
assert_eq!(v.as_deref(), Some("intx_or_msi"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn irq_mode_hint_returns_none_for_empty_value() {
|
||||||
|
let _g = ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner());
|
||||||
|
unsafe { std::env::set_var("REDBEAR_DRIVER_PCI_IRQ_MODE", "") };
|
||||||
|
let v = read_irq_mode_hint();
|
||||||
|
unsafe { std::env::remove_var("REDBEAR_DRIVER_PCI_IRQ_MODE") };
|
||||||
|
assert!(v.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn disable_accel_hint_defaults_false() {
|
||||||
|
let _g = ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner());
|
||||||
|
unsafe { std::env::remove_var("REDBEAR_DRIVER_DISABLE_ACCEL") };
|
||||||
|
assert!(!read_disable_accel_hint());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn disable_accel_hint_accepts_truthy_values() {
|
||||||
|
let _g = ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner());
|
||||||
|
for truthy in &["1", "true", "TRUE", "yes"] {
|
||||||
|
unsafe { std::env::set_var("REDBEAR_DRIVER_DISABLE_ACCEL", truthy) };
|
||||||
|
let v = read_disable_accel_hint();
|
||||||
|
unsafe { std::env::remove_var("REDBEAR_DRIVER_DISABLE_ACCEL") };
|
||||||
|
assert!(v, "value {:?} should be truthy", truthy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn disable_accel_hint_rejects_falsy_values() {
|
||||||
|
let _g = ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner());
|
||||||
|
for falsy in &["0", "false", "no", ""] {
|
||||||
|
unsafe { std::env::set_var("REDBEAR_DRIVER_DISABLE_ACCEL", falsy) };
|
||||||
|
let v = read_disable_accel_hint();
|
||||||
|
unsafe { std::env::remove_var("REDBEAR_DRIVER_DISABLE_ACCEL") };
|
||||||
|
assert!(!v, "value {:?} should be falsy", falsy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user