summary refs log tree commit diff
diff options
context:
space:
mode:
authorTomasz Jeznach <tjeznach@chromium.org>2019-08-05 16:01:42 -0700
committerCommit Bot <commit-bot@chromium.org>2019-08-07 14:38:14 +0000
commita1b54ce9b58fa5cbf8f1b0487e35bb3b66b2f283 (patch)
treecfa4064b1c63d5c734d94cfc512513909fea98a0
parent28ea102c0ef601340787cc86d3dc60bed382a763 (diff)
downloadcrosvm-a1b54ce9b58fa5cbf8f1b0487e35bb3b66b2f283.tar
crosvm-a1b54ce9b58fa5cbf8f1b0487e35bb3b66b2f283.tar.gz
crosvm-a1b54ce9b58fa5cbf8f1b0487e35bb3b66b2f283.tar.bz2
crosvm-a1b54ce9b58fa5cbf8f1b0487e35bb3b66b2f283.tar.lz
crosvm-a1b54ce9b58fa5cbf8f1b0487e35bb3b66b2f283.tar.xz
crosvm-a1b54ce9b58fa5cbf8f1b0487e35bb3b66b2f283.tar.zst
crosvm-a1b54ce9b58fa5cbf8f1b0487e35bb3b66b2f283.zip
usb: handle transfer errors after port is detached
When USB device is detached from kernel driver there might be multiple
pending USB transfers enqued, each completing with TransferStatus::NoDevice.
Once backend device is detached from system it's ok to ignore subsequent
detach request errors in transfer completion handler.

BUG=chromium:987500
TEST=ADB USB device attach/detach cycles with active adb service.

Change-Id: I4026e68df860c483973f51f9787bf3d48d2716b3
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1737471
Tested-by: Tomasz Jeznach <tjeznach@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Tomasz Jeznach <tjeznach@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-by: Zach Reizner <zachr@chromium.org>
-rw-r--r--devices/src/usb/xhci/xhci_transfer.rs9
1 files changed, 7 insertions, 2 deletions
diff --git a/devices/src/usb/xhci/xhci_transfer.rs b/devices/src/usb/xhci/xhci_transfer.rs
index e166c1a..400cbbc 100644
--- a/devices/src/usb/xhci/xhci_transfer.rs
+++ b/devices/src/usb/xhci/xhci_transfer.rs
@@ -290,8 +290,13 @@ impl XhciTransfer {
                 usb_debug!("device disconnected, detaching from port");
                 // If the device is gone, we don't need to send transfer completion event, cause we
                 // are going to destroy everything related to this device anyway.
-                self.port.detach().map_err(Error::DetachPort)?;
-                return Ok(());
+                return match self.port.detach() {
+                    Ok(v) => Ok(v),
+                    // It's acceptable for the port to be already disconnected
+                    // as asynchronous transfer completions are processed.
+                    Err(HubError::AlreadyDetached(_e)) => Ok(()),
+                    Err(e) => Err(Error::DetachPort(e)),
+                };
             }
             TransferStatus::Cancelled => {
                 // TODO(jkwang) According to the spec, we should send a stopped event here. But