Deduplicate event trb processing between polling and interrupt reactor

This commit is contained in:
bjorn3
2026-07-13 20:19:49 +02:00
parent 1b17b3fc24
commit b2ed85ea0d
+80 -83
View File
@@ -104,6 +104,12 @@ pub struct IrqReactor<const N: usize> {
pub type NewPendingTrb = State;
enum EventProcessResult {
NoEvent,
EventRingFull,
RegularEvent,
}
impl<const N: usize> IrqReactor<N> {
pub fn new(hci: Arc<Xhci<N>>, irq_file: Option<File>) -> Self {
let device_enumerator_sender = hci.device_enumerator_sender.clone();
@@ -139,45 +145,14 @@ impl<const N: usize> IrqReactor<N> {
let mut event_ring = hci_clone.primary_event_ring.lock().unwrap();
let event_trb = &mut event_ring.ring.trbs[event_trb_index];
if event_trb.completion_code() == TrbCompletionCode::Invalid as u8 {
continue 'trb_loop;
}
trace!(
"Found event TRB at index {} with type {} and cycle bit {}: {:?}",
event_trb_index,
event_trb.trb_type(),
event_trb.cycle() as u8,
event_trb
);
if self.check_event_ring_full(event_trb.clone()) {
info!("Had to resize event TRB, retrying...");
continue 'trb_loop;
}
trace!("Handling requests");
self.handle_requests();
trace!("Requests handled");
match event_trb.trb_type() {
_ if event_trb.trb_type() == TrbType::PortStatusChange as u8 => {
trace!("Received a port status change!");
self.handle_port_status_change(event_trb.clone())
} //TODO Handle the other unprompted events
_ => {
self.acknowledge(event_trb.clone());
loop {
match self.process_one_event(&mut event_ring, &mut event_trb_index) {
EventProcessResult::NoEvent | EventProcessResult::EventRingFull => {
continue 'trb_loop
}
EventProcessResult::RegularEvent => {}
}
}
event_trb.reserved(false);
self.update_erdp(&*event_ring);
hci_clone.event_handler_finished();
event_trb_index = event_ring.ring.next_index();
}
}
@@ -258,61 +233,83 @@ impl<const N: usize> IrqReactor<N> {
loop {
trace!("count: {}", count);
let event_trb = &mut event_ring.ring.trbs[event_trb_index];
if event_trb.completion_code() == TrbCompletionCode::Invalid as u8 {
if count == 0 {
warn!("xhci: Received interrupt, but no event was found in the event ring. Ignoring interrupt.")
match self.process_one_event(&mut event_ring, &mut event_trb_index) {
EventProcessResult::NoEvent => {
if count == 0 {
warn!("xhci: Received interrupt, but no event was found in the event ring. Ignoring interrupt.")
}
self.unmask_interrupts();
continue 'trb_loop;
}
//hci_clone.event_handler_finished();
self.unmask_interrupts();
continue 'trb_loop;
} else {
count += 1
}
info!(
"Found event TRB at index {} with type {} and cycle bit {}: {:?}",
event_trb_index,
event_trb.trb_type(),
event_trb.cycle() as u8,
event_trb
);
if self.check_event_ring_full(event_trb.clone()) {
info!("Had to resize event TRB, retrying...");
//hci_clone.event_handler_finished();
if self.hci.interrupt_is_pending(0) {
warn!("After incrementing the dequeue pointer, the interrupt bit is still pending.")
} else {
debug!("The interrupt bit is no longer pending.");
EventProcessResult::EventRingFull => {
if self.hci.interrupt_is_pending(0) {
warn!("After incrementing the dequeue pointer, the interrupt bit is still pending.")
} else {
debug!("The interrupt bit is no longer pending.");
}
self.unmask_interrupts();
continue 'trb_loop;
}
self.unmask_interrupts();
continue 'trb_loop;
}
self.handle_requests();
match event_trb.trb_type() {
_ if event_trb.trb_type() == TrbType::PortStatusChange as u8 => {
trace!("Received a port status change!");
self.handle_port_status_change(event_trb.clone())
} //TODO Handle the other unprompted events
_ => {
trace!("Received a non-status trb");
self.acknowledge(event_trb.clone());
EventProcessResult::RegularEvent => {
count += 1;
}
}
event_trb.reserved(false);
self.update_erdp(&*event_ring);
self.hci.event_handler_finished();
event_trb_index = event_ring.ring.next_index();
}
}
}
fn process_one_event(
&mut self,
event_ring: &mut EventRing,
event_trb_index: &mut usize,
) -> EventProcessResult {
let event_trb = &mut event_ring.ring.trbs[*event_trb_index];
if event_trb.completion_code() == TrbCompletionCode::Invalid as u8 {
//hci_clone.event_handler_finished();
return EventProcessResult::NoEvent;
}
trace!(
"Found event TRB at index {} with type {} and cycle bit {}: {:?}",
event_trb_index,
event_trb.trb_type(),
event_trb.cycle() as u8,
event_trb
);
if self.check_event_ring_full(event_trb.clone()) {
info!("Had to resize event TRB, retrying...");
//hci_clone.event_handler_finished();
return EventProcessResult::EventRingFull;
}
trace!("Handling requests");
self.handle_requests();
trace!("Requests handled");
match event_trb.trb_type() {
_ if event_trb.trb_type() == TrbType::PortStatusChange as u8 => {
trace!("Received a port status change!");
self.handle_port_status_change(event_trb.clone())
} //TODO Handle the other unprompted events
_ => {
trace!("Received a non-status trb");
self.acknowledge(event_trb.clone());
}
}
event_trb.reserved(false);
self.update_erdp(&*event_ring);
self.hci.event_handler_finished();
*event_trb_index = event_ring.ring.next_index();
EventProcessResult::RegularEvent
}
/// Handles device attach/detach events as indicated by a PortStatusChange
fn handle_port_status_change(&mut self, trb: Trb) {
if let Some(root_hub_port_num) = trb.port_status_change_port_id() {