xhcid: add more timeouts
This commit is contained in:
@@ -78,7 +78,7 @@ impl<const N: usize> DeviceEnumerator<N> {
|
|||||||
|
|
||||||
//THIS LOCKS THE PORTS. DO NOT LOCK PORTS BEFORE THIS POINT
|
//THIS LOCKS THE PORTS. DO NOT LOCK PORTS BEFORE THIS POINT
|
||||||
info!("Received a device connect on port {}, but it's not enabled. Resetting the port.", port_id);
|
info!("Received a device connect on port {}, but it's not enabled. Resetting the port.", port_id);
|
||||||
self.hci.reset_port(port_id);
|
let _ = self.hci.reset_port(port_id);
|
||||||
|
|
||||||
let mut ports = self.hci.ports.lock().unwrap();
|
let mut ports = self.hci.ports.lock().unwrap();
|
||||||
let port = &mut ports[port_array_index];
|
let port = &mut ports[port_array_index];
|
||||||
|
|||||||
+67
-38
@@ -20,7 +20,7 @@ use syscall::error::{Error, Result, EBADF, EBADMSG, EIO, ENOENT};
|
|||||||
use syscall::{EAGAIN, PAGE_SIZE};
|
use syscall::{EAGAIN, PAGE_SIZE};
|
||||||
|
|
||||||
use chashmap::CHashMap;
|
use chashmap::CHashMap;
|
||||||
use common::{dma::Dma, io::Io};
|
use common::{dma::Dma, io::Io, timeout::Timeout};
|
||||||
use crossbeam_channel::{Receiver, Sender};
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
use log::{debug, error, info, trace, warn};
|
use log::{debug, error, info, trace, warn};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
@@ -374,26 +374,42 @@ impl<const N: usize> Xhci<N> {
|
|||||||
|
|
||||||
//Reset the XHCI device
|
//Reset the XHCI device
|
||||||
let (max_slots, max_ports) = {
|
let (max_slots, max_ports) = {
|
||||||
debug!("Waiting for xHC becoming ready.");
|
{
|
||||||
// Wait until controller is ready
|
debug!("Waiting for xHC becoming ready.");
|
||||||
while op.usb_sts.readf(USB_STS_CNR) {
|
let timeout = Timeout::from_secs(1);
|
||||||
trace!("Waiting for the xHC to be ready.");
|
while op.usb_sts.readf(USB_STS_CNR) {
|
||||||
|
timeout.run().map_err(|()| {
|
||||||
|
log::error!("timeout on USB_STS_CNR");
|
||||||
|
Error::new(EIO)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Stopping the xHC");
|
debug!("Stopping the xHC");
|
||||||
// Set run/stop to 0
|
// Set run/stop to 0
|
||||||
op.usb_cmd.writef(USB_CMD_RS, false);
|
op.usb_cmd.writef(USB_CMD_RS, false);
|
||||||
|
|
||||||
debug!("Waiting for the xHC to stop.");
|
{
|
||||||
// Wait until controller not running
|
debug!("Waiting for the xHC to stop.");
|
||||||
while !op.usb_sts.readf(USB_STS_HCH) {
|
let timeout = Timeout::from_secs(1);
|
||||||
trace!("Waiting for the xHC to stop.");
|
while !op.usb_sts.readf(USB_STS_HCH) {
|
||||||
|
timeout.run().map_err(|()| {
|
||||||
|
log::error!("timeout on USB_STS_HCH");
|
||||||
|
Error::new(EIO)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Resetting the xHC.");
|
{
|
||||||
op.usb_cmd.writef(USB_CMD_HCRST, true);
|
debug!("Resetting the xHC.");
|
||||||
while op.usb_cmd.readf(USB_CMD_HCRST) {
|
op.usb_cmd.writef(USB_CMD_HCRST, true);
|
||||||
trace!("Waiting for the xHC to reset.");
|
let timeout = Timeout::from_secs(1);
|
||||||
|
while op.usb_cmd.readf(USB_CMD_HCRST) {
|
||||||
|
timeout.run().map_err(|()| {
|
||||||
|
log::error!("timeout on USB_CMD_HCRST");
|
||||||
|
Error::new(EIO)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Reading max slots.");
|
debug!("Reading max slots.");
|
||||||
@@ -472,14 +488,20 @@ impl<const N: usize> Xhci<N> {
|
|||||||
self.op.get_mut().unwrap().usb_cmd.writef(USB_CMD_RS, false);
|
self.op.get_mut().unwrap().usb_cmd.writef(USB_CMD_RS, false);
|
||||||
|
|
||||||
// Warm reset
|
// Warm reset
|
||||||
debug!("Reset xHC");
|
{
|
||||||
self.op
|
debug!("Reset xHC");
|
||||||
.get_mut()
|
let timeout = Timeout::from_secs(1);
|
||||||
.unwrap()
|
self.op
|
||||||
.usb_cmd
|
.get_mut()
|
||||||
.writef(USB_CMD_HCRST, true);
|
.unwrap()
|
||||||
while self.op.get_mut().unwrap().usb_cmd.readf(USB_CMD_HCRST) {
|
.usb_cmd
|
||||||
thread::yield_now();
|
.writef(USB_CMD_HCRST, true);
|
||||||
|
while self.op.get_mut().unwrap().usb_cmd.readf(USB_CMD_HCRST) {
|
||||||
|
timeout.run().map_err(|()| {
|
||||||
|
log::error!("timeout on USB_CMD_HCRST");
|
||||||
|
Error::new(EIO)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set enabled slots
|
// Set enabled slots
|
||||||
@@ -552,10 +574,15 @@ impl<const N: usize> Xhci<N> {
|
|||||||
debug!("Starting xHC.");
|
debug!("Starting xHC.");
|
||||||
self.op.get_mut().unwrap().usb_cmd.writef(USB_CMD_RS, true);
|
self.op.get_mut().unwrap().usb_cmd.writef(USB_CMD_RS, true);
|
||||||
|
|
||||||
// Wait until controller is running
|
{
|
||||||
debug!("Waiting for start request to complete.");
|
debug!("Waiting for start request to complete.");
|
||||||
while self.op.get_mut().unwrap().usb_sts.readf(USB_STS_HCH) {
|
let timeout = Timeout::from_secs(1);
|
||||||
trace!("Waiting for XHCI to report running status.");
|
while self.op.get_mut().unwrap().usb_sts.readf(USB_STS_HCH) {
|
||||||
|
timeout.run().map_err(|()| {
|
||||||
|
log::error!("timeout on USB_STS_HCH");
|
||||||
|
Error::new(EIO)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ring command doorbell
|
// Ring command doorbell
|
||||||
@@ -654,7 +681,7 @@ impl<const N: usize> Xhci<N> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn reset_port(&self, port_id: PortId) {
|
pub fn reset_port(&self, port_id: PortId) -> Result<()> {
|
||||||
debug!("XHCI Port {} reset", port_id);
|
debug!("XHCI Port {} reset", port_id);
|
||||||
|
|
||||||
//TODO handle the second unwrap
|
//TODO handle the second unwrap
|
||||||
@@ -664,20 +691,22 @@ impl<const N: usize> Xhci<N> {
|
|||||||
|
|
||||||
debug!("Port {} Link State: {}", port_id, port.state());
|
debug!("Port {} Link State: {}", port_id, port.state());
|
||||||
|
|
||||||
port.set_pr();
|
{
|
||||||
debug!(
|
port.set_pr();
|
||||||
"Flags after setting port {} reset: {:?}",
|
debug!(
|
||||||
port_id,
|
"Flags after setting port {} reset: {:?}",
|
||||||
port.flags()
|
port_id,
|
||||||
);
|
port.flags()
|
||||||
while !port.flags().contains(port::PortFlags::PRC) {
|
);
|
||||||
debug!("port {} reset loop ran at least once!", port_id);
|
let timeout = Timeout::from_secs(1);
|
||||||
if instant.elapsed().as_secs() >= 1 {
|
while !port.flags().contains(port::PortFlags::PRC) {
|
||||||
warn!("timeout");
|
timeout.run().map_err(|()| {
|
||||||
break;
|
log::error!("timeout on port {} PRC", port_id);
|
||||||
|
Error::new(EIO)
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
std::thread::yield_now();
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_scratchpads(&mut self) -> Result<()> {
|
pub fn setup_scratchpads(&mut self) -> Result<()> {
|
||||||
|
|||||||
Reference in New Issue
Block a user