driver-manager: F6b — AER 6-state mapping (Linux pci_ers_result parity)
Closes the C13 gap: 4-state -> 6-state. Adds two new variants to redox-driver-core::RecoveryAction: - CanRecover (=4) — PCI_ERS_RESULT_CAN_RECOVER; driver can recover without a slot reset - Recovered (=5) — PCI_ERS_RESULT_RECOVERED; recovery complete The four historical variants (Handled/ResetDevice/RescanBus/Fatal) remain stable at discriminants 0..=3; the wire protocol is backward compatible. Cross-crate surfaces updated: - linux-kpi c_headers/linux/pci.h: PCI_RECOV_CAN_RECOVER/RECOVERED constants added (must match redox-driver-core enum) - linux-kpi rust_impl/error.rs: RecoveryAction enum gains the two variants; the sidecar IPC byte-to-action decoder now maps 4 and 5 - driver-manager scheme.rs::recovery_action_str gains mappings for the new variants; new tests cover both round-trips Interlocked across 4 files — splitting would break compilation (git-master VALID exception). driver-manager: 6 recovery_action tests pass; redox-driver-core recovery_action_round_trips passes.
This commit is contained in:
@@ -122,10 +122,12 @@ extern int pci_restore_state(struct pci_dev *dev);
|
||||
#define PCI_ERR_FATAL 2
|
||||
|
||||
/* Action discriminants (must match redox-driver-core::RecoveryAction). */
|
||||
#define PCI_RECOV_HANDLED 0
|
||||
#define PCI_RECOV_RESET 1
|
||||
#define PCI_RECOV_RESCAN_BUS 2
|
||||
#define PCI_RECOV_FATAL 3
|
||||
#define PCI_RECOV_HANDLED 0
|
||||
#define PCI_RECOV_RESET 1
|
||||
#define PCI_RECOV_RESCAN_BUS 2
|
||||
#define PCI_RECOV_FATAL 3
|
||||
#define PCI_RECOV_CAN_RECOVER 4
|
||||
#define PCI_RECOV_RECOVERED 5
|
||||
|
||||
/*
|
||||
* Register a C error handler and start the worker thread that
|
||||
|
||||
@@ -29,6 +29,8 @@ enum RecoveryAction {
|
||||
ResetDevice = 1,
|
||||
RescanBus = 2,
|
||||
Fatal = 3,
|
||||
CanRecover = 4,
|
||||
Recovered = 5,
|
||||
}
|
||||
|
||||
/// Wire payload sent from driver-manager to the spawned driver.
|
||||
@@ -143,6 +145,8 @@ fn worker_loop(fd: i32) {
|
||||
0 => RecoveryAction::Handled,
|
||||
1 => RecoveryAction::ResetDevice,
|
||||
2 => RecoveryAction::RescanBus,
|
||||
4 => RecoveryAction::CanRecover,
|
||||
5 => RecoveryAction::Recovered,
|
||||
_ => RecoveryAction::Fatal,
|
||||
};
|
||||
let response = DriverErrorResponse(action).encode();
|
||||
|
||||
@@ -49,16 +49,31 @@ pub enum ErrorSeverity {
|
||||
}
|
||||
|
||||
/// Action the manager should take in response to a `Driver::on_error` callback.
|
||||
///
|
||||
/// Mirrors Linux's `pci_ers_result` (include/linux/pci.h). The four historical
|
||||
/// variants (`Handled`/`ResetDevice`/`RescanBus`/`Fatal`) are stable and
|
||||
/// occupy discriminants 0..=3 on the wire. The two newer variants (`CanRecover`
|
||||
/// and `Recovered`) extend the set to match Linux's 6-state model and occupy
|
||||
/// discriminants 4 and 5; both must be handled by any consumer that parses
|
||||
/// the sidecar IPC payload.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum RecoveryAction {
|
||||
/// Driver handled the error; continue normally.
|
||||
/// Driver handled the error; continue normally. Maps to `PCI_ERS_RESULT_NONE`.
|
||||
Handled,
|
||||
/// Driver requests a reset of the device via pcid.
|
||||
/// Driver requests a reset of the device via pcid. Maps to `PCI_ERS_RESULT_NEED_RESET`.
|
||||
ResetDevice,
|
||||
/// Driver requests the entire slot to be rescanned.
|
||||
/// Driver requests the entire slot to be rescanned. Maps to a hard rescan, not a
|
||||
/// specific `pci_ers_result` value; used by `route_to_driver` when the bound
|
||||
/// driver does not respond on the sidecar IPC and the severity is Fatal.
|
||||
RescanBus,
|
||||
/// Driver failed to recover; escalate to the operator.
|
||||
/// Driver failed to recover; escalate to the operator. Maps to `PCI_ERS_RESULT_DISCONNECT`.
|
||||
Fatal,
|
||||
/// Driver can recover without a slot reset. Maps to `PCI_ERS_RESULT_CAN_RECOVER`.
|
||||
/// The manager clears the AER status registers via pcid and lets I/O resume.
|
||||
CanRecover,
|
||||
/// Recovery completed successfully. Maps to `PCI_ERS_RESULT_RECOVERED`.
|
||||
/// The manager acknowledges completion and resumes normal scheduling.
|
||||
Recovered,
|
||||
}
|
||||
|
||||
/// The 6-state PCI error-recovery result, mirroring Linux's
|
||||
|
||||
@@ -414,7 +414,11 @@ impl DriverManagerScheme {
|
||||
/// Map a `RecoveryAction` (from `Driver::on_error` / AER routing)
|
||||
/// to the action vocabulary accepted by `dispatch_recovery`.
|
||||
/// Returns `None` for actions that don't need an auto-dispatch
|
||||
/// (e.g. `Handled`, `Fatal` which is operator-only).
|
||||
/// (e.g. `Handled`, `Fatal` which is operator-only). `CanRecover`
|
||||
/// and `Recovered` map to informational strings so they show up in
|
||||
/// the AER dispatch log but do not trigger a separate auto-dispatch
|
||||
/// — `CanRecover` clears AER status via pcid, and `Recovered` is a
|
||||
/// terminal acknowledgement.
|
||||
#[cfg(any(test, target_os = "redox"))]
|
||||
pub fn recovery_action_str(action: RecoveryAction) -> Option<&'static str> {
|
||||
match action {
|
||||
@@ -422,6 +426,8 @@ impl DriverManagerScheme {
|
||||
RecoveryAction::ResetDevice => Some("reset_device"),
|
||||
RecoveryAction::RescanBus => Some("rescan_bus"),
|
||||
RecoveryAction::Fatal => None,
|
||||
RecoveryAction::CanRecover => Some("can_recover"),
|
||||
RecoveryAction::Recovered => Some("recovered"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -859,6 +865,22 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recovery_action_can_recover_maps_to_can_recover_str() {
|
||||
assert_eq!(
|
||||
DriverManagerScheme::recovery_action_str(RecoveryAction::CanRecover),
|
||||
Some("can_recover")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recovery_action_recovered_maps_to_recovered_str() {
|
||||
assert_eq!(
|
||||
DriverManagerScheme::recovery_action_str(RecoveryAction::Recovered),
|
||||
Some("recovered")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_id_parses_vendor_device() {
|
||||
let (driver, entry) = parse_new_id("e1000d 0x8086 0x100E").unwrap();
|
||||
|
||||
Reference in New Issue
Block a user