summary refs log tree commit diff
diff options
context:
space:
mode:
authorDaniel Verkamp <dverkamp@chromium.org>2019-05-01 17:45:00 -0700
committerchrome-bot <chrome-bot@chromium.org>2019-05-10 15:26:02 -0700
commit21accb31ac9056ab28930689ddd9dce185956258 (patch)
treea90d48795a6491d643552cb2079c4771fcceda13
parent9fb20d9c53b426d74a251f585a37183fe1137031 (diff)
downloadcrosvm-21accb31ac9056ab28930689ddd9dce185956258.tar
crosvm-21accb31ac9056ab28930689ddd9dce185956258.tar.gz
crosvm-21accb31ac9056ab28930689ddd9dce185956258.tar.bz2
crosvm-21accb31ac9056ab28930689ddd9dce185956258.tar.lz
crosvm-21accb31ac9056ab28930689ddd9dce185956258.tar.xz
crosvm-21accb31ac9056ab28930689ddd9dce185956258.tar.zst
crosvm-21accb31ac9056ab28930689ddd9dce185956258.zip
usb: execute control requests in DataStage
If a control request has a DataStage, execute the request during the
data stage so that we can get the actual length of the transferred data.
This will allow the ISP (Interrupt on Short Packets) bit to be
implemented correctly; we need to know the actual length during
processing of the DataStage TRB rather than at the StatusStage as we did
previously. (Note that ISP isn't implemented yet in this change; this
just passes the correct length to xhci_transfer.on_transfer_complete,
which doesn't do anything useful with the length yet in the short
transfer case.)

BUG=chromium:831850
TEST=Test adb on Crostini

Change-Id: I340424269aa139b0d9698f44ce9d3a457f3eb899
Signed-off-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1593715
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Zach Reizner <zachr@chromium.org>
-rw-r--r--devices/src/usb/host_backend/host_device.rs25
1 files changed, 17 insertions, 8 deletions
diff --git a/devices/src/usb/host_backend/host_device.rs b/devices/src/usb/host_backend/host_device.rs
index 3213994..61a7c7a 100644
--- a/devices/src/usb/host_backend/host_device.rs
+++ b/devices/src/usb/host_backend/host_device.rs
@@ -49,7 +49,7 @@ pub struct HostDevice {
     alt_settings: HashMap<u16, u16>,
     claimed_interfaces: Vec<i32>,
     control_request_setup: UsbRequestSetup,
-    buffer: Option<ScatterGatherBuffer>,
+    executed: bool,
     job_queue: Arc<AsyncJobQueue>,
 }
 
@@ -76,7 +76,7 @@ impl HostDevice {
             alt_settings: HashMap::new(),
             claimed_interfaces: vec![],
             control_request_setup: UsbRequestSetup::new(0, 0, 0, 0, 0),
-            buffer: None,
+            executed: false,
             job_queue,
         }
     }
@@ -272,10 +272,10 @@ impl HostDevice {
                     error!("Control endpoint is in an inconsistant state");
                     return Ok(());
                 }
-                self.buffer = Some(buffer);
-                xhci_transfer
-                    .on_transfer_complete(&TransferStatus::Completed, 0)
-                    .map_err(Error::TransferComplete)?;
+                // Requests with a DataStage will be executed here.
+                // Requests without a DataStage will be executed in StatusStage.
+                self.execute_control_transfer(xhci_transfer, Some(buffer))?;
+                self.executed = true;
                 self.ctl_ep_state = ControlEndpointState::StatusStage;
             }
             XhciTransferType::StatusStage => {
@@ -283,8 +283,17 @@ impl HostDevice {
                     error!("Control endpoint is in an inconsistant state");
                     return Ok(());
                 }
-                let buffer = self.buffer.take();
-                self.execute_control_transfer(xhci_transfer, buffer)?;
+                if self.executed {
+                    // Request was already executed during DataStage.
+                    // Just complete the StatusStage transfer.
+                    xhci_transfer
+                        .on_transfer_complete(&TransferStatus::Completed, 0)
+                        .map_err(Error::TransferComplete)?;
+                } else {
+                    // Execute the request now since there was no DataStage.
+                    self.execute_control_transfer(xhci_transfer, None)?;
+                }
+                self.executed = false;
                 self.ctl_ep_state = ControlEndpointState::SetupStage;
             }
             _ => {