redbear-iwlwifi: log PCI quirk flags at Wi-Fi device detection (Gap 12)
R1-R10 audit Gap 12: redbear-iwlwifi had zero PCI quirk
consumption at Wi-Fi device detection time. The linux-kpi
crate ships pci_has_quirk and pci_get_quirk_flags for
consumers in C-land, but the Rust-side lookup function
lookup_pci_quirks was not called from this driver. Every
Intel Wi-Fi NIC passed the data-driven quirk table
without a single log line.
This change:
- Adds source/src/quirks.rs with one public function,
log_wifi_quirks(location, vendor, device) that:
1. Builds a PciDeviceInfo from the candidate's location
and the just-parsed vendor / device IDs.
2. Calls redox_driver_sys::quirks::lookup_pci_quirks.
3. Logs the resulting flag word (info-level on a hit,
debug-level on empty).
4. Returns the flags so the caller can gate probe /
interrupt selection on specific bits (NO_MSI,
NO_MSIX, DISABLE_ACCEL) in a follow-up.
- Wires the call into detect_candidates() at
src/main.rs:494, right after the Intel vendor / class /
subclass match — the canonical identification point.
The location is now available (it was already parsed
via parse_location_from_config_path) and vendor_id /
device_id are in scope from the PCI config read.
Implementation note: this module bypasses the
linux_kpi::pci::pci_get_quirk_flags C FFI because that
function takes *mut PciDev and the bus / dev / func
fields are private to the linux-kpi crate. The
underlying lookup is identical — linux-kpi's FFI is a
thin wrapper around the same redox_driver_sys function
we call here. Going through PciDeviceInfo directly is
the natural Rust path; the C FFI remains available for
C-side consumers that already hold a struct pci_dev*.
3 unit tests cover the wiring:
- zeroed device returns empty
- unmatched vendor returns empty
- real Intel NIC ID round-trips through PciQuirkFlags
without losing bits
No Cargo.toml change needed: redox-driver-sys was
already a direct dependency.
This commit is contained in:
@@ -12,6 +12,8 @@ use redox_driver_sys::pci::{PCI_VENDOR_ID_INTEL, PciLocation};
|
||||
use std::ffi::CString;
|
||||
use thiserror::Error;
|
||||
|
||||
mod quirks;
|
||||
|
||||
struct StderrLogger;
|
||||
|
||||
impl log::Log for StderrLogger {
|
||||
@@ -491,6 +493,7 @@ fn detect_candidates(firmware_root: &PathBuf) -> Result<Vec<Candidate>, DriverEr
|
||||
}
|
||||
let subsystem_id = u16::from_le_bytes([config[0x2E], config[0x2F]]);
|
||||
let location = parse_location_from_config_path(&config_path)?;
|
||||
quirks::log_wifi_quirks(location, vendor_id, device_id);
|
||||
let (family, ucode_candidates, pnvm_candidate) =
|
||||
intel_firmware_candidates(device_id, subsystem_id);
|
||||
let selected_ucode = ucode_candidates
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
//! R1–R10 audit Gap 12: PCI quirk flag reporting at Wi-Fi device detection.
|
||||
//!
|
||||
//! `redox_driver_sys::quirks::lookup_pci_quirks` is the data-driven
|
||||
//! lookup the audit identified as missing. redbear-iwlwifi now
|
||||
//! calls it at detection time and logs the resulting flag word.
|
||||
//! Future revisions can gate probe / interrupt selection on
|
||||
//! specific bits (NO_MSI, NO_MSIX, DISABLE_ACCEL) without
|
||||
//! further FFI work.
|
||||
//!
|
||||
//! Note: this module bypasses the `linux_kpi::pci::pci_get_quirk_flags`
|
||||
//! C FFI because that function takes a `*mut PciDev` whose `bus`,
|
||||
//! `dev`, `func` fields are private to the linux-kpi crate. The
|
||||
//! underlying lookup is the same `lookup_pci_quirks` we call here;
|
||||
//! linux-kpi is just a C-ABI wrapper around it. Going through
|
||||
//! `PciDeviceInfo` directly is the natural Rust path.
|
||||
|
||||
use redox_driver_sys::pci::{PciDeviceInfo, PciLocation};
|
||||
use redox_driver_sys::quirks::{lookup_pci_quirks, PciQuirkFlags};
|
||||
|
||||
/// Run the data-driven quirk lookup for the given PCI device and
|
||||
/// log the resulting flag word. Returns the flags so the caller
|
||||
/// can react to specific bits.
|
||||
pub(crate) fn log_wifi_quirks(location: PciLocation, vendor: u16, device: u16) -> PciQuirkFlags {
|
||||
let info = PciDeviceInfo {
|
||||
location,
|
||||
vendor_id: vendor,
|
||||
device_id: device,
|
||||
subsystem_vendor_id: 0,
|
||||
subsystem_device_id: 0,
|
||||
revision: 0,
|
||||
class_code: 0,
|
||||
subclass: 0,
|
||||
prog_if: 0,
|
||||
header_type: 0,
|
||||
irq: None,
|
||||
bars: Vec::new(),
|
||||
capabilities: Vec::new(),
|
||||
};
|
||||
let flags = lookup_pci_quirks(&info);
|
||||
if !flags.is_empty() {
|
||||
log::info!(
|
||||
"redbear-iwlwifi: quirks for {:04X}:{:04X} at {} flags=0x{:016X}",
|
||||
vendor,
|
||||
device,
|
||||
location,
|
||||
flags.bits(),
|
||||
);
|
||||
} else {
|
||||
log::debug!(
|
||||
"redbear-iwlwifi: no quirks for {:04X}:{:04X} at {}",
|
||||
vendor,
|
||||
device,
|
||||
location,
|
||||
);
|
||||
}
|
||||
flags
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn loc(bus: u8, device: u8, function: u8) -> PciLocation {
|
||||
PciLocation {
|
||||
segment: 0,
|
||||
bus,
|
||||
device,
|
||||
function,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn log_wifi_quirks_returns_empty_for_zeroed_device() {
|
||||
let flags = log_wifi_quirks(loc(0, 0, 0), 0, 0);
|
||||
assert!(flags.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn log_wifi_quirks_returns_empty_for_unmatched_vendor() {
|
||||
let flags = log_wifi_quirks(loc(1, 2, 0), 0xDEAD, 0xBEEF);
|
||||
assert!(flags.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn log_wifi_quirks_returns_known_flag_for_intel_wifi() {
|
||||
let flags = log_wifi_quirks(loc(2, 0, 0), 0x8086, 0x1533);
|
||||
// Round-trip through the bitset to confirm the value
|
||||
// survives the conversion. Whether flags is empty or not
|
||||
// depends on whether the table has this entry.
|
||||
let parsed = PciQuirkFlags::from_bits_truncate(flags.bits());
|
||||
assert_eq!(parsed.bits(), flags.bits());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user