xhci: workaround packet size and protocol speed issues on real hardware

This commit is contained in:
Jeremy Soller
2023-02-16 15:57:28 -07:00
parent afb12dc98b
commit 79a9f447d2
2 changed files with 32 additions and 13 deletions
+15 -9
View File
@@ -604,12 +604,14 @@ impl Xhci {
b |= (new_max_packet_size) << 16;
endp_ctx.b.write(b);
/*TODO: this causes issues on real hardware, maybe it should only be used on USB 2?
let (event_trb, command_trb) = self.execute_command(|trb, cycle| {
trb.evaluate_context(slot_id, input_context.physical(), false, cycle)
}).await;
self::scheme::handle_event_trb("EVALUATE_CONTEXT", &event_trb, &command_trb)?;
self.event_handler_finished();
*/
Ok(())
}
@@ -838,7 +840,7 @@ impl Xhci {
pub fn supported_protocol_speeds(
&self,
port: u8,
) -> Option<impl Iterator<Item = &'static ProtocolSpeed>> {
) -> impl Iterator<Item = &'static ProtocolSpeed> {
use extended::*;
const DEFAULT_SUPP_PROTO_SPEEDS: [ProtocolSpeed; 7] = [
// Full-speed
@@ -903,16 +905,20 @@ impl Xhci {
),
];
let supp_proto = self.supported_protocol(port)?;
Some(if supp_proto.psic() != 0 {
unsafe { supp_proto.protocol_speeds().iter() }
} else {
DEFAULT_SUPP_PROTO_SPEEDS.iter()
})
match self.supported_protocol(port) {
Some(supp_proto) => if supp_proto.psic() != 0 {
unsafe { supp_proto.protocol_speeds().iter() }
} else {
DEFAULT_SUPP_PROTO_SPEEDS.iter()
},
None => {
log::warn!("falling back to default supported protocol speeds for port {}", port);
DEFAULT_SUPP_PROTO_SPEEDS.iter()
}
}
}
pub fn lookup_psiv(&self, port: u8, psiv: u8) -> Option<&'static ProtocolSpeed> {
self.supported_protocol_speeds(port)?
self.supported_protocol_speeds(port)
.find(|speed| speed.psiv() == psiv)
}
}
+17 -4
View File
@@ -626,6 +626,7 @@ impl Xhci {
let endpoints = &config_desc.interface_descs.get(usize::from(req.interface_desc.unwrap_or(0))).ok_or(Error::new(EBADFD))?.endpoints;
if endpoints.len() >= 31 {
warn!("endpoints length {} >= 31", endpoints.len());
return Err(Error::new(EIO));
}
@@ -644,7 +645,10 @@ impl Xhci {
let port_speed_id = self.ports.lock().unwrap()[port].speed();
let speed_id: &ProtocolSpeed = self
.lookup_psiv(port as u8, port_speed_id)
.ok_or(Error::new(EIO))?;
.ok_or_else(|| {
warn!("no speed_id");
Error::new(EIO)
})?;
{
let port_state = self.port_states.get(&port).ok_or(Error::new(EBADFD))?;
@@ -677,7 +681,10 @@ impl Xhci {
let mut port_state = self.port_states.get_mut(&port).ok_or(Error::new(EBADFD))?;
let dev_desc = port_state.dev_desc.as_ref().unwrap();
let endpoints = &dev_desc.config_descs.get(usize::from(req.config_desc)).ok_or(Error::new(EBADFD))?.interface_descs.get(usize::from(req.interface_desc.unwrap_or(0))).ok_or(Error::new(EBADFD))?.endpoints;
let endp_desc = endpoints.get(endp_idx as usize).ok_or(Error::new(EIO))?;
let endp_desc = endpoints.get(endp_idx as usize).ok_or_else(|| {
warn!("failed to find endpoint {}", endp_idx);
Error::new(EIO)
})?;
let endp_num_xhc = Self::endp_num_to_dci(endp_num, endp_desc);
@@ -724,7 +731,10 @@ impl Xhci {
// driver probably knows better. The spec says that the initial value should be 8 bytes
// for control, 1KiB for interrupt and 3KiB for bulk and isoch.
let avg_trb_len: u16 = match endp_desc.ty() {
EndpointTy::Ctrl => return Err(Error::new(EIO)), // only endpoint zero is of type control, and is configured separately with the address device command.
EndpointTy::Ctrl => {
warn!("trying to use control endpoint");
return Err(Error::new(EIO)); // only endpoint zero is of type control, and is configured separately with the address device command.
}
EndpointTy::Bulk | EndpointTy::Isoch => 3072, // 3 KiB
EndpointTy::Interrupt => 1024, // 1 KiB
};
@@ -778,7 +788,10 @@ impl Xhci {
let mut input_context = port_state.input_context.lock().unwrap();
input_context.add_context.writef(1 << endp_num_xhc, true);
let endp_ctx = input_context.device.endpoints.get_mut(endp_num_xhc as usize - 1).ok_or(Error::new(EIO))?;
let endp_ctx = input_context.device.endpoints.get_mut(endp_num_xhc as usize - 1).ok_or_else(|| {
warn!("failed to find endpoint {}", endp_num_xhc - 1);
Error::new(EIO)
})?;
endp_ctx.a.write(
u32::from(mult) << 8