Deduplicate event trb processing between polling and interrupt reactor
This commit is contained in:
@@ -104,6 +104,12 @@ pub struct IrqReactor<const N: usize> {
|
|||||||
|
|
||||||
pub type NewPendingTrb = State;
|
pub type NewPendingTrb = State;
|
||||||
|
|
||||||
|
enum EventProcessResult {
|
||||||
|
NoEvent,
|
||||||
|
EventRingFull,
|
||||||
|
RegularEvent,
|
||||||
|
}
|
||||||
|
|
||||||
impl<const N: usize> IrqReactor<N> {
|
impl<const N: usize> IrqReactor<N> {
|
||||||
pub fn new(hci: Arc<Xhci<N>>, irq_file: Option<File>) -> Self {
|
pub fn new(hci: Arc<Xhci<N>>, irq_file: Option<File>) -> Self {
|
||||||
let device_enumerator_sender = hci.device_enumerator_sender.clone();
|
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 mut event_ring = hci_clone.primary_event_ring.lock().unwrap();
|
||||||
|
|
||||||
let event_trb = &mut event_ring.ring.trbs[event_trb_index];
|
loop {
|
||||||
|
match self.process_one_event(&mut event_ring, &mut event_trb_index) {
|
||||||
if event_trb.completion_code() == TrbCompletionCode::Invalid as u8 {
|
EventProcessResult::NoEvent | EventProcessResult::EventRingFull => {
|
||||||
continue 'trb_loop;
|
continue 'trb_loop
|
||||||
}
|
}
|
||||||
|
EventProcessResult::RegularEvent => {}
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
loop {
|
||||||
trace!("count: {}", count);
|
trace!("count: {}", count);
|
||||||
let event_trb = &mut event_ring.ring.trbs[event_trb_index];
|
|
||||||
|
|
||||||
if event_trb.completion_code() == TrbCompletionCode::Invalid as u8 {
|
match self.process_one_event(&mut event_ring, &mut event_trb_index) {
|
||||||
if count == 0 {
|
EventProcessResult::NoEvent => {
|
||||||
warn!("xhci: Received interrupt, but no event was found in the event ring. Ignoring interrupt.")
|
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();
|
EventProcessResult::EventRingFull => {
|
||||||
self.unmask_interrupts();
|
if self.hci.interrupt_is_pending(0) {
|
||||||
continue 'trb_loop;
|
warn!("After incrementing the dequeue pointer, the interrupt bit is still pending.")
|
||||||
} else {
|
} else {
|
||||||
count += 1
|
debug!("The interrupt bit is no longer pending.");
|
||||||
}
|
}
|
||||||
|
self.unmask_interrupts();
|
||||||
info!(
|
continue 'trb_loop;
|
||||||
"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.");
|
|
||||||
}
|
}
|
||||||
self.unmask_interrupts();
|
EventProcessResult::RegularEvent => {
|
||||||
continue 'trb_loop;
|
count += 1;
|
||||||
}
|
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
/// Handles device attach/detach events as indicated by a PortStatusChange
|
||||||
fn handle_port_status_change(&mut self, trb: Trb) {
|
fn handle_port_status_change(&mut self, trb: Trb) {
|
||||||
if let Some(root_hub_port_num) = trb.port_status_change_port_id() {
|
if let Some(root_hub_port_num) = trb.port_status_change_port_id() {
|
||||||
|
|||||||
Reference in New Issue
Block a user