xhcid: remove transfer states on dead rings

This commit is contained in:
Jeremy Soller
2024-11-11 14:27:32 -07:00
parent 842fc73a34
commit 5cf8bfda72
4 changed files with 39 additions and 41 deletions
+2 -18
View File
@@ -63,10 +63,6 @@ pub mod driver_interface;
mod usb;
mod xhci;
async fn handle_packet(hci: Arc<Xhci>, packet: Packet) -> Packet {
todo!()
}
#[cfg(target_arch = "x86_64")]
fn get_int_method(
pcid_handle: &mut PciFunctionHandle,
@@ -224,7 +220,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let socket_fd =
libredox::call::open(format!(":{}", scheme_name), flag::O_RDWR | flag::O_CREAT, 0)
.expect("xhcid: failed to create usb scheme");
let socket = Arc::new(Mutex::new(unsafe { File::from_raw_fd(socket_fd as RawFd) }));
let mut socket = unsafe { File::from_raw_fd(socket_fd as RawFd) };
daemon.ready().expect("xhcid: failed to notify parent");
@@ -238,20 +234,8 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
hci.poll();
//let event_queue = RawEventQueue::new().expect("xhcid: failed to create event queue");
let todo = Arc::new(Mutex::new(Vec::<Packet>::new()));
//let todo_futures = Arc::new(Mutex::new(Vec::<Pin<Box<dyn Future<Output = usize> + Send + Sync + 'static>>>::new()));
//let socket_fd = socket.lock().unwrap().as_raw_fd();
//event_queue.subscribe(socket_fd as usize, 0, event::EventFlags::READ).unwrap();
let socket_packet = socket.clone();
let mut todo = Vec::<Packet>::new();
loop {
let mut socket = socket_packet.lock().unwrap();
let mut todo = todo.lock().unwrap();
let mut packet = Packet::default();
match socket.read(&mut packet) {
Ok(0) => break,
+32 -19
View File
@@ -34,6 +34,14 @@ pub struct State {
is_isoch_or_vf: bool,
}
impl State {
fn finish(self, message: Option<NextEventTrb>) {
*self.message.lock().unwrap() = message;
trace!("Waking up future with waker: {:?}", self.waker);
self.waker.wake();
}
}
#[derive(Debug)]
pub struct NextEventTrb {
pub event_trb: Trb,
@@ -401,13 +409,10 @@ impl IrqReactor {
};
// TODO: Validate the command TRB.
*state.message.lock().unwrap() = Some(NextEventTrb {
state.finish(Some(NextEventTrb {
src_trb: Some(command_trb.clone()),
event_trb: trb.clone(),
});
trace!("Waking up future with waker: {:?}", state.waker);
state.waker.wake();
}));
return;
} else if trb.completion_trb_pointer().is_none() {
@@ -419,12 +424,9 @@ impl IrqReactor {
first_phys_ptr,
last_phys_ptr,
ring_id,
} if trb.trb_type() == TrbType::Transfer as u8 => {
if let Some(src_trb) = trb
.transfer_event_trb_pointer()
.map(|ptr| self.hci.get_transfer_trb(ptr, ring_id))
.flatten()
{
} => {
// Check if the TRB matches the transfer
if trb.trb_type() == TrbType::Transfer as u8 {
match trb.transfer_event_trb_pointer() {
Some(phys_ptr) => {
let matches = if first_phys_ptr <= last_phys_ptr {
@@ -434,13 +436,13 @@ impl IrqReactor {
phys_ptr >= first_phys_ptr || phys_ptr <= last_phys_ptr
};
if matches {
let src_trb = self.hci.get_transfer_trb(phys_ptr, ring_id);
// Give the source transfer TRB together with the event TRB, to the future.
let state = self.states.remove(index);
*state.message.lock().unwrap() = Some(NextEventTrb {
src_trb: Some(src_trb),
state.finish(Some(NextEventTrb {
src_trb: src_trb,
event_trb: trb.clone(),
});
state.waker.wake();
}));
return;
}
}
@@ -461,11 +463,23 @@ impl IrqReactor {
}
}
}
// Also check if the transfer is on a dead ring
if self.hci.with_ring(ring_id, |_ring| ()).is_none() {
log::debug!("State {} is a dead transfer", index);
let state = self.states.remove(index);
state.finish(Some(NextEventTrb {
src_trb: None,
//TODO: don't send this TRB as it may not be related
event_trb: trb.clone(),
}));
continue;
}
}
StateKind::Other(trb_type) if trb_type as u8 == trb.trb_type() => {
let state = self.states.remove(index);
state.waker.wake();
state.finish(None);
return;
}
@@ -493,11 +507,10 @@ impl IrqReactor {
continue;
}
let state = self.states.remove(index);
*state.message.lock().unwrap() = Some(NextEventTrb {
state.finish(Some(NextEventTrb {
event_trb: trb.clone(),
src_trb: None,
});
state.waker.wake();
}));
}
}
/// Checks if an event TRB is a Host Controller Event, with the completion code Event Ring
+2 -1
View File
@@ -162,7 +162,7 @@ impl Xhci {
debug!("Waiting for the next transfer event TRB...");
let trbs = future.await;
let event_trb = trbs.event_trb;
let status_trb = trbs.src_trb.unwrap();
let status_trb = trbs.src_trb.ok_or(Error::new(EIO))?;
trace!("Handling the transfer event TRB!");
self::scheme::handle_transfer_event_trb("GET_DESC", &event_trb, &status_trb)?;
@@ -698,6 +698,7 @@ impl Xhci {
Ok(event_trb.event_slot())
}
pub async fn disable_port_slot(&self, slot: u8) -> Result<()> {
trace!("Disable slot {}", slot);
let (event_trb, command_trb) = self
.execute_command(|cmd, cycle| cmd.disable_slot(slot, cycle))
.await;
+3 -3
View File
@@ -651,7 +651,7 @@ impl Xhci {
let trbs = future.await;
let event_trb = trbs.event_trb;
let status_trb = trbs.src_trb.unwrap();
let status_trb = trbs.src_trb.ok_or(Error::new(EIO))?;
handle_transfer_event_trb("CONTROL_TRANSFER", &event_trb, &status_trb)?;
@@ -748,7 +748,7 @@ impl Xhci {
let trbs = future.await;
let event_trb = trbs.event_trb;
let transfer_trb = trbs.src_trb.unwrap();
let transfer_trb = trbs.src_trb.ok_or(Error::new(EIO))?;
handle_transfer_event_trb("EXECUTE_TRANSFER", &event_trb, &transfer_trb)?;
@@ -1136,7 +1136,7 @@ impl Xhci {
.c
.write(u32::from(avg_trb_len) | (u32::from(max_esit_payload_lo) << 16));
log::info!("INITIALIZED ENDPOINT {}", endp_num);
log::info!("initialized endpoint {}", endp_num);
}
{