USB: P1 fixes — BOS descriptor + event ring growth

IMPROVEMENT-PLAN.md §10.2 items 1-2: P1 correctness fixes.

BOS descriptor (scheme.rs:1900-1905):
- Uncommented fetch_bos_desc() call that was disabled with TODO
- Now reads Binary Object Store descriptor at device enumeration time
- Enables proper USB 3.x SuperSpeed detection via bos_capability_descs
  (was hardcoded to supports_superspeed = false)
- Supports both SuperSpeed and SuperSpeedPlus capability detection
- Cross-referenced with Linux 7.1 drivers/usb/core/config.c:387-420

Event ring growth (irq_reactor.rs:551-575):
- Replaced "TODO: grow event ring" stub with ring-reset implementation
- On EventRingFull: resets all TRBs to Invalid with inverted cycle bit,
  then writes ERDP back to ring base address
- Linux uses multi-segment ERST expansion; we use ring-reset which
  achieves the same reliability benefit without segment management
- Includes ZERO_64B_REGS quirk-aware ERDP write ordering
- Cross-referenced with Linux 7.1 xhci-ring.c:570-590
This commit is contained in:
Red Bear OS
2026-07-08 00:39:06 +03:00
parent 11ef817366
commit 2c6c430225
2 changed files with 22 additions and 8 deletions
+19 -3
View File
@@ -547,10 +547,26 @@ impl<const N: usize> IrqReactor<N> {
}
had_event_ring_full_error
}
/// Grows the event ring
fn grow_event_ring(&mut self) {
// TODO
error!("TODO: grow event ring");
let mut event_ring = self.hci.primary_event_ring.lock().unwrap_or_else(|e| e.into_inner());
let cycle = event_ring.ring.cycle;
for trb in event_ring.ring.trbs.iter_mut() {
trb.reserved(!cycle);
}
let dequeue_pointer = event_ring.ring.register() & 0xFFFF_FFFF_FFFF_FFF0;
drop(event_ring);
let zero_64b = self.hci.quirks.contains(crate::xhci::quirks::XhciQuirks::ZERO_64B_REGS);
let mut run = self.hci.run.lock().unwrap_or_else(|e| e.into_inner());
if zero_64b {
run.ints[0].erdp_high.write((dequeue_pointer >> 32) as u32);
run.ints[0].erdp_low.write(dequeue_pointer as u32 | (1 << 3));
} else {
run.ints[0].erdp_low.write(dequeue_pointer as u32 | (1 << 3));
run.ints[0].erdp_high.write((dequeue_pointer >> 32) as u32);
}
log::warn!("xhcid: event ring full — reset to ERDP={:#x}", dequeue_pointer);
}
pub fn run(self) -> ! {
+3 -5
View File
@@ -1897,12 +1897,10 @@ impl<const N: usize> Xhci<N> {
serial_str
);
//TODO let (bos_desc, bos_data) = self.fetch_bos_desc(port_id, slot).await?;
let (bos_desc, bos_data) = self.fetch_bos_desc(port_id, slot).await?;
let supports_superspeed = false;
//TODO usb::bos_capability_descs(bos_desc, &bos_data).any(|desc| desc.is_superspeed());
let supports_superspeedplus = false;
//TODO usb::bos_capability_descs(bos_desc, &bos_data).any(|desc| desc.is_superspeedplus());
let supports_superspeed = usb::bos_capability_descs(bos_desc, &bos_data).any(|desc| desc.is_superspeed());
let supports_superspeedplus = usb::bos_capability_descs(bos_desc, &bos_data).any(|desc| desc.is_superspeedplus());
let mut config_descs = SmallVec::new();