Sometimes one may want to obtain a DMA handle starting at a given offset. This can be done by adding said offset to the result of `dma_handle()`, but doing so on the client side carries the risk that the operation will go outside the bounds of the allocation.
Thus, add a `dma_handle_with_offset` method that adds the desired offset after checking that it is still valid. Signed-off-by: Alexandre Courbot <acour...@nvidia.com> --- rust/kernel/dma.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs index 15ff639b3067d0e4a39e181bbe709a9c372a591a..04546e58252d308e7a9f17bd2eae0aebfdc3c271 100644 --- a/rust/kernel/dma.rs +++ b/rust/kernel/dma.rs @@ -238,6 +238,20 @@ pub fn dma_handle(&self) -> bindings::dma_addr_t { self.dma_handle } + /// Returns a DMA handle starting at `offset` (in units of `T`) which may be given to the + /// device as the DMA address base of the region. + /// + /// Returns `EINVAL` if `offset` is not within the bounds of the allocation. + pub fn dma_handle_with_offset(&self, offset: usize) -> Result<bindings::dma_addr_t> { + if offset >= self.count { + Err(EINVAL) + } else { + // INVARIANT: The type invariant of `Self` guarantees that `size_of::<T> * count` fits + // into a `usize`, and `offset` is inferior to `count`. + Ok(self.dma_handle + (offset * core::mem::size_of::<T>()) as bindings::dma_addr_t) + } + } + /// Returns a pointer to an element from the region with bounds checking. `offset` is in /// units of `T`, not the number of bytes. /// -- 2.49.0