1
0

rust: dma: use NonNull<T> instead of *mut T

In struct CoherentAllocation, use NonNull<T> instead of a raw *mut T for
the CPU address; the CPU address of a valid CoherentAllocation won't
ever be NULL.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://patch.msgid.link/20251103190655.2326191-2-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
Danilo Krummrich
2025-11-03 20:06:50 +01:00
parent f7afdc4737
commit ededb7bcdf

View File

@@ -12,6 +12,7 @@ use crate::{
sync::aref::ARef, sync::aref::ARef,
transmute::{AsBytes, FromBytes}, transmute::{AsBytes, FromBytes},
}; };
use core::ptr::NonNull;
/// DMA address type. /// DMA address type.
/// ///
@@ -358,7 +359,7 @@ pub struct CoherentAllocation<T: AsBytes + FromBytes> {
dev: ARef<device::Device>, dev: ARef<device::Device>,
dma_handle: DmaAddress, dma_handle: DmaAddress,
count: usize, count: usize,
cpu_addr: *mut T, cpu_addr: NonNull<T>,
dma_attrs: Attrs, dma_attrs: Attrs,
} }
@@ -392,7 +393,7 @@ impl<T: AsBytes + FromBytes> CoherentAllocation<T> {
.ok_or(EOVERFLOW)?; .ok_or(EOVERFLOW)?;
let mut dma_handle = 0; let mut dma_handle = 0;
// SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`. // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
let ret = unsafe { let addr = unsafe {
bindings::dma_alloc_attrs( bindings::dma_alloc_attrs(
dev.as_raw(), dev.as_raw(),
size, size,
@@ -401,9 +402,7 @@ impl<T: AsBytes + FromBytes> CoherentAllocation<T> {
dma_attrs.as_raw(), dma_attrs.as_raw(),
) )
}; };
if ret.is_null() { let addr = NonNull::new(addr).ok_or(ENOMEM)?;
return Err(ENOMEM);
}
// INVARIANT: // INVARIANT:
// - We just successfully allocated a coherent region which is accessible for // - We just successfully allocated a coherent region which is accessible for
// `count` elements, hence the cpu address is valid. We also hold a refcounted reference // `count` elements, hence the cpu address is valid. We also hold a refcounted reference
@@ -414,7 +413,7 @@ impl<T: AsBytes + FromBytes> CoherentAllocation<T> {
dev: dev.into(), dev: dev.into(),
dma_handle, dma_handle,
count, count,
cpu_addr: ret.cast::<T>(), cpu_addr: addr.cast(),
dma_attrs, dma_attrs,
}) })
} }
@@ -446,13 +445,13 @@ impl<T: AsBytes + FromBytes> CoherentAllocation<T> {
/// Returns the base address to the allocated region in the CPU's virtual address space. /// Returns the base address to the allocated region in the CPU's virtual address space.
pub fn start_ptr(&self) -> *const T { pub fn start_ptr(&self) -> *const T {
self.cpu_addr self.cpu_addr.as_ptr()
} }
/// Returns the base address to the allocated region in the CPU's virtual address space as /// Returns the base address to the allocated region in the CPU's virtual address space as
/// a mutable pointer. /// a mutable pointer.
pub fn start_ptr_mut(&mut self) -> *mut T { pub fn start_ptr_mut(&mut self) -> *mut T {
self.cpu_addr self.cpu_addr.as_ptr()
} }
/// Returns a DMA handle which may be given to the device as the DMA address base of /// Returns a DMA handle which may be given to the device as the DMA address base of
@@ -580,7 +579,7 @@ impl<T: AsBytes + FromBytes> CoherentAllocation<T> {
// and we've just checked that the range and index is within bounds. // and we've just checked that the range and index is within bounds.
// - `offset` can't overflow since it is smaller than `self.count` and we've checked // - `offset` can't overflow since it is smaller than `self.count` and we've checked
// that `self.count` won't overflow early in the constructor. // that `self.count` won't overflow early in the constructor.
Ok(unsafe { self.cpu_addr.add(offset) }) Ok(unsafe { self.cpu_addr.as_ptr().add(offset) })
} }
/// Reads the value of `field` and ensures that its type is [`FromBytes`]. /// Reads the value of `field` and ensures that its type is [`FromBytes`].