1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
use custom_error::custom_error;
// library includes
use crate::iomem::IOBufChain;
custom_error! {pub DevQueueError
BufferInvalid = "one of the supplied buffers was invalid",
OutOfMemory = "the operation caused an out-of-memory condition",
QueueFull = "the queue was full. Can't enqueue more buffers.",
QueueEmpty = "the queue was empty. Nothing to deuqueue.",
QueueFailure = "Unknown queue failure",
}
/// A device queue interface supporting enqueue/dequeueu
pub trait DevQueue {
/// Enqueues an IOBufChain into the queue that implements this trait. This
/// updates the descriptors of the queue accordingly, but the buffers may
/// not yet be made available for the device, and a flush() is required
/// afterwards.
///
/// The function returns the buffer chain if there was not enough space to
/// enqueue all buffers in this chain. (e.g., due to limited available space
/// on the queue).
///
/// # Arguments
/// - bufs: a vector of buffers chains to be enqueued on the card
///
/// # Return
/// - On success: returns nothing
/// - On error, in case there was no space left on the device ring, it may
/// return the entire IOBufChain back to the client. The implementor
/// should ensure not to partially enqueue an IOBufChain in this situation
/// by checking for available space up-front.
fn enqueue(&mut self, bufs: IOBufChain) -> Result<(), IOBufChain>;
/// Notifies the device that there have been new descriptors added to the
/// queue.
///
/// # Returns
/// Returns the number of IOBufChains that have been handed to the device.
fn flush(&mut self) -> Result<usize, DevQueueError>;
/// Checks if new buffers can be enqueued and returns the number of
/// available slots. The returned count should reflect the actual available
/// slots if the `exact` parameter is true, otherwise non zero indicates
/// there is at least one slot available.
///
/// # Arguments
/// - `how_many_seg`: Indicate how many segments (of one or multiple
/// IOBufChain) the client wants to enqueue.
///
/// # Returns
/// - true if we can enqueue that many segemnts in the device ring
/// - false if we don't have enough space in the device ring
fn can_enqueue(&self, how_many_seg: usize) -> bool;
/// Dequeues a previously enqueued IOBufChain from the queue which has been
/// processed. The buffers shall be returned back in FIFO order.
///
/// # Returns
/// - On success, one (processed) IOBufChain
/// - A DevQueueError, for example if there is no IOBufChain ready to
/// dequeue.
fn dequeue(&mut self) -> Result<IOBufChain, DevQueueError>;
/// Checks if there are buffers ready to be dequeued and returns the count
/// of processed buffers.
///
/// # Arguments
/// - exact: flag indicating whether the exact amount should be calculated.
/// if this is false the implementation may process less items, but
/// should try to return at least 1 if there is something to be dequed.
///
/// # Returns
/// - The number of IOBufChains that are ready to be dequeued (using
/// `dequeue`).
fn can_dequeue(&mut self, exact: bool) -> usize;
}