Improve flexibility of DmaStreamSlice

This commit is contained in:
Shaowei Song
2024-11-20 13:43:57 +00:00
committed by Tate, Hongliang Tian
parent 29ebfa3934
commit d37da228ab
3 changed files with 77 additions and 22 deletions

View File

@ -322,12 +322,12 @@ impl DeviceInner {
resp_slice resp_slice
}; };
let dma_slices: Vec<DmaStreamSlice> = dma_streams let dma_slices: Vec<DmaStreamSlice<_>> = dma_streams
.iter() .iter()
.map(|(stream, offset, len)| DmaStreamSlice::new(stream, *offset, *len)) .map(|(stream, offset, len)| DmaStreamSlice::new(stream, *offset, *len))
.collect(); .collect();
let outputs = { let outputs = {
let mut outputs: Vec<&DmaStreamSlice> = Vec::with_capacity(dma_streams.len() + 1); let mut outputs: Vec<&DmaStreamSlice<_>> = Vec::with_capacity(dma_streams.len() + 1);
outputs.extend(dma_slices.iter()); outputs.extend(dma_slices.iter());
outputs.push(&resp_slice); outputs.push(&resp_slice);
outputs outputs
@ -384,12 +384,12 @@ impl DeviceInner {
resp_slice resp_slice
}; };
let dma_slices: Vec<DmaStreamSlice> = dma_streams let dma_slices: Vec<DmaStreamSlice<_>> = dma_streams
.iter() .iter()
.map(|(stream, offset, len)| DmaStreamSlice::new(stream, *offset, *len)) .map(|(stream, offset, len)| DmaStreamSlice::new(stream, *offset, *len))
.collect(); .collect();
let inputs = { let inputs = {
let mut inputs: Vec<&DmaStreamSlice> = Vec::with_capacity(dma_streams.len() + 1); let mut inputs: Vec<&DmaStreamSlice<_>> = Vec::with_capacity(dma_streams.len() + 1);
inputs.push(&req_slice); inputs.push(&req_slice);
inputs.extend(dma_slices.iter()); inputs.extend(dma_slices.iter());
inputs inputs

View File

@ -19,7 +19,7 @@ impl DmaBuf for DmaStream {
} }
} }
impl DmaBuf for DmaStreamSlice<'_> { impl<Dma: AsRef<DmaStream>> DmaBuf for DmaStreamSlice<Dma> {
fn len(&self) -> usize { fn len(&self) -> usize {
self.nbytes() self.nbytes()
} }

View File

@ -48,7 +48,7 @@ struct DmaStreamInner {
pub enum DmaDirection { pub enum DmaDirection {
/// Data flows to the device /// Data flows to the device
ToDevice, ToDevice,
/// Data flows form the device /// Data flows from the device
FromDevice, FromDevice,
/// Data flows both from and to the device /// Data flows both from and to the device
Bidirectional, Bidirectional,
@ -117,16 +117,21 @@ impl DmaStream {
&self.inner.vm_segment &self.inner.vm_segment
} }
/// Returns the number of frames /// Returns the number of frames.
pub fn nframes(&self) -> usize { pub fn nframes(&self) -> usize {
self.inner.vm_segment.nbytes() / PAGE_SIZE self.inner.vm_segment.nbytes() / PAGE_SIZE
} }
/// Returns the number of bytes /// Returns the number of bytes.
pub fn nbytes(&self) -> usize { pub fn nbytes(&self) -> usize {
self.inner.vm_segment.nbytes() self.inner.vm_segment.nbytes()
} }
/// Returns the DMA direction.
pub fn direction(&self) -> DmaDirection {
self.inner.direction
}
/// Synchronizes the streaming DMA mapping with the device. /// Synchronizes the streaming DMA mapping with the device.
/// ///
/// This method should be called under one of the two conditions: /// This method should be called under one of the two conditions:
@ -242,15 +247,21 @@ impl HasPaddr for DmaStream {
} }
} }
impl AsRef<DmaStream> for DmaStream {
fn as_ref(&self) -> &DmaStream {
self
}
}
/// A slice of streaming DMA mapping. /// A slice of streaming DMA mapping.
#[derive(Debug)] #[derive(Debug)]
pub struct DmaStreamSlice<'a> { pub struct DmaStreamSlice<Dma> {
stream: &'a DmaStream, stream: Dma,
offset: usize, offset: usize,
len: usize, len: usize,
} }
impl<'a> DmaStreamSlice<'a> { impl<Dma: AsRef<DmaStream>> DmaStreamSlice<Dma> {
/// Constructs a `DmaStreamSlice` from the [`DmaStream`]. /// Constructs a `DmaStreamSlice` from the [`DmaStream`].
/// ///
/// # Panics /// # Panics
@ -259,9 +270,9 @@ impl<'a> DmaStreamSlice<'a> {
/// this method will panic. /// this method will panic.
/// If the `offset + len` is greater than the length of the stream, /// If the `offset + len` is greater than the length of the stream,
/// this method will panic. /// this method will panic.
pub fn new(stream: &'a DmaStream, offset: usize, len: usize) -> Self { pub fn new(stream: Dma, offset: usize, len: usize) -> Self {
assert!(offset < stream.nbytes()); assert!(offset < stream.as_ref().nbytes());
assert!(offset + len <= stream.nbytes()); assert!(offset + len <= stream.as_ref().nbytes());
Self { Self {
stream, stream,
@ -270,6 +281,16 @@ impl<'a> DmaStreamSlice<'a> {
} }
} }
/// Returns the underlying `DmaStream`.
pub fn stream(&self) -> &DmaStream {
self.stream.as_ref()
}
/// Returns the offset of the slice.
pub fn offset(&self) -> usize {
self.offset
}
/// Returns the number of bytes. /// Returns the number of bytes.
pub fn nbytes(&self) -> usize { pub fn nbytes(&self) -> usize {
self.len self.len
@ -277,35 +298,69 @@ impl<'a> DmaStreamSlice<'a> {
/// Synchronizes the slice of streaming DMA mapping with the device. /// Synchronizes the slice of streaming DMA mapping with the device.
pub fn sync(&self) -> Result<(), Error> { pub fn sync(&self) -> Result<(), Error> {
self.stream.sync(self.offset..self.offset + self.len) self.stream
.as_ref()
.sync(self.offset..self.offset + self.len)
}
/// Returns a reader to read data from it.
pub fn reader(&self) -> Result<VmReader<Infallible>, Error> {
let stream_reader = self
.stream
.as_ref()
.reader()?
.skip(self.offset)
.limit(self.len);
Ok(stream_reader)
}
/// Returns a writer to write data into it.
pub fn writer(&self) -> Result<VmWriter<Infallible>, Error> {
let stream_writer = self
.stream
.as_ref()
.writer()?
.skip(self.offset)
.limit(self.len);
Ok(stream_writer)
} }
} }
impl VmIo for DmaStreamSlice<'_> { impl<Dma: AsRef<DmaStream> + Send + Sync> VmIo for DmaStreamSlice<Dma> {
fn read(&self, offset: usize, writer: &mut VmWriter) -> Result<(), Error> { fn read(&self, offset: usize, writer: &mut VmWriter) -> Result<(), Error> {
if writer.avail() + offset > self.len { if writer.avail() + offset > self.len {
return Err(Error::InvalidArgs); return Err(Error::InvalidArgs);
} }
self.stream.read(self.offset + offset, writer) self.stream.as_ref().read(self.offset + offset, writer)
} }
fn write(&self, offset: usize, reader: &mut VmReader) -> Result<(), Error> { fn write(&self, offset: usize, reader: &mut VmReader) -> Result<(), Error> {
if reader.remain() + offset > self.len { if reader.remain() + offset > self.len {
return Err(Error::InvalidArgs); return Err(Error::InvalidArgs);
} }
self.stream.write(self.offset + offset, reader) self.stream.as_ref().write(self.offset + offset, reader)
} }
} }
impl HasDaddr for DmaStreamSlice<'_> { impl<Dma: AsRef<DmaStream>> HasDaddr for DmaStreamSlice<Dma> {
fn daddr(&self) -> Daddr { fn daddr(&self) -> Daddr {
self.stream.daddr() + self.offset self.stream.as_ref().daddr() + self.offset
} }
} }
impl HasPaddr for DmaStreamSlice<'_> { impl<Dma: AsRef<DmaStream>> HasPaddr for DmaStreamSlice<Dma> {
fn paddr(&self) -> Paddr { fn paddr(&self) -> Paddr {
self.stream.paddr() + self.offset self.stream.as_ref().paddr() + self.offset
}
}
impl Clone for DmaStreamSlice<DmaStream> {
fn clone(&self) -> Self {
Self {
stream: self.stream.clone(),
offset: self.offset,
len: self.len,
}
} }
} }