diff options
author | Daniel Verkamp <dverkamp@chromium.org> | 2019-05-01 17:45:00 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-05-10 15:26:02 -0700 |
commit | 21accb31ac9056ab28930689ddd9dce185956258 (patch) | |
tree | a90d48795a6491d643552cb2079c4771fcceda13 | |
parent | 9fb20d9c53b426d74a251f585a37183fe1137031 (diff) | |
download | crosvm-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.rs | 25 |
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; } _ => { |