[PATCH 0/3] rust: dma: add the single-buffer streaming DMA API

Maurice Hieronymus <[email protected]> Wed, 05 Aug 2026 23:54:40 +0200
Newsgroups org.kernel.vger.rust-for-linux,dev.linux.lists.driver-core,dev.linux.lists.nova-gpu,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
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/[email protected]/
[2] https://lore.kernel.org/rust-for-linux/[email protected]/

Signed-off-by: Maurice Hieronymus <[email protected]>
---
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 <[email protected]>