diff options
author | Daniel Verkamp <dverkamp@chromium.org> | 2020-05-13 14:03:48 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-05-27 06:03:49 +0000 |
commit | 247134fe68f32f45f7a92a7f3181c0a74f713dec (patch) | |
tree | 385eb74095d7282ece8c32471c2bdd1a702d4665 | |
parent | 1cc1d5e6eea56c24261380fee6549b4958735d9d (diff) | |
download | crosvm-247134fe68f32f45f7a92a7f3181c0a74f713dec.tar crosvm-247134fe68f32f45f7a92a7f3181c0a74f713dec.tar.gz crosvm-247134fe68f32f45f7a92a7f3181c0a74f713dec.tar.bz2 crosvm-247134fe68f32f45f7a92a7f3181c0a74f713dec.tar.lz crosvm-247134fe68f32f45f7a92a7f3181c0a74f713dec.tar.xz crosvm-247134fe68f32f45f7a92a7f3181c0a74f713dec.tar.zst crosvm-247134fe68f32f45f7a92a7f3181c0a74f713dec.zip |
devices: usb: add unit test for ring buffer cycle
Validate that the toggle_cycle code works as expected. I initially misunderstood the behavior of toggle_cycle in the Link TRB, but it appears to work correctly as written after writing a unit test to verify my understanding. Add the unit test anyway to be sure the behavior doesn't regress in the future. BUG=None TEST=cargo test -p devices Change-Id: I9dbc34b26225945fa6d31c34261f53d5b64ba259 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2199956 Reviewed-by: Zach Reizner <zachr@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
-rw-r--r-- | devices/src/usb/xhci/ring_buffer.rs | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/devices/src/usb/xhci/ring_buffer.rs b/devices/src/usb/xhci/ring_buffer.rs index 3033b0e..91806c6 100644 --- a/devices/src/usb/xhci/ring_buffer.rs +++ b/devices/src/usb/xhci/ring_buffer.rs @@ -264,4 +264,89 @@ mod test { let descriptor = transfer_ring.dequeue_transfer_descriptor().unwrap(); assert_eq!(descriptor.is_none(), true); } + + #[test] + fn ring_test_toggle_cycle() { + let trb_size = size_of::<Trb>() as u64; + let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x1000)]).unwrap(); + let mut transfer_ring = RingBuffer::new(String::new(), gm.clone()); + + let mut trb = NormalTrb::new(); + trb.set_trb_type(TrbType::Normal); + trb.set_data_buffer(1); + trb.set_chain(false); + trb.set_cycle(false); + gm.write_obj_at_addr(trb.clone(), GuestAddress(0x100)) + .unwrap(); + + let mut ltrb = LinkTrb::new(); + ltrb.set_trb_type(TrbType::Link); + ltrb.set_ring_segment_pointer(0x100); + ltrb.set_toggle_cycle(true); + ltrb.set_cycle(false); + gm.write_obj_at_addr(ltrb, GuestAddress(0x100 + trb_size)) + .unwrap(); + + // Initial state: consumer cycle = false + transfer_ring.set_dequeue_pointer(GuestAddress(0x100)); + transfer_ring.set_consumer_cycle_state(false); + + // Read first transfer descriptor. + let descriptor = transfer_ring + .dequeue_transfer_descriptor() + .unwrap() + .unwrap(); + assert_eq!(descriptor.len(), 1); + assert_eq!(descriptor[0].trb.get_parameter(), 1); + + // Cycle bit should be unchanged since we haven't advanced past the Link TRB yet. + assert_eq!(transfer_ring.consumer_cycle_state, false); + + // Overwrite the first TRB with a new one (data = 2) + // with the new producer cycle bit state (true). + let mut trb = NormalTrb::new(); + trb.set_trb_type(TrbType::Normal); + trb.set_data_buffer(2); + trb.set_cycle(true); // Link TRB toggled the cycle. + gm.write_obj_at_addr(trb.clone(), GuestAddress(0x100)) + .unwrap(); + + // Read new transfer descriptor. + let descriptor = transfer_ring + .dequeue_transfer_descriptor() + .unwrap() + .unwrap(); + assert_eq!(descriptor.len(), 1); + assert_eq!(descriptor[0].trb.get_parameter(), 2); + + assert_eq!(transfer_ring.consumer_cycle_state, true); + + // Update the Link TRB with the new cycle bit. + let mut ltrb = LinkTrb::new(); + ltrb.set_trb_type(TrbType::Link); + ltrb.set_ring_segment_pointer(0x100); + ltrb.set_toggle_cycle(true); + ltrb.set_cycle(true); // Producer cycle state is now 1. + gm.write_obj_at_addr(ltrb, GuestAddress(0x100 + trb_size)) + .unwrap(); + + // Overwrite the first TRB again with a new one (data = 3) + // with the new producer cycle bit state (false). + let mut trb = NormalTrb::new(); + trb.set_trb_type(TrbType::Normal); + trb.set_data_buffer(3); + trb.set_cycle(false); // Link TRB toggled the cycle. + gm.write_obj_at_addr(trb.clone(), GuestAddress(0x100)) + .unwrap(); + + // Read new transfer descriptor. + let descriptor = transfer_ring + .dequeue_transfer_descriptor() + .unwrap() + .unwrap(); + assert_eq!(descriptor.len(), 1); + assert_eq!(descriptor[0].trb.get_parameter(), 3); + + assert_eq!(transfer_ring.consumer_cycle_state, false); + } } |