]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
rust: dma: implement BinaryWriter for Coherent<[u8]>
authorTimur Tabi <ttabi@nvidia.com>
Thu, 19 Mar 2026 21:26:55 +0000 (16:26 -0500)
committerDanilo Krummrich <dakr@kernel.org>
Wed, 25 Mar 2026 00:24:11 +0000 (01:24 +0100)
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>
rust/kernel/dma.rs

index bf823818a67d4ebc2a5bb82b8ed881ff51040100..3eef7c2396bbe6a3fb73dd65854e7d52ed5f53c1 100644 (file)
@@ -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