diff options
| author | Danilo Krummrich <dakr@kernel.org> | 2026-03-20 20:45:40 +0100 |
|---|---|---|
| committer | Danilo Krummrich <dakr@kernel.org> | 2026-03-23 22:36:00 +0100 |
| commit | 40251bac0e00818b0b632d2d154e4f1f815849eb (patch) | |
| tree | 690280aba08687b5bda630533f22fa10cad1550f /rust | |
| parent | 80f4a7b5138d1c427ee5626e8a796aa6b2994a95 (diff) | |
| download | linux-next-history-40251bac0e00818b0b632d2d154e4f1f815849eb.tar.gz | |
rust: dma: add Coherent:init() and Coherent::init_with_attrs()
Analogous to Coherent::zeroed() and Coherent::zeroed_with_attrs(), add
Coherent:init() and Coherent::init_with_attrs() which both take an impl
Init<T, E> argument initializing the DMA coherent memory.
Compared to CoherentInit, Coherent::init() is a one-shot constructor
that runs an Init closure and immediately exposes the DMA handle,
whereas CoherentInit is a multi-stage initializer that provides safe
&mut T access by withholding the DMA address until converted to
Coherent.
Reviewed-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Link: https://patch.msgid.link/20260320194626.36263-6-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Diffstat (limited to 'rust')
| -rw-r--r-- | rust/kernel/dma.rs | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs index 5b41603cee2e6..be44ec99af5f7 100644 --- a/rust/kernel/dma.rs +++ b/rust/kernel/dma.rs @@ -715,6 +715,44 @@ impl<T: AsBytes + FromBytes> Coherent<T> { Self::zeroed_with_attrs(dev, gfp_flags, Attrs(0)) } + /// Same as [`Coherent::zeroed_with_attrs`], but instead of a zero-initialization the memory is + /// initialized with `init`. + pub fn init_with_attrs<E>( + dev: &device::Device<Bound>, + gfp_flags: kernel::alloc::Flags, + dma_attrs: Attrs, + init: impl Init<T, E>, + ) -> Result<Self> + where + Error: From<E>, + { + let dmem = Self::alloc_with_attrs(dev, gfp_flags, dma_attrs)?; + let ptr = dmem.as_mut_ptr(); + + // SAFETY: + // - `ptr` is valid, properly aligned, and points to exclusively owned memory. + // - If `__init` fails, `self` is dropped, which safely frees the underlying `Coherent`'s + // DMA memory. `T: AsBytes + FromBytes` ensures there are no complex `Drop` requirements + // we are bypassing. + unsafe { init.__init(ptr)? }; + + Ok(dmem) + } + + /// Same as [`Coherent::zeroed`], but instead of a zero-initialization the memory is initialized + /// with `init`. + #[inline] + pub fn init<E>( + dev: &device::Device<Bound>, + gfp_flags: kernel::alloc::Flags, + init: impl Init<T, E>, + ) -> Result<Self> + where + Error: From<E>, + { + Self::init_with_attrs(dev, gfp_flags, Attrs(0), init) + } + /// Allocates a region of `[T; len]` of coherent memory. fn alloc_slice_with_attrs( dev: &device::Device<Bound>, |
