[PATCH 0/3] rust: dma: add the single-buffer streaming DMA API
From: Maurice Hieronymus
Date: Wed Aug 05 2026 - 17:56:07 EST
The Rust DMA abstraction covers `dma_alloc_coherent()` only. The streaming
half (`dma_map_single()`) is missing.
A streaming mapping is a temporary lease on memory the caller already owns:
between map and unmap the buffer belongs to the device, and the CPU may only
touch it in between a `dma_sync_single_for_cpu()` /
`dma_sync_single_for_device()` pair. In C that protocol is left to the driver
author, and getting it wrong is silent data corruption on non-coherent
platforms. It is a borrow handover, so it can be expressed in the type
system:
let mut dma = Streaming::new(dev, buf, DataDirection::Bidirectional)?;
*dma.for_cpu() = 42;
let dma = dma.submit();
// Program `dma.dma_handle()` into the device and wait for the transfer.
// SAFETY: the transfer has been waited for.
let mut dma = unsafe { dma.complete() };
assert_eq!(*dma.for_cpu(), 42);
`submit()` consumes the `Streaming` and returns a `StreamingInFlight`, the
only source of the `DmaAddress`. It owns the buffer, so the contents are
unreachable while a transfer may be in flight, no matter where the driver
stores the address. That is what makes `for_cpu()` safe. Whether the device
has finished cannot be checked by any abstraction, so `complete()` is the
single `unsafe` operation. Dropping a `StreamingInFlight` without
`complete()` leaks the mapping and the storage, with a warning: safe code
cannot prove the device is done, so it is not allowed to unmap or free
memory the device may still be using.
Patch 1 adds `ContiguousBuffer`, describing storage `dma_map_single()`
accepts: a single physically contiguous region in the kernel's linear
mapping. Patch 2 adds the mapping itself. Patch 3 converts nova-core's
`GspFwWprMeta`, a streaming workload written against the coherent API.
One thing to note
=================
`Streaming` borrows a `&'a Device<Bound>` where `Coherent` and
`SGTable<Owned<P>>` both hold an `ARef<Device>`. The DMA API may only be
called while a driver is bound, and `Drop` unmaps, so a refcount does not
express what the mapping needs [1]. The two existing types predate the
`'bound` driver-core infrastructure; converting them is not part of this
series.
Testing
=======
Build-tested on x86_64 with `CLIPPY=1` and `rustfmtcheck`; the kernel crate
doctests, including the new `Streaming` ones, pass under virtme-ng.
Patch 3 is compile-tested only, I have no NVIDIA hardware; it touches the
GSP boot path on all supported chipsets, so a Tested-by would be very
welcome. However, I've tested it on my Rust EDU Driver locally [2] while
using swiotlb=force to emulate bounce buffers on x86.
[1] https://lore.kernel.org/all/20250306160907.GF354511@xxxxxxxxxx/
[2] https://lore.kernel.org/rust-for-linux/20260620-b4-rust-pci-edu-driver-v2-0-6fd6684f2c14@xxxxxxxxxxx/
Signed-off-by: Maurice Hieronymus <mhi@xxxxxxxxxxx>
---
Maurice Hieronymus (3):
rust: dma: add ContiguousBuffer trait for streaming DMA storage
rust: dma: add abstraction for the single-buffer streaming DMA API
gpu: nova-core: gsp: map the WPR meta for streaming DMA
drivers/gpu/nova-core/firmware/booter.rs | 11 +-
drivers/gpu/nova-core/gsp/boot.rs | 20 +-
drivers/gpu/nova-core/gsp/hal.rs | 4 +-
drivers/gpu/nova-core/gsp/hal/gh100.rs | 4 +-
drivers/gpu/nova-core/gsp/hal/tu102.rs | 4 +-
rust/helpers/dma.c | 35 +++
rust/kernel/dma.rs | 449 +++++++++++++++++++++++++++++++
7 files changed, 515 insertions(+), 12 deletions(-)
---
base-commit: dc01dfb37b34beeefcfe1c3055364d41a4070c7e
change-id: 20260719-dma-streaming-9c505a8760cb
Best regards,
--
Maurice Hieronymus <mhi@xxxxxxxxxxx>