From fbe00d57f916b6b8c4f1771b91bc359e5250369f Mon Sep 17 00:00:00 2001 From: Liam Murphy Date: Fri, 15 Jul 2022 16:23:27 +1000 Subject: [PATCH] Fix USB deadlock handling pending packets (#513) --- patches/tock/12-pending-deadlock.patch | 79 ++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 patches/tock/12-pending-deadlock.patch diff --git a/patches/tock/12-pending-deadlock.patch b/patches/tock/12-pending-deadlock.patch new file mode 100644 index 0000000..dbdee3f --- /dev/null +++ b/patches/tock/12-pending-deadlock.patch @@ -0,0 +1,79 @@ +diff --git a/capsules/src/usb/usbc_ctap_hid.rs b/capsules/src/usb/usbc_ctap_hid.rs +index 16b80cb10..c71ed639a 100644 +--- a/capsules/src/usb/usbc_ctap_hid.rs ++++ b/capsules/src/usb/usbc_ctap_hid.rs +@@ -120,7 +120,6 @@ struct EndpointState { + + tx_packet: OptionalCell<[u8; 64]>, + pending_in: Cell, +- pending_out: Cell, + // Is there a delayed packet? + delayed_out: Cell, + } +@@ -133,7 +132,6 @@ impl EndpointState { + out_buffer: Buffer64::default(), + tx_packet: OptionalCell::empty(), + pending_in: Cell::new(false), +- pending_out: Cell::new(false), + delayed_out: Cell::new(false), + } + } +@@ -142,6 +140,9 @@ impl EndpointState { + pub struct ClientCtapHID<'a, 'b, C: 'a> { + client_ctrl: ClientCtrl<'a, 'static, C>, + ++ // Is there a pending OUT transaction happening? ++ pending_out: Cell, ++ + endpoints: [EndpointState; NUM_ENDPOINTS], + + // Interaction with the client +@@ -264,6 +265,7 @@ impl<'a, 'b, C: hil::usb::UsbController<'a>> ClientCtapHID<'a, 'b, C> { + LANGUAGES, + strings, + ), ++ pending_out: Cell::new(false), + endpoints: [ + EndpointState::new(ENDPOINT_NUM), + #[cfg(feature = "vendor_hid")] +@@ -306,12 +308,14 @@ impl<'a, 'b, C: hil::usb::UsbController<'a>> ClientCtapHID<'a, 'b, C> { + } + + pub fn receive_packet(&'a self, app: &mut App) { +- for (_, s) in self.endpoints.iter().enumerate() { +- if s.pending_out.get() { +- // The previous packet has not yet been received, reject the new one. +- continue; +- } else { +- s.pending_out.set(true); ++ if self.pending_out.get() { ++ // The previous packet has not yet been received, reject the new one. ++ } else { ++ self.pending_out.set(true); ++ // Process the first endpoint that has a delayed packet. ++ // TODO(liamjm): Determine if a round-robin approach reduces latency ++ // in the worst case. ++ for (_, s) in self.endpoints.iter().enumerate() { + // In case we reported Delay before, send the pending packet back to the client. + // Otherwise, there's nothing to do, the controller will send us a packet_out when a + // packet arrives. +@@ -344,7 +348,7 @@ impl<'a, 'b, C: hil::usb::UsbController<'a>> ClientCtapHID<'a, 'b, C> { + .client + .map_or(false, |client| client.can_receive_packet(&app)) + { +- assert!(s.pending_out.take()); ++ assert!(self.pending_out.take()); + + // Clear any pending packet on the transmitting side. + // It's up to the client to handle the received packet and decide if this packet +@@ -387,8 +391,8 @@ impl<'a, 'b, C: hil::usb::UsbController<'a>> ClientCtapHID<'a, 'b, C> { + } + + fn cancel_out_transaction(&'a self, endpoint: usize) -> bool { +- if let Some(s) = self.get_endpoint(endpoint) { +- s.pending_out.take() ++ if let Some(_) = self.get_endpoint(endpoint) { ++ self.pending_out.take() + } else { + // Unsupported endpoint + false