rust: dma: add from-slice constructors for Coherent and CoherentBox
A very common pattern is to create a block of coherent memory with the content of an already-existing slice of bytes (e.g. a loaded firmware blob). `CoherentBox` makes this easier, but still implies a potentially panicking operation with `copy_from_slice` that requires a `PANIC` comment. Add `from_slice_with_attrs` and `from_slice` methods to both `Coherent` and `CoherentBox` to turn this into a trivial one-step operation. Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org> Reviewed-by: Gary Guo <gary@garyguo.net> Reviewed-by: Danilo Krummrich <dakr@kernel.org> Link: https://patch.msgid.link/20260327-b4-nova-dma-removal-v2-1-616e1d0b5cb3@nvidia.com Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>master
parent
6dd782af1e
commit
816718c611
|
|
@ -453,6 +453,66 @@ impl<T: AsBytes + FromBytes> CoherentBox<[T]> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Allocates a region of coherent memory of the same size as `data` and initializes it with a
|
||||
/// copy of its contents.
|
||||
///
|
||||
/// This is the [`CoherentBox`] variant of [`Coherent::from_slice_with_attrs`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use core::ops::Deref;
|
||||
///
|
||||
/// # use kernel::device::{Bound, Device};
|
||||
/// use kernel::dma::{
|
||||
/// attrs::*,
|
||||
/// CoherentBox
|
||||
/// };
|
||||
///
|
||||
/// # fn test(dev: &Device<Bound>) -> Result {
|
||||
/// let data = [0u8, 1u8, 2u8, 3u8];
|
||||
/// let c: CoherentBox<[u8]> =
|
||||
/// CoherentBox::from_slice_with_attrs(dev, &data, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
|
||||
///
|
||||
/// assert_eq!(c.deref(), &data);
|
||||
/// # Ok::<(), Error>(()) }
|
||||
/// ```
|
||||
pub fn from_slice_with_attrs(
|
||||
dev: &device::Device<Bound>,
|
||||
data: &[T],
|
||||
gfp_flags: kernel::alloc::Flags,
|
||||
dma_attrs: Attrs,
|
||||
) -> Result<Self>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
let mut slice = Self(Coherent::<T>::alloc_slice_with_attrs(
|
||||
dev,
|
||||
data.len(),
|
||||
gfp_flags,
|
||||
dma_attrs,
|
||||
)?);
|
||||
|
||||
// PANIC: `slice` was created with length `data.len()`.
|
||||
slice.copy_from_slice(data);
|
||||
|
||||
Ok(slice)
|
||||
}
|
||||
|
||||
/// Performs the same functionality as [`CoherentBox::from_slice_with_attrs`], except the
|
||||
/// `dma_attrs` is 0 by default.
|
||||
#[inline]
|
||||
pub fn from_slice(
|
||||
dev: &device::Device<Bound>,
|
||||
data: &[T],
|
||||
gfp_flags: kernel::alloc::Flags,
|
||||
) -> Result<Self>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
Self::from_slice_with_attrs(dev, data, gfp_flags, Attrs(0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsBytes + FromBytes> CoherentBox<T> {
|
||||
|
|
@ -839,6 +899,53 @@ impl<T: AsBytes + FromBytes> Coherent<T> {
|
|||
) -> Result<Coherent<[T]>> {
|
||||
Self::zeroed_slice_with_attrs(dev, len, gfp_flags, Attrs(0))
|
||||
}
|
||||
|
||||
/// Allocates a region of coherent memory of the same size as `data` and initializes it with a
|
||||
/// copy of its contents.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use kernel::device::{Bound, Device};
|
||||
/// use kernel::dma::{
|
||||
/// attrs::*,
|
||||
/// Coherent
|
||||
/// };
|
||||
///
|
||||
/// # fn test(dev: &Device<Bound>) -> Result {
|
||||
/// let data = [0u8, 1u8, 2u8, 3u8];
|
||||
/// // `c` has the same content as `data`.
|
||||
/// let c: Coherent<[u8]> =
|
||||
/// Coherent::from_slice_with_attrs(dev, &data, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
|
||||
///
|
||||
/// # Ok::<(), Error>(()) }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn from_slice_with_attrs(
|
||||
dev: &device::Device<Bound>,
|
||||
data: &[T],
|
||||
gfp_flags: kernel::alloc::Flags,
|
||||
dma_attrs: Attrs,
|
||||
) -> Result<Coherent<[T]>>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
CoherentBox::from_slice_with_attrs(dev, data, gfp_flags, dma_attrs).map(Into::into)
|
||||
}
|
||||
|
||||
/// Performs the same functionality as [`Coherent::from_slice_with_attrs`], except the
|
||||
/// `dma_attrs` is 0 by default.
|
||||
#[inline]
|
||||
pub fn from_slice(
|
||||
dev: &device::Device<Bound>,
|
||||
data: &[T],
|
||||
gfp_flags: kernel::alloc::Flags,
|
||||
) -> Result<Coherent<[T]>>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
Self::from_slice_with_attrs(dev, data, gfp_flags, Attrs(0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Coherent<[T]> {
|
||||
|
|
|
|||
Loading…
Reference in New Issue