From 89b8bec88a6fd02bc3862d4cd79af152b2b65962 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20Yi=C4=9Fit=20=C5=9Eahin?= Date: Fri, 3 May 2024 16:19:21 +0200 Subject: [PATCH] virtq: remove Transfer Transfer was a wrapper around TransferToken, which in turn is a wrapper around BufferToken with the state of the transfer and the queue which the transfer is to be returned. The receiving queues do not need a reference to themselves and the transfer state is no longer needed as a variable since we do not share the transfer with the caller while the transfer in process. As a result, we are able to replace the uses of Transfer with BufferToken. Most methods on Transfer are also wrappers around the underlying BufferToken and could be removed in entirely. Those that didn't have an exact analogue in the implementation of BufferToken were moved there. --- src/drivers/net/virtio_net.rs | 41 +- src/drivers/virtio/virtqueue/mod.rs | 520 +++++-------------------- src/drivers/virtio/virtqueue/packed.rs | 10 +- src/drivers/virtio/virtqueue/split.rs | 12 +- 4 files changed, 133 insertions(+), 450 deletions(-) diff --git a/src/drivers/net/virtio_net.rs b/src/drivers/net/virtio_net.rs index 8ccf9dfb91..36738b9789 100644 --- a/src/drivers/net/virtio_net.rs +++ b/src/drivers/net/virtio_net.rs @@ -2,6 +2,7 @@ //! //! The module contains ... +use alloc::boxed::Box; use alloc::collections::VecDeque; use alloc::rc::Rc; use alloc::vec::Vec; @@ -31,9 +32,7 @@ use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg}; use crate::drivers::virtio::transport::pci::{ComCfg, IsrStatus, NotifCfg}; use crate::drivers::virtio::virtqueue::packed::PackedVq; use crate::drivers::virtio::virtqueue::split::SplitVq; -use crate::drivers::virtio::virtqueue::{ - BuffSpec, BufferToken, Bytes, Transfer, Virtq, VqIndex, VqSize, -}; +use crate::drivers::virtio::virtqueue::{BuffSpec, BufferToken, Bytes, Virtq, VqIndex, VqSize}; use crate::executor::device::{RxToken, TxToken}; /// A wrapper struct for the raw configuration structure. @@ -155,14 +154,14 @@ enum MqCmd { pub struct RxQueues { vqs: Vec>, - poll_queue: Rc>>, + poll_queue: Rc>>>, is_multi: bool, } impl RxQueues { pub fn new( vqs: Vec>, - poll_queue: Rc>>, + poll_queue: Rc>>>, is_multi: bool, ) -> Self { Self { @@ -176,14 +175,8 @@ impl RxQueues { /// This currently include nothing. But in the future it might include among others:: /// * Calculating missing checksums /// * Merging receive buffers, by simply checking the poll_queue (if VIRTIO_NET_F_MRG_BUF) - fn post_processing(transfer: Transfer) -> Result { - if transfer.poll() { - // Here we could implement all features. - Ok(transfer) - } else { - warn!("Unfinished transfer in post processing. Returning buffer to queue. This will need explicit cleanup."); - Err(VirtioNetError::ProcessOngoing) - } + fn post_processing(buffer_tkn: Box) -> Result, VirtioNetError> { + Ok(buffer_tkn) } /// Adds a given queue to the underlying vector and populates the queue with RecvBuffers. @@ -230,7 +223,7 @@ impl RxQueues { } } - fn get_next(&mut self) -> Option { + fn get_next(&mut self) -> Option> { let transfer = self.poll_queue.borrow_mut().pop_front(); transfer.or_else(|| { @@ -276,7 +269,7 @@ impl RxQueues { /// to the respective queue structures. pub struct TxQueues { vqs: Vec>, - poll_queue: Rc>>, + poll_queue: Rc>>>, ready_queue: Vec, /// Indicates, whether the Driver/Device are using multiple /// queues for communication. @@ -286,7 +279,7 @@ pub struct TxQueues { impl TxQueues { pub fn new( vqs: Vec>, - poll_queue: Rc>>, + poll_queue: Rc>>>, ready_queue: Vec, is_multi: bool, ) -> Self { @@ -419,8 +412,8 @@ impl TxQueues { self.poll(); } - while let Some(transfer) = self.poll_queue.borrow_mut().pop_back() { - let mut tkn = transfer.reuse().unwrap(); + while let Some(buffer_token) = self.poll_queue.borrow_mut().pop_back() { + let mut tkn = buffer_token.reset(); let (send_len, _) = tkn.len(); match send_len.cmp(&len) { @@ -586,8 +579,7 @@ impl NetworkDriver for VirtioNetDriver { // drop packets with invalid packet size if packet.len() < HEADER_SIZE { transfer - .reuse() - .unwrap() + .reset() .provide() .dispatch_await(Rc::clone(&self.recv_vqs.poll_queue), false); @@ -604,8 +596,7 @@ impl NetworkDriver for VirtioNetDriver { vec_data.extend_from_slice(&packet[mem::size_of::()..]); transfer - .reuse() - .unwrap() + .reset() .provide() .dispatch_await(Rc::clone(&self.recv_vqs.poll_queue), false); @@ -627,8 +618,7 @@ impl NetworkDriver for VirtioNetDriver { let packet = recv_data.pop().unwrap(); vec_data.extend_from_slice(packet); transfer - .reuse() - .unwrap() + .reset() .provide() .dispatch_await(Rc::clone(&self.recv_vqs.poll_queue), false); } @@ -637,8 +627,7 @@ impl NetworkDriver for VirtioNetDriver { } else { error!("Empty transfer, or with wrong buffer layout. Reusing and returning error to user-space network driver..."); transfer - .reuse() - .unwrap() + .reset() .write_seq(None::<&VirtioNetHdr>, Some(&VirtioNetHdr::default())) .unwrap() .provide() diff --git a/src/drivers/virtio/virtqueue/mod.rs b/src/drivers/virtio/virtqueue/mod.rs index 3302abb51a..e0d9560ab9 100644 --- a/src/drivers/virtio/virtqueue/mod.rs +++ b/src/drivers/virtio/virtqueue/mod.rs @@ -156,7 +156,7 @@ pub trait Virtq: VirtqPrivate { fn dispatch_batch_await( &self, tkns: Vec, - await_queue: Rc>>, + await_queue: Rc>>>, notif: bool, ); @@ -1399,7 +1399,7 @@ pub fn dispatch_batch(tkns: Vec, notif: bool) { /// updated notification flags before finishing transfers! pub fn dispatch_batch_await( tkns: Vec, - await_queue: Rc>>, + await_queue: Rc>>>, notif: bool, ) { let mut used_vqs: Vec<(Rc, Vec)> = Vec::new(); @@ -1478,404 +1478,6 @@ pub trait AsSliceU8 { } } -/// The [Transfer] will be received when a [TransferToken] is dispatched via [TransferToken::dispatch_blocking] or through the await -/// queue given to [TransferToken::dispatch_await]. -/// -/// The struct represents an ongoing transfer or an active transfer. While this does NOT mean, that the transfer is at all times inside -/// actual virtqueue. The Transfers state can be polled via `Transfer.poll()`, which returns a bool if the transfer is finished. -/// -/// **Finished Transfers:** -/// * Finished transfers are able to return their send and receive buffers. Either as a copy via `Transfer.ret_cpy()` or as the actual -/// buffers via `Transfer.ret()`. -/// * Finished transfers can be reused via `Transfer.reuse()`. -/// * This returns an normal BufferToken (One should be cautious with reusing transfers where buffers were created from raw pointers) -pub struct Transfer { - transfer_tkn: Option>, -} - -// Public Interface of Transfer -impl Transfer { - /// Used to poll the current state of the transfer. - /// * true = Transfer is finished and can be closed, reused or return data - /// * false = Transfer is ongoing - pub fn poll(&self) -> bool { - // Unwrapping is okay here, as Transfers must hold a TransferToken - match self.transfer_tkn.as_ref().unwrap().state { - TransferState::Finished => true, - TransferState::Ready => unreachable!("Transfers owned by other than queue should have Tokens, of Finished or Processing State!"), - TransferState::Processing => false, - } - } - - /// Returns a vector of immutable slices to the underlying memory areas. - /// - /// The vectors contain the slices in creation order. - /// E.g.: - /// * Driver creates buffer as - /// * send buffer: 50 bytes, 60 bytes - /// * receive buffer: 10 bytes - /// * The return tuple will be: - /// * `(Some(vec[50, 60]), Some(vec[10]))` - /// * Where 50 refers to a slice of u8 of length 50. - /// The other numbers follow the same principle. - pub fn as_slices(&self) -> Result<(Option>, Option>), VirtqError> { - match &self.transfer_tkn.as_ref().unwrap().state { - TransferState::Finished => { - // Unwrapping is okay here, as TransferToken must hold a BufferToken - let send_data = match &self - .transfer_tkn - .as_ref() - .unwrap() - .buff_tkn - .as_ref() - .unwrap() - .send_buff - { - Some(buff) => { - let mut arr = Vec::with_capacity(buff.as_slice().len()); - - for desc in buff.as_slice() { - arr.push(desc.deref()) - } - - Some(arr) - } - None => None, - }; - - let recv_data = match &self - .transfer_tkn - .as_ref() - .unwrap() - .buff_tkn - .as_ref() - .unwrap() - .recv_buff - { - Some(buff) => { - let mut arr = Vec::with_capacity(buff.as_slice().len()); - - for desc in buff.as_slice() { - arr.push(desc.deref()) - } - - Some(arr) - } - None => None, - }; - - Ok((send_data, recv_data)) - } - TransferState::Processing => Err(VirtqError::OngoingTransfer(None)), - TransferState::Ready => unreachable!( - "Transfers not owned by a queue Must have state Finished or Processing!" - ), - } - } - - /// Returns a vector of mutable slices to the underlying memory areas. - /// - /// The vectors contain the slices in creation order. - /// E.g.: - /// * Driver creates buffer as - /// * send buffer: 50 bytes, 60 bytes - /// * receive buffer: 10 bytes - /// * The return tuple will be: - /// * `(Some(vec[50, 60]), Some(vec[10]))` - /// * Where 50 refers to a slice of u8 of length 50. - /// The other numbers follow the same principle. - pub fn as_slices_mut( - &mut self, - ) -> Result<(Option>, Option>), VirtqError> { - match &self.transfer_tkn.as_ref().unwrap().state { - TransferState::Finished => { - let (send_buff, recv_buff) = { - let BufferToken { - send_buff, - recv_buff, - .. - } = self - .transfer_tkn - .as_mut() - .unwrap() - .buff_tkn - .as_mut() - .unwrap(); - - (send_buff.as_mut(), recv_buff.as_mut()) - }; - - // Unwrapping is okay here, as TransferToken must hold a BufferToken - let send_data = match send_buff { - Some(buff) => { - let mut arr = Vec::with_capacity(buff.as_slice().len()); - - for desc in buff.as_mut_slice() { - arr.push(desc.deref_mut()) - } - - Some(arr) - } - None => None, - }; - - let recv_data = match recv_buff { - Some(buff) => { - let mut arr = Vec::with_capacity(buff.as_slice().len()); - - for desc in buff.as_mut_slice() { - arr.push(desc.deref_mut()) - } - - Some(arr) - } - None => None, - }; - - Ok((send_data, recv_data)) - } - TransferState::Processing => Err(VirtqError::OngoingTransfer(None)), - TransferState::Ready => unreachable!( - "Transfers not owned by a queue Must have state Finished or Processing!" - ), - } - } - - /// Returns a copy if the respective send and receiving buffers - /// The actual buffers remain in the BufferToken and hence the token can be - /// reused afterwards. - /// - /// **Return Tuple** - /// - /// `(sended_data, received_data)` - /// - /// The returned data is of type `Box<[Box<[u8]>]>`. This function therefore preserves - /// the scattered structure of the buffer, - /// - /// If one creates this buffer via a `Virtq.prep_transfer_from_raw()` - /// call, a casting back to the original structure `T` is NOT possible. - /// In these cases please use `Transfer.ret_cpy()` or use 'BuffSpec::Single' only! - pub fn ret_scat_cpy( - &self, - ) -> Result<(Option>>, Option>>), VirtqError> { - match &self.transfer_tkn.as_ref().unwrap().state { - TransferState::Finished => { - // Unwrapping is okay here, as TransferToken must hold a BufferToken - let send_data = self - .transfer_tkn - .as_ref() - .unwrap() - .buff_tkn - .as_ref() - .unwrap() - .send_buff - .as_ref() - .map(Buffer::scat_cpy); - - let recv_data = self - .transfer_tkn - .as_ref() - .unwrap() - .buff_tkn - .as_ref() - .unwrap() - .recv_buff - .as_ref() - .map(Buffer::scat_cpy); - - Ok((send_data, recv_data)) - } - TransferState::Processing => Err(VirtqError::OngoingTransfer(None)), - TransferState::Ready => unreachable!( - "Transfers not owned by a queue Must have state Finished or Processing!" - ), - } - } - - /// Returns a copy if the respective send and receiving buffers - /// The actual buffers remain in the BufferToken and hence the token can be - /// reused afterwards. - /// - /// **Return Tuple** - /// - /// `(sended_data, received_data)` - /// - /// The sended_data is `Box<[u8]>`. This function herefore merges (if multiple descriptors - /// were requested for one buffer) into a single `[u8]`. - /// - /// It can be assumed, that if one created the send buffer from a structure `T`, that - /// `&sended_data[0] as *const u8 == *const T` - pub fn ret_cpy(&self) -> Result<(Option>, Option>), VirtqError> { - match &self.transfer_tkn.as_ref().unwrap().state { - TransferState::Finished => { - // Unwrapping is okay here, as TransferToken must hold a BufferToken - let send_data = self - .transfer_tkn - .as_ref() - .unwrap() - .buff_tkn - .as_ref() - .unwrap() - .send_buff - .as_ref() - .map(Buffer::cpy); - - let recv_data = self - .transfer_tkn - .as_ref() - .unwrap() - .buff_tkn - .as_ref() - .unwrap() - .recv_buff - .as_ref() - .map(Buffer::cpy); - - Ok((send_data, recv_data)) - } - TransferState::Processing => Err(VirtqError::OngoingTransfer(None)), - TransferState::Ready => unreachable!( - "Transfers not owned by a queue Must have state Finished or Processing!" - ), - } - } - - /// # HIGHLY EXPERIMENTIALLY - /// This function returns a Vector of tuples to the allocated memory areas Currently the complete behaviour of this function is not well tested and it should be used with care. - /// - /// **INFO:** - /// * Memory regions MUST be deallocated via `Virtq::free_raw(*mut u8, len)` - /// * Memory regions length might be larger than expected due to the used - /// allocation function in the kernel. Hence one MUST NOT assume valid data - /// after the length of the buffer, that was given at creation, is reached. - /// * Still the provided `Virtq::free_raw(*mut u8, len)` function MUST be provided - /// with the actual usize returned by this function in order to prevent memory leaks or failure. - /// * Fails if `TransferState != Finished`. - /// - pub fn into_raw( - mut self, - ) -> Result<(Option>, Option>), VirtqError> { - let state = self.transfer_tkn.as_ref().unwrap().state; - - match state { - TransferState::Finished => { - // Desctructure Token - let mut transfer_tkn = self.transfer_tkn.take().unwrap(); - - let mut buffer_tkn = transfer_tkn.buff_tkn.take().unwrap(); - - let send_data = if buffer_tkn.ret_send { - match buffer_tkn.send_buff { - Some(buff) => { - // This data is not a second time returnable - // Unnecessary, because token will be dropped. - // But to be consistent in state. - buffer_tkn.ret_send = false; - Some(buff.into_raw()) - } - None => None, - } - } else { - return Err(VirtqError::NoReuseBuffer); - }; - - let recv_data = if buffer_tkn.ret_recv { - match buffer_tkn.recv_buff { - Some(buff) => { - // This data is not a second time returnable - // Unnecessary, because token will be dropped. - // But to be consistent in state. - buffer_tkn.ret_recv = false; - Some(buff.into_raw()) - } - None => None, - } - } else { - return Err(VirtqError::NoReuseBuffer); - }; - // Prevent Token to be reusable although it will be dropped - // later in this function. - // Unnecessary but to be consistent in state. - // - // Unwrapping is okay here, as TransferToken must hold a BufferToken - buffer_tkn.reusable = false; - - Ok((send_data, recv_data)) - } - TransferState::Processing => Err(VirtqError::OngoingTransfer(Some(self))), - TransferState::Ready => unreachable!( - "Transfers not owned by a queue Must have state Finished or Processing!" - ), - } - } - - /// If the transfer was finished returns the BufferToken inside the transfer else returns an error. - /// - /// **WARN:** - /// - /// This function does restore the actual size of the Buffer at creation but does NOT reset the - /// written memory areas to zero! If this is needed please use `Transfer.reuse_reset` - pub fn reuse(mut self) -> Result { - // Unwrapping is okay here, as TransferToken must hold a BufferToken - match self.transfer_tkn.as_ref().unwrap().state { - TransferState::Finished => { - if self - .transfer_tkn - .as_ref() - .unwrap() - .buff_tkn - .as_ref() - .unwrap() - .reusable - { - let tkn = self.transfer_tkn.take().unwrap().buff_tkn.take().unwrap(); - - Ok(tkn.reset()) - } else { - Err(VirtqError::NoReuseBuffer) - } - } - TransferState::Processing => Err(VirtqError::OngoingTransfer(Some(self))), - TransferState::Ready => unreachable!( - "Transfers coming from outside the queue must be Processing or Finished" - ), - } - } - - /// If the transfer was finished returns the BufferToken inside the transfer else returns an error. - /// - /// - /// This function does restore the actual size of the Buffer at creation and does reset the - /// written memory areas to zero! Depending on the size of the Buffer this might take some time and - /// one could prefer to allocate a new token via prep_buffer() of the wanted size. - pub fn reuse_reset(mut self) -> Result { - // Unwrapping is okay here, as TransferToken must hold a BufferToken - match self.transfer_tkn.as_ref().unwrap().state { - TransferState::Finished => { - if self - .transfer_tkn - .as_ref() - .unwrap() - .buff_tkn - .as_ref() - .unwrap() - .reusable - { - let tkn = self.transfer_tkn.take().unwrap().buff_tkn.take().unwrap(); - - Ok(tkn.reset_purge()) - } else { - Err(VirtqError::NoReuseBuffer) - } - } - TransferState::Processing => Err(VirtqError::OngoingTransfer(Some(self))), - TransferState::Ready => unreachable!( - "Transfers coming from outside the queue must be Processing or Finished" - ), - } - } -} - /// Enum indicates the current state of a transfer. #[derive(PartialEq, Copy, Clone, Debug)] enum TransferState { @@ -1898,7 +1500,7 @@ pub struct TransferToken { /// If Some, finished TransferTokens will be placed here /// as finished `Transfers`. If None, only the state /// of the Token will be changed. - await_queue: Option>>>, + await_queue: Option>>>>, } /// Public Interface for TransferToken @@ -1914,7 +1516,11 @@ impl TransferToken { /// The `notif` parameter indicates if the driver wants to have a notification for this specific /// transfer. This is only for performance optimization. As it is NOT ensured, that the device sees the /// updated notification flags before finishing transfers! - pub fn dispatch_await(mut self, await_queue: Rc>>, notif: bool) { + pub fn dispatch_await( + mut self, + await_queue: Rc>>>, + notif: bool, + ) { self.await_queue = Some(Rc::clone(&await_queue)); self.get_vq().dispatch(self, notif); @@ -1939,7 +1545,7 @@ impl TransferToken { /// **INFO:** /// Currently this function is constantly polling the queue while keeping the notifications disabled. /// Upon finish notifications are enabled again. - pub fn dispatch_blocking(self) -> Result { + pub fn dispatch_blocking(self) -> Result, VirtqError> { let vq = self.get_vq(); let rcv_queue = Rc::new(RefCell::new(VecDeque::with_capacity(1))); self.dispatch_await(rcv_queue.clone(), false); @@ -2143,7 +1749,7 @@ impl BufferToken { /// * Resetting the write status inside the MemDescr. -> Allowing to rewrite the buffers /// * Resetting the MemDescr length at initialization. This length might be reduced upon writes /// of the driver or the device. - fn reset(mut self) -> Self { + pub fn reset(mut self) -> Self { let mut ctrl_desc_cnt = 0usize; if let Some(buff) = self.send_buff.as_mut() { @@ -2396,6 +2002,7 @@ impl BufferToken { (None, None) => unreachable!("Empty BufferToken not allowed!"), } } + /// Returns the underlying raw pointers to the user accessible memory hold by the Buffertoken. This is mostly /// useful in order to provide the user space with pointers to write to. Return tuple has the form /// (`pointer_to_mem_area`, `length_of_accessible_mem_area`). @@ -2442,6 +2049,102 @@ impl BufferToken { } } + /// Returns a vector of immutable slices to the underlying memory areas. + /// + /// The vectors contain the slices in creation order. + /// E.g.: + /// * Driver creates buffer as + /// * send buffer: 50 bytes, 60 bytes + /// * receive buffer: 10 bytes + /// * The return tuple will be: + /// * `(Some(vec[50, 60]), Some(vec[10]))` + /// * Where 50 refers to a slice of u8 of length 50. + /// The other numbers follow the same principle. + pub fn as_slices(&self) -> Result<(Option>, Option>), VirtqError> { + // Unwrapping is okay here, as TransferToken must hold a BufferToken + let send_data = match &self.send_buff { + Some(buff) => { + let mut arr = Vec::with_capacity(buff.as_slice().len()); + + for desc in buff.as_slice() { + arr.push(desc.deref()) + } + + Some(arr) + } + None => None, + }; + + let recv_data = match &self.recv_buff { + Some(buff) => { + let mut arr = Vec::with_capacity(buff.as_slice().len()); + + for desc in buff.as_slice() { + arr.push(desc.deref()) + } + + Some(arr) + } + None => None, + }; + + Ok((send_data, recv_data)) + } + + /// Returns a vector of mutable slices to the underlying memory areas. + /// + /// The vectors contain the slices in creation order. + /// E.g.: + /// * Driver creates buffer as + /// * send buffer: 50 bytes, 60 bytes + /// * receive buffer: 10 bytes + /// * The return tuple will be: + /// * `(Some(vec[50, 60]), Some(vec[10]))` + /// * Where 50 refers to a slice of u8 of length 50. + /// The other numbers follow the same principle. + pub fn as_slices_mut( + &mut self, + ) -> Result<(Option>, Option>), VirtqError> { + let (send_buff, recv_buff) = { + let BufferToken { + send_buff, + recv_buff, + .. + } = self; + + (send_buff.as_mut(), recv_buff.as_mut()) + }; + + // Unwrapping is okay here, as TransferToken must hold a BufferToken + let send_data = match send_buff { + Some(buff) => { + let mut arr = Vec::with_capacity(buff.as_slice().len()); + + for desc in buff.as_mut_slice() { + arr.push(desc.deref_mut()) + } + + Some(arr) + } + None => None, + }; + + let recv_data = match recv_buff { + Some(buff) => { + let mut arr = Vec::with_capacity(buff.as_slice().len()); + + for desc in buff.as_mut_slice() { + arr.push(desc.deref_mut()) + } + + Some(arr) + } + None => None, + }; + + Ok((send_data, recv_data)) + } + /// Writes the provided datastructures into the respective buffers. `K` into `self.send_buff` and `H` into /// `self.recv_buff`. /// If the provided datastructures do not "fit" into the respective buffers, the function will return an error. Even @@ -3306,7 +3009,6 @@ impl From for u16 { /// This module unifies errors provided to useres of a virtqueue, independent of the underlying /// virtqueue implementation, realized via the different enum variants. pub mod error { - use super::Transfer; use crate::fd; #[derive(Debug)] @@ -3348,13 +3050,6 @@ pub mod error { /// via `Virtq.prep_transfer_from_raw()`. Due to the fact, that reusing /// Buffers which refer to raw pointers seems dangerours, this is forbidden. NoReuseBuffer, - /// Indicates that a Transfer method was called, that is only allowed to be - /// called when the transfer is Finished (or Ready, although this state is - /// only allowed for Transfer structs owned by the Virtqueue). - /// The Error returns the called Transfer for recovery, if called from a - /// consuming function as a `Some(Transfer)`. For non-consuming - /// functions returns `None`. - OngoingTransfer(Option), /// Indicates a write into a Buffer that is not existing NoBufferAvail, /// Indicates that a write to a Buffer happened and the data to be written into @@ -3380,7 +3075,6 @@ pub mod error { VirtqError::NoDescrAvail => write!(f, "Virtqs memory pool is exhausted!"), VirtqError::BufferSizeWrong(_) => write!(f, "Specified Buffer is to small for write!"), VirtqError::NoReuseBuffer => write!(f, "Buffer can not be reused!"), - VirtqError::OngoingTransfer(_) => write!(f, "Transfer is ongoging and can not be used currently!"), VirtqError::WriteTooLarge => write!(f, "Write is to large for BufferToken!"), VirtqError::BufferToLarge => write!(f, "Buffer to large for queue! u32::MAX exceeded."), VirtqError::QueueSizeNotAllowed(_) => write!(f, "The requested queue size is not valid."), diff --git a/src/drivers/virtio/virtqueue/packed.rs b/src/drivers/virtio/virtqueue/packed.rs index 5fc1467a7c..74afb6ce31 100644 --- a/src/drivers/virtio/virtqueue/packed.rs +++ b/src/drivers/virtio/virtqueue/packed.rs @@ -20,7 +20,7 @@ use super::super::transport::mmio::{ComCfg, NotifCfg, NotifCtrl}; use super::super::transport::pci::{ComCfg, NotifCfg, NotifCtrl}; use super::error::VirtqError; use super::{ - BuffSpec, Buffer, BufferToken, Bytes, DescrFlags, MemDescr, MemPool, Transfer, TransferState, + BuffSpec, Buffer, BufferToken, Bytes, DescrFlags, MemDescr, MemPool, TransferState, TransferToken, Virtq, VirtqPrivate, VqIndex, VqSize, }; use crate::arch::mm::paging::{BasePageSize, PageSize}; @@ -139,9 +139,9 @@ impl DescriptorRing { tkn.state = TransferState::Finished; if let Some(queue) = tkn.await_queue.take() { // Place the TransferToken in a Transfer, which will hold ownership of the token - queue.borrow_mut().push_back(Transfer { - transfer_tkn: Some(tkn), - }); + queue + .borrow_mut() + .push_back(Box::new(tkn.buff_tkn.unwrap())); } } } @@ -1003,7 +1003,7 @@ impl Virtq for PackedVq { fn dispatch_batch_await( &self, mut tkns: Vec, - await_queue: Rc>>, + await_queue: Rc>>>, notif: bool, ) { // Zero transfers are not allowed diff --git a/src/drivers/virtio/virtqueue/split.rs b/src/drivers/virtio/virtqueue/split.rs index d655d61934..1226022ea6 100644 --- a/src/drivers/virtio/virtqueue/split.rs +++ b/src/drivers/virtio/virtqueue/split.rs @@ -18,8 +18,8 @@ use super::super::transport::mmio::{ComCfg, NotifCfg, NotifCtrl}; use super::super::transport::pci::{ComCfg, NotifCfg, NotifCtrl}; use super::error::VirtqError; use super::{ - BuffSpec, BufferToken, Bytes, DescrFlags, MemDescr, MemPool, Transfer, TransferState, - TransferToken, Virtq, VirtqPrivate, VqIndex, VqSize, + BuffSpec, BufferToken, Bytes, DescrFlags, MemDescr, MemPool, TransferState, TransferToken, + Virtq, VirtqPrivate, VqIndex, VqSize, }; use crate::arch::memory_barrier; use crate::arch::mm::paging::{BasePageSize, PageSize}; @@ -216,9 +216,9 @@ impl DescrRing { } tkn.state = TransferState::Finished; if let Some(queue) = tkn.await_queue.take() { - queue.borrow_mut().push_back(Transfer { - transfer_tkn: Some(tkn), - }) + queue + .borrow_mut() + .push_back(Box::new(tkn.buff_tkn.unwrap())) } memory_barrier(); self.read_idx = self.read_idx.wrapping_add(1); @@ -268,7 +268,7 @@ impl Virtq for SplitVq { fn dispatch_batch_await( &self, _tkns: Vec, - _await_queue: Rc>>, + _await_queue: Rc>>>, _notif: bool, ) { unimplemented!()