Skip to content

Commit 816718c

Browse files
committed
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>
1 parent 6dd782a commit 816718c

1 file changed

Lines changed: 107 additions & 0 deletions

File tree

rust/kernel/dma.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,66 @@ impl<T: AsBytes + FromBytes> CoherentBox<[T]> {
453453

454454
Ok(())
455455
}
456+
457+
/// Allocates a region of coherent memory of the same size as `data` and initializes it with a
458+
/// copy of its contents.
459+
///
460+
/// This is the [`CoherentBox`] variant of [`Coherent::from_slice_with_attrs`].
461+
///
462+
/// # Examples
463+
///
464+
/// ```
465+
/// use core::ops::Deref;
466+
///
467+
/// # use kernel::device::{Bound, Device};
468+
/// use kernel::dma::{
469+
/// attrs::*,
470+
/// CoherentBox
471+
/// };
472+
///
473+
/// # fn test(dev: &Device<Bound>) -> Result {
474+
/// let data = [0u8, 1u8, 2u8, 3u8];
475+
/// let c: CoherentBox<[u8]> =
476+
/// CoherentBox::from_slice_with_attrs(dev, &data, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
477+
///
478+
/// assert_eq!(c.deref(), &data);
479+
/// # Ok::<(), Error>(()) }
480+
/// ```
481+
pub fn from_slice_with_attrs(
482+
dev: &device::Device<Bound>,
483+
data: &[T],
484+
gfp_flags: kernel::alloc::Flags,
485+
dma_attrs: Attrs,
486+
) -> Result<Self>
487+
where
488+
T: Copy,
489+
{
490+
let mut slice = Self(Coherent::<T>::alloc_slice_with_attrs(
491+
dev,
492+
data.len(),
493+
gfp_flags,
494+
dma_attrs,
495+
)?);
496+
497+
// PANIC: `slice` was created with length `data.len()`.
498+
slice.copy_from_slice(data);
499+
500+
Ok(slice)
501+
}
502+
503+
/// Performs the same functionality as [`CoherentBox::from_slice_with_attrs`], except the
504+
/// `dma_attrs` is 0 by default.
505+
#[inline]
506+
pub fn from_slice(
507+
dev: &device::Device<Bound>,
508+
data: &[T],
509+
gfp_flags: kernel::alloc::Flags,
510+
) -> Result<Self>
511+
where
512+
T: Copy,
513+
{
514+
Self::from_slice_with_attrs(dev, data, gfp_flags, Attrs(0))
515+
}
456516
}
457517

458518
impl<T: AsBytes + FromBytes> CoherentBox<T> {
@@ -839,6 +899,53 @@ impl<T: AsBytes + FromBytes> Coherent<T> {
839899
) -> Result<Coherent<[T]>> {
840900
Self::zeroed_slice_with_attrs(dev, len, gfp_flags, Attrs(0))
841901
}
902+
903+
/// Allocates a region of coherent memory of the same size as `data` and initializes it with a
904+
/// copy of its contents.
905+
///
906+
/// # Examples
907+
///
908+
/// ```
909+
/// # use kernel::device::{Bound, Device};
910+
/// use kernel::dma::{
911+
/// attrs::*,
912+
/// Coherent
913+
/// };
914+
///
915+
/// # fn test(dev: &Device<Bound>) -> Result {
916+
/// let data = [0u8, 1u8, 2u8, 3u8];
917+
/// // `c` has the same content as `data`.
918+
/// let c: Coherent<[u8]> =
919+
/// Coherent::from_slice_with_attrs(dev, &data, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
920+
///
921+
/// # Ok::<(), Error>(()) }
922+
/// ```
923+
#[inline]
924+
pub fn from_slice_with_attrs(
925+
dev: &device::Device<Bound>,
926+
data: &[T],
927+
gfp_flags: kernel::alloc::Flags,
928+
dma_attrs: Attrs,
929+
) -> Result<Coherent<[T]>>
930+
where
931+
T: Copy,
932+
{
933+
CoherentBox::from_slice_with_attrs(dev, data, gfp_flags, dma_attrs).map(Into::into)
934+
}
935+
936+
/// Performs the same functionality as [`Coherent::from_slice_with_attrs`], except the
937+
/// `dma_attrs` is 0 by default.
938+
#[inline]
939+
pub fn from_slice(
940+
dev: &device::Device<Bound>,
941+
data: &[T],
942+
gfp_flags: kernel::alloc::Flags,
943+
) -> Result<Coherent<[T]>>
944+
where
945+
T: Copy,
946+
{
947+
Self::from_slice_with_attrs(dev, data, gfp_flags, Attrs(0))
948+
}
842949
}
843950

844951
impl<T> Coherent<[T]> {

0 commit comments

Comments
 (0)