diff options
| author | Timur Tabi <ttabi@nvidia.com> | 2026-03-20 00:26:55 +0300 |
|---|---|---|
| committer | Danilo Krummrich <dakr@kernel.org> | 2026-03-25 03:24:11 +0300 |
| commit | 01681851393642e10b5cc3f35eb6a1916ee4aff1 (patch) | |
| tree | ad72d3d87c2a9972ca19c8ce4e48e0f4d5d31094 | |
| parent | 69bfce0f25c8f949f7a02c3ed93e36aadad3fa57 (diff) | |
| download | linux-01681851393642e10b5cc3f35eb6a1916ee4aff1.tar.xz | |
rust: dma: implement BinaryWriter for Coherent<[u8]>
Implement the BinaryWriter trait for Coherent<[u8]>, enabling DMA
coherent allocations to be exposed as readable binary files. The
implementation handles offset tracking and bounds checking, copying data
from the coherent allocation to userspace via write_dma().
Signed-off-by: Timur Tabi <ttabi@nvidia.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Tested-by: John Hubbard <jhubbard@nvidia.com>
Tested-by: Eliot Courtney <ecourtney@nvidia.com>
Link: https://patch.msgid.link/20260319212658.2541610-4-ttabi@nvidia.com
[ Rebase onto Coherent<T> changes. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
| -rw-r--r-- | rust/kernel/dma.rs | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs index bf823818a67d..3eef7c2396bb 100644 --- a/rust/kernel/dma.rs +++ b/rust/kernel/dma.rs @@ -6,12 +6,14 @@ use crate::{ bindings, + debugfs, device::{ self, Bound, Core, // }, error::to_result, + fs::file, prelude::*, ptr::KnownSize, sync::aref::ARef, @@ -19,6 +21,7 @@ use crate::{ AsBytes, FromBytes, // }, // + uaccess::UserSliceWriter, }; use core::{ ops::{ @@ -876,6 +879,37 @@ impl<T: KnownSize + ?Sized> Drop for Coherent<T> { // can be sent to another thread. unsafe impl<T: KnownSize + Send + ?Sized> Send for Coherent<T> {} +// SAFETY: Sharing `&Coherent` across threads is safe if `T` is `Sync`, because all +// methods that access the buffer contents (`field_read`, `field_write`, `as_slice`, +// `as_slice_mut`) are `unsafe`, and callers are responsible for ensuring no data races occur. +// The safe methods only return metadata or raw pointers whose use requires `unsafe`. +unsafe impl<T: KnownSize + ?Sized + AsBytes + FromBytes + Sync> Sync for Coherent<T> {} + +impl debugfs::BinaryWriter for Coherent<[u8]> { + fn write_to_slice( + &self, + writer: &mut UserSliceWriter, + offset: &mut file::Offset, + ) -> Result<usize> { + if offset.is_negative() { + return Err(EINVAL); + } + + // If the offset is too large for a usize (e.g. on 32-bit platforms), + // then consider that as past EOF and just return 0 bytes. + let Ok(offset_val) = usize::try_from(*offset) else { + return Ok(0); + }; + + let count = self.size().saturating_sub(offset_val).min(writer.len()); + + writer.write_dma(self, offset_val, count)?; + + *offset += count as i64; + Ok(count) + } +} + /// Reads a field of an item from an allocated region of structs. /// /// The syntax is of the form `kernel::dma_read!(dma, proj)` where `dma` is an expression evaluating |
