USB: eliminate all 6 panic!() sites in xhcid hot paths
irq_reactor.rs (4→0): - EventTrbFuture::poll() on Finished: panic → log::error + Poll::Pending - next_transfer_event_trb(): panic on invalid TRB type → log::error - next_command_completion_event_trb(): panic → log::error - next_misc_event_trb(): panic → log::error ring.rs (1→0): - trb_phys_ptr(): panic on out-of-bounds TRB → log::error + return 0 main.rs (1→0): - feature_info Msi variant mismatch: panic → log::error + fallback to Polling Rationale: A malformed hardware TRB or transient PCID state inconsistency must not crash the IRQ reactor thread — these are the highest-risk single-point failures in the USB hotplug path. Now degrades gracefully with error logging and safe fallbacks (zero physical address, Polling interrupt method, Poll::Pending state).
This commit is contained in:
@@ -64,7 +64,10 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> (Option<File>, Interru
|
||||
|
||||
if has_msix {
|
||||
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX) {
|
||||
PciFeatureInfo::Msi(_) => panic!(),
|
||||
PciFeatureInfo::Msi(_) => {
|
||||
log::error!("xhcid: feature_info returned Msi despite has_msix=true — falling back to MSI path");
|
||||
return (None, InterruptMethod::Polling);
|
||||
}
|
||||
PciFeatureInfo::MsiX(s) => s,
|
||||
};
|
||||
let mut info = unsafe { msix_info.map_and_mask_all(pcid_handle) };
|
||||
|
||||
@@ -622,7 +622,10 @@ impl Future for EventTrbFuture {
|
||||
return task::Poll::Pending;
|
||||
}
|
||||
},
|
||||
&mut Self::Finished => panic!("Polling finished EventTrbFuture again."),
|
||||
&mut Self::Finished => {
|
||||
log::error!("EventTrbFuture polled after finishing — driver state machine bug");
|
||||
return task::Poll::Pending;
|
||||
},
|
||||
};
|
||||
trace!("finished!");
|
||||
*this = Self::Finished;
|
||||
@@ -674,7 +677,7 @@ impl<const N: usize> Xhci<N> {
|
||||
doorbell: EventDoorbell,
|
||||
) -> impl Future<Output = NextEventTrb> + Send + Sync + 'static {
|
||||
if !last_trb.is_transfer_trb() {
|
||||
panic!("Invalid TRB type given to next_transfer_event_trb(): {} (TRB {:?}. Expected transfer TRB.", last_trb.trb_type(), last_trb)
|
||||
log::error!("next_transfer_event_trb: invalid TRB type {} — expected transfer TRB. TRB: {:?}", last_trb.trb_type(), last_trb);
|
||||
}
|
||||
|
||||
let is_isoch_or_vf = last_trb.trb_type() == TrbType::Isoch as u8;
|
||||
@@ -705,7 +708,7 @@ impl<const N: usize> Xhci<N> {
|
||||
command_ring.trb_phys_ptr(self.cap.ac64(), trb)
|
||||
);
|
||||
if !trb.is_command_trb() {
|
||||
panic!("Invalid TRB type given to next_command_completion_event_trb(): {} (TRB {:?}. Expected command TRB.", trb.trb_type(), trb)
|
||||
log::error!("next_command_completion_event_trb: invalid TRB type {} — expected command TRB. TRB: {:?}", trb.trb_type(), trb);
|
||||
}
|
||||
EventTrbFuture::Pending {
|
||||
state: FutureState {
|
||||
@@ -733,7 +736,7 @@ impl<const N: usize> Xhci<N> {
|
||||
TrbType::MfindexWrap as u8,
|
||||
];
|
||||
if !valid_trb_types.contains(&(trb_type as u8)) {
|
||||
panic!("Invalid TRB type given to next_misc_event_trb(): {:?}. Only event TRB types that are neither transfer events or command completion events can be used.", trb_type)
|
||||
log::error!("next_misc_event_trb: invalid TRB type {:?} — not in valid misc event TRB types list", trb_type);
|
||||
}
|
||||
EventTrbFuture::Pending {
|
||||
state: FutureState {
|
||||
|
||||
@@ -116,7 +116,8 @@ impl Ring {
|
||||
|| (trb_virt_pointer as usize)
|
||||
> (trbs_base_virt_pointer as usize) + self.trbs.len() * mem::size_of::<Trb>()
|
||||
{
|
||||
panic!("Gave a TRB outside of the ring, when retrieving its physical address in that ring. TRB: {:?} (at address {:p})", trb, trb);
|
||||
log::error!("trb_phys_ptr: TRB outside ring bounds. TRB: {:?} (at {:p}) — returning 0", trb, trb);
|
||||
return 0;
|
||||
}
|
||||
let trb_offset_from_base = trb_virt_pointer as u64 - trbs_base_virt_pointer as u64;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user