summaryrefslogtreecommitdiff
path: root/rust
diff options
context:
space:
mode:
authorAlexandre Courbot <acourbot@nvidia.com>2026-03-27 00:22:07 +0900
committerAlexandre Courbot <acourbot@nvidia.com>2026-03-28 22:20:07 +0900
commit816718c611cab2164d718b91ad8204afcd0af81f (patch)
tree9ca32950ee9230252a0798634c6b9d85cc712e91 /rust
parent6dd782af1eb6be16a80349ea7822f0f8a23bb3e8 (diff)
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>
Diffstat (limited to 'rust')
-rw-r--r--rust/kernel/dma.rs107
1 files changed, 107 insertions, 0 deletions
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
index 7ea3c3b73367..4995ee5dc689 100644
--- a/rust/kernel/dma.rs
+++ b/rust/kernel/dma.rs
@@ -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]> {