xref: /linux/rust/kernel/scatterlist.rs (revision 05aa6fb1c21d7fb9df735da24096d793223789d5)
1*05aa6fb1SDanilo Krummrich // SPDX-License-Identifier: GPL-2.0
2*05aa6fb1SDanilo Krummrich 
3*05aa6fb1SDanilo Krummrich //! Abstractions for scatter-gather lists.
4*05aa6fb1SDanilo Krummrich //!
5*05aa6fb1SDanilo Krummrich //! C header: [`include/linux/scatterlist.h`](srctree/include/linux/scatterlist.h)
6*05aa6fb1SDanilo Krummrich //!
7*05aa6fb1SDanilo Krummrich //! Scatter-gather (SG) I/O is a memory access technique that allows devices to perform DMA
8*05aa6fb1SDanilo Krummrich //! operations on data buffers that are not physically contiguous in memory. It works by creating a
9*05aa6fb1SDanilo Krummrich //! "scatter-gather list", an array where each entry specifies the address and length of a
10*05aa6fb1SDanilo Krummrich //! physically contiguous memory segment.
11*05aa6fb1SDanilo Krummrich //!
12*05aa6fb1SDanilo Krummrich //! The device's DMA controller can then read this list and process the segments sequentially as
13*05aa6fb1SDanilo Krummrich //! part of one logical I/O request. This avoids the need for a single, large, physically contiguous
14*05aa6fb1SDanilo Krummrich //! memory buffer, which can be difficult or impossible to allocate.
15*05aa6fb1SDanilo Krummrich //!
16*05aa6fb1SDanilo Krummrich //! This module provides safe Rust abstractions over the kernel's `struct scatterlist` and
17*05aa6fb1SDanilo Krummrich //! `struct sg_table` types.
18*05aa6fb1SDanilo Krummrich //!
19*05aa6fb1SDanilo Krummrich //! The main entry point is the [`SGTable`] type, which represents a complete scatter-gather table.
20*05aa6fb1SDanilo Krummrich //! It can be either:
21*05aa6fb1SDanilo Krummrich //!
22*05aa6fb1SDanilo Krummrich //! - An owned table ([`SGTable<Owned<P>>`]), created from a Rust memory buffer (e.g., [`VVec`]).
23*05aa6fb1SDanilo Krummrich //!   This type manages the allocation of the `struct sg_table`, the DMA mapping of the buffer, and
24*05aa6fb1SDanilo Krummrich //!   the automatic cleanup of all resources.
25*05aa6fb1SDanilo Krummrich //! - A borrowed reference (&[`SGTable`]), which provides safe, read-only access to a table that was
26*05aa6fb1SDanilo Krummrich //!   allocated by other (e.g., C) code.
27*05aa6fb1SDanilo Krummrich //!
28*05aa6fb1SDanilo Krummrich //! Individual entries in the table are represented by [`SGEntry`], which can be accessed by
29*05aa6fb1SDanilo Krummrich //! iterating over an [`SGTable`].
30*05aa6fb1SDanilo Krummrich 
31*05aa6fb1SDanilo Krummrich use crate::{
32*05aa6fb1SDanilo Krummrich     alloc,
33*05aa6fb1SDanilo Krummrich     alloc::allocator::VmallocPageIter,
34*05aa6fb1SDanilo Krummrich     bindings,
35*05aa6fb1SDanilo Krummrich     device::{Bound, Device},
36*05aa6fb1SDanilo Krummrich     devres::Devres,
37*05aa6fb1SDanilo Krummrich     dma, error,
38*05aa6fb1SDanilo Krummrich     io::resource::ResourceSize,
39*05aa6fb1SDanilo Krummrich     page,
40*05aa6fb1SDanilo Krummrich     prelude::*,
41*05aa6fb1SDanilo Krummrich     types::{ARef, Opaque},
42*05aa6fb1SDanilo Krummrich };
43*05aa6fb1SDanilo Krummrich use core::{ops::Deref, ptr::NonNull};
44*05aa6fb1SDanilo Krummrich 
45*05aa6fb1SDanilo Krummrich /// A single entry in a scatter-gather list.
46*05aa6fb1SDanilo Krummrich ///
47*05aa6fb1SDanilo Krummrich /// An `SGEntry` represents a single, physically contiguous segment of memory that has been mapped
48*05aa6fb1SDanilo Krummrich /// for DMA.
49*05aa6fb1SDanilo Krummrich ///
50*05aa6fb1SDanilo Krummrich /// Instances of this struct are obtained by iterating over an [`SGTable`]. Drivers do not create
51*05aa6fb1SDanilo Krummrich /// or own [`SGEntry`] objects directly.
52*05aa6fb1SDanilo Krummrich #[repr(transparent)]
53*05aa6fb1SDanilo Krummrich pub struct SGEntry(Opaque<bindings::scatterlist>);
54*05aa6fb1SDanilo Krummrich 
55*05aa6fb1SDanilo Krummrich // SAFETY: `SGEntry` can be sent to any task.
56*05aa6fb1SDanilo Krummrich unsafe impl Send for SGEntry {}
57*05aa6fb1SDanilo Krummrich 
58*05aa6fb1SDanilo Krummrich // SAFETY: `SGEntry` has no interior mutability and can be accessed concurrently.
59*05aa6fb1SDanilo Krummrich unsafe impl Sync for SGEntry {}
60*05aa6fb1SDanilo Krummrich 
61*05aa6fb1SDanilo Krummrich impl SGEntry {
62*05aa6fb1SDanilo Krummrich     /// Convert a raw `struct scatterlist *` to a `&'a SGEntry`.
63*05aa6fb1SDanilo Krummrich     ///
64*05aa6fb1SDanilo Krummrich     /// # Safety
65*05aa6fb1SDanilo Krummrich     ///
66*05aa6fb1SDanilo Krummrich     /// Callers must ensure that the `struct scatterlist` pointed to by `ptr` is valid for the
67*05aa6fb1SDanilo Krummrich     /// lifetime `'a`.
68*05aa6fb1SDanilo Krummrich     #[inline]
69*05aa6fb1SDanilo Krummrich     unsafe fn from_raw<'a>(ptr: *mut bindings::scatterlist) -> &'a Self {
70*05aa6fb1SDanilo Krummrich         // SAFETY: The safety requirements of this function guarantee that `ptr` is a valid pointer
71*05aa6fb1SDanilo Krummrich         // to a `struct scatterlist` for the duration of `'a`.
72*05aa6fb1SDanilo Krummrich         unsafe { &*ptr.cast() }
73*05aa6fb1SDanilo Krummrich     }
74*05aa6fb1SDanilo Krummrich 
75*05aa6fb1SDanilo Krummrich     /// Obtain the raw `struct scatterlist *`.
76*05aa6fb1SDanilo Krummrich     #[inline]
77*05aa6fb1SDanilo Krummrich     fn as_raw(&self) -> *mut bindings::scatterlist {
78*05aa6fb1SDanilo Krummrich         self.0.get()
79*05aa6fb1SDanilo Krummrich     }
80*05aa6fb1SDanilo Krummrich 
81*05aa6fb1SDanilo Krummrich     /// Returns the DMA address of this SG entry.
82*05aa6fb1SDanilo Krummrich     ///
83*05aa6fb1SDanilo Krummrich     /// This is the address that the device should use to access the memory segment.
84*05aa6fb1SDanilo Krummrich     #[inline]
85*05aa6fb1SDanilo Krummrich     pub fn dma_address(&self) -> dma::DmaAddress {
86*05aa6fb1SDanilo Krummrich         // SAFETY: `self.as_raw()` is a valid pointer to a `struct scatterlist`.
87*05aa6fb1SDanilo Krummrich         unsafe { bindings::sg_dma_address(self.as_raw()) }
88*05aa6fb1SDanilo Krummrich     }
89*05aa6fb1SDanilo Krummrich 
90*05aa6fb1SDanilo Krummrich     /// Returns the length of this SG entry in bytes.
91*05aa6fb1SDanilo Krummrich     #[inline]
92*05aa6fb1SDanilo Krummrich     pub fn dma_len(&self) -> ResourceSize {
93*05aa6fb1SDanilo Krummrich         #[allow(clippy::useless_conversion)]
94*05aa6fb1SDanilo Krummrich         // SAFETY: `self.as_raw()` is a valid pointer to a `struct scatterlist`.
95*05aa6fb1SDanilo Krummrich         unsafe { bindings::sg_dma_len(self.as_raw()) }.into()
96*05aa6fb1SDanilo Krummrich     }
97*05aa6fb1SDanilo Krummrich }
98*05aa6fb1SDanilo Krummrich 
99*05aa6fb1SDanilo Krummrich /// The borrowed generic type of an [`SGTable`], representing a borrowed or externally managed
100*05aa6fb1SDanilo Krummrich /// table.
101*05aa6fb1SDanilo Krummrich #[repr(transparent)]
102*05aa6fb1SDanilo Krummrich pub struct Borrowed(Opaque<bindings::sg_table>);
103*05aa6fb1SDanilo Krummrich 
104*05aa6fb1SDanilo Krummrich // SAFETY: `Borrowed` can be sent to any task.
105*05aa6fb1SDanilo Krummrich unsafe impl Send for Borrowed {}
106*05aa6fb1SDanilo Krummrich 
107*05aa6fb1SDanilo Krummrich // SAFETY: `Borrowed` has no interior mutability and can be accessed concurrently.
108*05aa6fb1SDanilo Krummrich unsafe impl Sync for Borrowed {}
109*05aa6fb1SDanilo Krummrich 
110*05aa6fb1SDanilo Krummrich /// A scatter-gather table.
111*05aa6fb1SDanilo Krummrich ///
112*05aa6fb1SDanilo Krummrich /// This struct is a wrapper around the kernel's `struct sg_table`. It manages a list of DMA-mapped
113*05aa6fb1SDanilo Krummrich /// memory segments that can be passed to a device for I/O operations.
114*05aa6fb1SDanilo Krummrich ///
115*05aa6fb1SDanilo Krummrich /// The generic parameter `T` is used as a generic type to distinguish between owned and borrowed
116*05aa6fb1SDanilo Krummrich /// tables.
117*05aa6fb1SDanilo Krummrich ///
118*05aa6fb1SDanilo Krummrich ///  - [`SGTable<Owned>`]: An owned table created and managed entirely by Rust code. It handles
119*05aa6fb1SDanilo Krummrich ///    allocation, DMA mapping, and cleanup of all associated resources. See [`SGTable::new`].
120*05aa6fb1SDanilo Krummrich ///  - [`SGTable<Borrowed>`} (or simply [`SGTable`]): Represents a table whose lifetime is managed
121*05aa6fb1SDanilo Krummrich ///    externally. It can be used safely via a borrowed reference `&'a SGTable`, where `'a` is the
122*05aa6fb1SDanilo Krummrich ///    external lifetime.
123*05aa6fb1SDanilo Krummrich ///
124*05aa6fb1SDanilo Krummrich /// All [`SGTable`] variants can be iterated over the individual [`SGEntry`]s.
125*05aa6fb1SDanilo Krummrich #[repr(transparent)]
126*05aa6fb1SDanilo Krummrich #[pin_data]
127*05aa6fb1SDanilo Krummrich pub struct SGTable<T: private::Sealed = Borrowed> {
128*05aa6fb1SDanilo Krummrich     #[pin]
129*05aa6fb1SDanilo Krummrich     inner: T,
130*05aa6fb1SDanilo Krummrich }
131*05aa6fb1SDanilo Krummrich 
132*05aa6fb1SDanilo Krummrich impl SGTable {
133*05aa6fb1SDanilo Krummrich     /// Creates a borrowed `&'a SGTable` from a raw `struct sg_table` pointer.
134*05aa6fb1SDanilo Krummrich     ///
135*05aa6fb1SDanilo Krummrich     /// This allows safe access to an `sg_table` that is managed elsewhere (for example, in C code).
136*05aa6fb1SDanilo Krummrich     ///
137*05aa6fb1SDanilo Krummrich     /// # Safety
138*05aa6fb1SDanilo Krummrich     ///
139*05aa6fb1SDanilo Krummrich     /// Callers must ensure that:
140*05aa6fb1SDanilo Krummrich     ///
141*05aa6fb1SDanilo Krummrich     /// - the `struct sg_table` pointed to by `ptr` is valid for the entire lifetime of `'a`,
142*05aa6fb1SDanilo Krummrich     /// - the data behind `ptr` is not modified concurrently for the duration of `'a`.
143*05aa6fb1SDanilo Krummrich     #[inline]
144*05aa6fb1SDanilo Krummrich     pub unsafe fn from_raw<'a>(ptr: *mut bindings::sg_table) -> &'a Self {
145*05aa6fb1SDanilo Krummrich         // SAFETY: The safety requirements of this function guarantee that `ptr` is a valid pointer
146*05aa6fb1SDanilo Krummrich         // to a `struct sg_table` for the duration of `'a`.
147*05aa6fb1SDanilo Krummrich         unsafe { &*ptr.cast() }
148*05aa6fb1SDanilo Krummrich     }
149*05aa6fb1SDanilo Krummrich 
150*05aa6fb1SDanilo Krummrich     #[inline]
151*05aa6fb1SDanilo Krummrich     fn as_raw(&self) -> *mut bindings::sg_table {
152*05aa6fb1SDanilo Krummrich         self.inner.0.get()
153*05aa6fb1SDanilo Krummrich     }
154*05aa6fb1SDanilo Krummrich 
155*05aa6fb1SDanilo Krummrich     /// Returns an [`SGTableIter`] bound to the lifetime of `self`.
156*05aa6fb1SDanilo Krummrich     pub fn iter(&self) -> SGTableIter<'_> {
157*05aa6fb1SDanilo Krummrich         // SAFETY: `self.as_raw()` is a valid pointer to a `struct sg_table`.
158*05aa6fb1SDanilo Krummrich         let nents = unsafe { (*self.as_raw()).nents };
159*05aa6fb1SDanilo Krummrich 
160*05aa6fb1SDanilo Krummrich         let pos = if nents > 0 {
161*05aa6fb1SDanilo Krummrich             // SAFETY: `self.as_raw()` is a valid pointer to a `struct sg_table`.
162*05aa6fb1SDanilo Krummrich             let ptr = unsafe { (*self.as_raw()).sgl };
163*05aa6fb1SDanilo Krummrich 
164*05aa6fb1SDanilo Krummrich             // SAFETY: `ptr` is guaranteed to be a valid pointer to a `struct scatterlist`.
165*05aa6fb1SDanilo Krummrich             Some(unsafe { SGEntry::from_raw(ptr) })
166*05aa6fb1SDanilo Krummrich         } else {
167*05aa6fb1SDanilo Krummrich             None
168*05aa6fb1SDanilo Krummrich         };
169*05aa6fb1SDanilo Krummrich 
170*05aa6fb1SDanilo Krummrich         SGTableIter { pos, nents }
171*05aa6fb1SDanilo Krummrich     }
172*05aa6fb1SDanilo Krummrich }
173*05aa6fb1SDanilo Krummrich 
174*05aa6fb1SDanilo Krummrich /// Represents the DMA mapping state of a `struct sg_table`.
175*05aa6fb1SDanilo Krummrich ///
176*05aa6fb1SDanilo Krummrich /// This is used as an inner type of [`Owned`] to manage the DMA mapping lifecycle.
177*05aa6fb1SDanilo Krummrich ///
178*05aa6fb1SDanilo Krummrich /// # Invariants
179*05aa6fb1SDanilo Krummrich ///
180*05aa6fb1SDanilo Krummrich /// - `sgt` is a valid pointer to a `struct sg_table` for the entire lifetime of the
181*05aa6fb1SDanilo Krummrich ///   [`DmaMappedSgt`].
182*05aa6fb1SDanilo Krummrich /// - `sgt` is always DMA mapped.
183*05aa6fb1SDanilo Krummrich struct DmaMappedSgt {
184*05aa6fb1SDanilo Krummrich     sgt: NonNull<bindings::sg_table>,
185*05aa6fb1SDanilo Krummrich     dev: ARef<Device>,
186*05aa6fb1SDanilo Krummrich     dir: dma::DataDirection,
187*05aa6fb1SDanilo Krummrich }
188*05aa6fb1SDanilo Krummrich 
189*05aa6fb1SDanilo Krummrich // SAFETY: `DmaMappedSgt` can be sent to any task.
190*05aa6fb1SDanilo Krummrich unsafe impl Send for DmaMappedSgt {}
191*05aa6fb1SDanilo Krummrich 
192*05aa6fb1SDanilo Krummrich // SAFETY: `DmaMappedSgt` has no interior mutability and can be accessed concurrently.
193*05aa6fb1SDanilo Krummrich unsafe impl Sync for DmaMappedSgt {}
194*05aa6fb1SDanilo Krummrich 
195*05aa6fb1SDanilo Krummrich impl DmaMappedSgt {
196*05aa6fb1SDanilo Krummrich     /// # Safety
197*05aa6fb1SDanilo Krummrich     ///
198*05aa6fb1SDanilo Krummrich     /// - `sgt` must be a valid pointer to a `struct sg_table` for the entire lifetime of the
199*05aa6fb1SDanilo Krummrich     ///   returned [`DmaMappedSgt`].
200*05aa6fb1SDanilo Krummrich     /// - The caller must guarantee that `sgt` remains DMA mapped for the entire lifetime of
201*05aa6fb1SDanilo Krummrich     ///   [`DmaMappedSgt`].
202*05aa6fb1SDanilo Krummrich     unsafe fn new(
203*05aa6fb1SDanilo Krummrich         sgt: NonNull<bindings::sg_table>,
204*05aa6fb1SDanilo Krummrich         dev: &Device<Bound>,
205*05aa6fb1SDanilo Krummrich         dir: dma::DataDirection,
206*05aa6fb1SDanilo Krummrich     ) -> Result<Self> {
207*05aa6fb1SDanilo Krummrich         // SAFETY:
208*05aa6fb1SDanilo Krummrich         // - `dev.as_raw()` is a valid pointer to a `struct device`, which is guaranteed to be
209*05aa6fb1SDanilo Krummrich         //   bound to a driver for the duration of this call.
210*05aa6fb1SDanilo Krummrich         // - `sgt` is a valid pointer to a `struct sg_table`.
211*05aa6fb1SDanilo Krummrich         error::to_result(unsafe {
212*05aa6fb1SDanilo Krummrich             bindings::dma_map_sgtable(dev.as_raw(), sgt.as_ptr(), dir.into(), 0)
213*05aa6fb1SDanilo Krummrich         })?;
214*05aa6fb1SDanilo Krummrich 
215*05aa6fb1SDanilo Krummrich         // INVARIANT: By the safety requirements of this function it is guaranteed that `sgt` is
216*05aa6fb1SDanilo Krummrich         // valid for the entire lifetime of this object instance.
217*05aa6fb1SDanilo Krummrich         Ok(Self {
218*05aa6fb1SDanilo Krummrich             sgt,
219*05aa6fb1SDanilo Krummrich             dev: dev.into(),
220*05aa6fb1SDanilo Krummrich             dir,
221*05aa6fb1SDanilo Krummrich         })
222*05aa6fb1SDanilo Krummrich     }
223*05aa6fb1SDanilo Krummrich }
224*05aa6fb1SDanilo Krummrich 
225*05aa6fb1SDanilo Krummrich impl Drop for DmaMappedSgt {
226*05aa6fb1SDanilo Krummrich     #[inline]
227*05aa6fb1SDanilo Krummrich     fn drop(&mut self) {
228*05aa6fb1SDanilo Krummrich         // SAFETY:
229*05aa6fb1SDanilo Krummrich         // - `self.dev.as_raw()` is a pointer to a valid `struct device`.
230*05aa6fb1SDanilo Krummrich         // - `self.dev` is the same device the mapping has been created for in `Self::new()`.
231*05aa6fb1SDanilo Krummrich         // - `self.sgt.as_ptr()` is a valid pointer to a `struct sg_table` by the type invariants
232*05aa6fb1SDanilo Krummrich         //   of `Self`.
233*05aa6fb1SDanilo Krummrich         // - `self.dir` is the same `dma::DataDirection` the mapping has been created with in
234*05aa6fb1SDanilo Krummrich         //   `Self::new()`.
235*05aa6fb1SDanilo Krummrich         unsafe {
236*05aa6fb1SDanilo Krummrich             bindings::dma_unmap_sgtable(self.dev.as_raw(), self.sgt.as_ptr(), self.dir.into(), 0)
237*05aa6fb1SDanilo Krummrich         };
238*05aa6fb1SDanilo Krummrich     }
239*05aa6fb1SDanilo Krummrich }
240*05aa6fb1SDanilo Krummrich 
241*05aa6fb1SDanilo Krummrich /// A transparent wrapper around a `struct sg_table`.
242*05aa6fb1SDanilo Krummrich ///
243*05aa6fb1SDanilo Krummrich /// While we could also create the `struct sg_table` in the constructor of [`Owned`], we can't tear
244*05aa6fb1SDanilo Krummrich /// down the `struct sg_table` in [`Owned::drop`]; the drop order in [`Owned`] matters.
245*05aa6fb1SDanilo Krummrich #[repr(transparent)]
246*05aa6fb1SDanilo Krummrich struct RawSGTable(Opaque<bindings::sg_table>);
247*05aa6fb1SDanilo Krummrich 
248*05aa6fb1SDanilo Krummrich // SAFETY: `RawSGTable` can be sent to any task.
249*05aa6fb1SDanilo Krummrich unsafe impl Send for RawSGTable {}
250*05aa6fb1SDanilo Krummrich 
251*05aa6fb1SDanilo Krummrich // SAFETY: `RawSGTable` has no interior mutability and can be accessed concurrently.
252*05aa6fb1SDanilo Krummrich unsafe impl Sync for RawSGTable {}
253*05aa6fb1SDanilo Krummrich 
254*05aa6fb1SDanilo Krummrich impl RawSGTable {
255*05aa6fb1SDanilo Krummrich     /// # Safety
256*05aa6fb1SDanilo Krummrich     ///
257*05aa6fb1SDanilo Krummrich     /// - `pages` must be a slice of valid `struct page *`.
258*05aa6fb1SDanilo Krummrich     /// - The pages pointed to by `pages` must remain valid for the entire lifetime of the returned
259*05aa6fb1SDanilo Krummrich     ///   [`RawSGTable`].
260*05aa6fb1SDanilo Krummrich     unsafe fn new(
261*05aa6fb1SDanilo Krummrich         pages: &mut [*mut bindings::page],
262*05aa6fb1SDanilo Krummrich         size: usize,
263*05aa6fb1SDanilo Krummrich         max_segment: u32,
264*05aa6fb1SDanilo Krummrich         flags: alloc::Flags,
265*05aa6fb1SDanilo Krummrich     ) -> Result<Self> {
266*05aa6fb1SDanilo Krummrich         // `sg_alloc_table_from_pages_segment()` expects at least one page, otherwise it
267*05aa6fb1SDanilo Krummrich         // produces a NPE.
268*05aa6fb1SDanilo Krummrich         if pages.is_empty() {
269*05aa6fb1SDanilo Krummrich             return Err(EINVAL);
270*05aa6fb1SDanilo Krummrich         }
271*05aa6fb1SDanilo Krummrich 
272*05aa6fb1SDanilo Krummrich         let sgt = Opaque::zeroed();
273*05aa6fb1SDanilo Krummrich         // SAFETY:
274*05aa6fb1SDanilo Krummrich         // - `sgt.get()` is a valid pointer to uninitialized memory.
275*05aa6fb1SDanilo Krummrich         // - As by the check above, `pages` is not empty.
276*05aa6fb1SDanilo Krummrich         error::to_result(unsafe {
277*05aa6fb1SDanilo Krummrich             bindings::sg_alloc_table_from_pages_segment(
278*05aa6fb1SDanilo Krummrich                 sgt.get(),
279*05aa6fb1SDanilo Krummrich                 pages.as_mut_ptr(),
280*05aa6fb1SDanilo Krummrich                 pages.len().try_into()?,
281*05aa6fb1SDanilo Krummrich                 0,
282*05aa6fb1SDanilo Krummrich                 size,
283*05aa6fb1SDanilo Krummrich                 max_segment,
284*05aa6fb1SDanilo Krummrich                 flags.as_raw(),
285*05aa6fb1SDanilo Krummrich             )
286*05aa6fb1SDanilo Krummrich         })?;
287*05aa6fb1SDanilo Krummrich 
288*05aa6fb1SDanilo Krummrich         Ok(Self(sgt))
289*05aa6fb1SDanilo Krummrich     }
290*05aa6fb1SDanilo Krummrich 
291*05aa6fb1SDanilo Krummrich     #[inline]
292*05aa6fb1SDanilo Krummrich     fn as_raw(&self) -> *mut bindings::sg_table {
293*05aa6fb1SDanilo Krummrich         self.0.get()
294*05aa6fb1SDanilo Krummrich     }
295*05aa6fb1SDanilo Krummrich }
296*05aa6fb1SDanilo Krummrich 
297*05aa6fb1SDanilo Krummrich impl Drop for RawSGTable {
298*05aa6fb1SDanilo Krummrich     #[inline]
299*05aa6fb1SDanilo Krummrich     fn drop(&mut self) {
300*05aa6fb1SDanilo Krummrich         // SAFETY: `sgt` is a valid and initialized `struct sg_table`.
301*05aa6fb1SDanilo Krummrich         unsafe { bindings::sg_free_table(self.0.get()) };
302*05aa6fb1SDanilo Krummrich     }
303*05aa6fb1SDanilo Krummrich }
304*05aa6fb1SDanilo Krummrich 
305*05aa6fb1SDanilo Krummrich /// The [`Owned`] generic type of an [`SGTable`].
306*05aa6fb1SDanilo Krummrich ///
307*05aa6fb1SDanilo Krummrich /// A [`SGTable<Owned>`] signifies that the [`SGTable`] owns all associated resources:
308*05aa6fb1SDanilo Krummrich ///
309*05aa6fb1SDanilo Krummrich /// - The backing memory pages.
310*05aa6fb1SDanilo Krummrich /// - The `struct sg_table` allocation (`sgt`).
311*05aa6fb1SDanilo Krummrich /// - The DMA mapping, managed through a [`Devres`]-managed `DmaMappedSgt`.
312*05aa6fb1SDanilo Krummrich ///
313*05aa6fb1SDanilo Krummrich /// Users interact with this type through the [`SGTable`] handle and do not need to manage
314*05aa6fb1SDanilo Krummrich /// [`Owned`] directly.
315*05aa6fb1SDanilo Krummrich #[pin_data]
316*05aa6fb1SDanilo Krummrich pub struct Owned<P> {
317*05aa6fb1SDanilo Krummrich     // Note: The drop order is relevant; we first have to unmap the `struct sg_table`, then free the
318*05aa6fb1SDanilo Krummrich     // `struct sg_table` and finally free the backing pages.
319*05aa6fb1SDanilo Krummrich     #[pin]
320*05aa6fb1SDanilo Krummrich     dma: Devres<DmaMappedSgt>,
321*05aa6fb1SDanilo Krummrich     sgt: RawSGTable,
322*05aa6fb1SDanilo Krummrich     _pages: P,
323*05aa6fb1SDanilo Krummrich }
324*05aa6fb1SDanilo Krummrich 
325*05aa6fb1SDanilo Krummrich // SAFETY: `Owned` can be sent to any task if `P` can be send to any task.
326*05aa6fb1SDanilo Krummrich unsafe impl<P: Send> Send for Owned<P> {}
327*05aa6fb1SDanilo Krummrich 
328*05aa6fb1SDanilo Krummrich // SAFETY: `Owned` has no interior mutability and can be accessed concurrently if `P` can be
329*05aa6fb1SDanilo Krummrich // accessed concurrently.
330*05aa6fb1SDanilo Krummrich unsafe impl<P: Sync> Sync for Owned<P> {}
331*05aa6fb1SDanilo Krummrich 
332*05aa6fb1SDanilo Krummrich impl<P> Owned<P>
333*05aa6fb1SDanilo Krummrich where
334*05aa6fb1SDanilo Krummrich     for<'a> P: page::AsPageIter<Iter<'a> = VmallocPageIter<'a>> + 'static,
335*05aa6fb1SDanilo Krummrich {
336*05aa6fb1SDanilo Krummrich     fn new(
337*05aa6fb1SDanilo Krummrich         dev: &Device<Bound>,
338*05aa6fb1SDanilo Krummrich         mut pages: P,
339*05aa6fb1SDanilo Krummrich         dir: dma::DataDirection,
340*05aa6fb1SDanilo Krummrich         flags: alloc::Flags,
341*05aa6fb1SDanilo Krummrich     ) -> Result<impl PinInit<Self, Error> + '_> {
342*05aa6fb1SDanilo Krummrich         let page_iter = pages.page_iter();
343*05aa6fb1SDanilo Krummrich         let size = page_iter.size();
344*05aa6fb1SDanilo Krummrich 
345*05aa6fb1SDanilo Krummrich         let mut page_vec: KVec<*mut bindings::page> =
346*05aa6fb1SDanilo Krummrich             KVec::with_capacity(page_iter.page_count(), flags)?;
347*05aa6fb1SDanilo Krummrich 
348*05aa6fb1SDanilo Krummrich         for page in page_iter {
349*05aa6fb1SDanilo Krummrich             page_vec.push(page.as_ptr(), flags)?;
350*05aa6fb1SDanilo Krummrich         }
351*05aa6fb1SDanilo Krummrich 
352*05aa6fb1SDanilo Krummrich         // `dma_max_mapping_size` returns `size_t`, but `sg_alloc_table_from_pages_segment()` takes
353*05aa6fb1SDanilo Krummrich         // an `unsigned int`.
354*05aa6fb1SDanilo Krummrich         //
355*05aa6fb1SDanilo Krummrich         // SAFETY: `dev.as_raw()` is a valid pointer to a `struct device`.
356*05aa6fb1SDanilo Krummrich         let max_segment = match unsafe { bindings::dma_max_mapping_size(dev.as_raw()) } {
357*05aa6fb1SDanilo Krummrich             0 => u32::MAX,
358*05aa6fb1SDanilo Krummrich             max_segment => u32::try_from(max_segment).unwrap_or(u32::MAX),
359*05aa6fb1SDanilo Krummrich         };
360*05aa6fb1SDanilo Krummrich 
361*05aa6fb1SDanilo Krummrich         Ok(try_pin_init!(&this in Self {
362*05aa6fb1SDanilo Krummrich             // SAFETY:
363*05aa6fb1SDanilo Krummrich             // - `page_vec` is a `KVec` of valid `struct page *` obtained from `pages`.
364*05aa6fb1SDanilo Krummrich             // - The pages contained in `pages` remain valid for the entire lifetime of the
365*05aa6fb1SDanilo Krummrich             //   `RawSGTable`.
366*05aa6fb1SDanilo Krummrich             sgt: unsafe { RawSGTable::new(&mut page_vec, size, max_segment, flags) }?,
367*05aa6fb1SDanilo Krummrich             dma <- {
368*05aa6fb1SDanilo Krummrich                 // SAFETY: `this` is a valid pointer to uninitialized memory.
369*05aa6fb1SDanilo Krummrich                 let sgt = unsafe { &raw mut (*this.as_ptr()).sgt }.cast();
370*05aa6fb1SDanilo Krummrich 
371*05aa6fb1SDanilo Krummrich                 // SAFETY: `sgt` is guaranteed to be non-null.
372*05aa6fb1SDanilo Krummrich                 let sgt = unsafe { NonNull::new_unchecked(sgt) };
373*05aa6fb1SDanilo Krummrich 
374*05aa6fb1SDanilo Krummrich                 // SAFETY:
375*05aa6fb1SDanilo Krummrich                 // - It is guaranteed that the object returned by `DmaMappedSgt::new` won't out-live
376*05aa6fb1SDanilo Krummrich                 //   `sgt`.
377*05aa6fb1SDanilo Krummrich                 // - `sgt` is never DMA unmapped manually.
378*05aa6fb1SDanilo Krummrich                 Devres::new(dev, unsafe { DmaMappedSgt::new(sgt, dev, dir) })
379*05aa6fb1SDanilo Krummrich             },
380*05aa6fb1SDanilo Krummrich             _pages: pages,
381*05aa6fb1SDanilo Krummrich         }))
382*05aa6fb1SDanilo Krummrich     }
383*05aa6fb1SDanilo Krummrich }
384*05aa6fb1SDanilo Krummrich 
385*05aa6fb1SDanilo Krummrich impl<P> SGTable<Owned<P>>
386*05aa6fb1SDanilo Krummrich where
387*05aa6fb1SDanilo Krummrich     for<'a> P: page::AsPageIter<Iter<'a> = VmallocPageIter<'a>> + 'static,
388*05aa6fb1SDanilo Krummrich {
389*05aa6fb1SDanilo Krummrich     /// Allocates a new scatter-gather table from the given pages and maps it for DMA.
390*05aa6fb1SDanilo Krummrich     ///
391*05aa6fb1SDanilo Krummrich     /// This constructor creates a new [`SGTable<Owned>`] that takes ownership of `P`.
392*05aa6fb1SDanilo Krummrich     /// It allocates a `struct sg_table`, populates it with entries corresponding to the physical
393*05aa6fb1SDanilo Krummrich     /// pages of `P`, and maps the table for DMA with the specified [`Device`] and
394*05aa6fb1SDanilo Krummrich     /// [`dma::DataDirection`].
395*05aa6fb1SDanilo Krummrich     ///
396*05aa6fb1SDanilo Krummrich     /// The DMA mapping is managed through [`Devres`], ensuring that the DMA mapping is unmapped
397*05aa6fb1SDanilo Krummrich     /// once the associated [`Device`] is unbound, or when the [`SGTable<Owned>`] is dropped.
398*05aa6fb1SDanilo Krummrich     ///
399*05aa6fb1SDanilo Krummrich     /// # Parameters
400*05aa6fb1SDanilo Krummrich     ///
401*05aa6fb1SDanilo Krummrich     /// * `dev`: The [`Device`] that will be performing the DMA.
402*05aa6fb1SDanilo Krummrich     /// * `pages`: The entity providing the backing pages. It must implement [`page::AsPageIter`].
403*05aa6fb1SDanilo Krummrich     ///   The ownership of this entity is moved into the new [`SGTable<Owned>`].
404*05aa6fb1SDanilo Krummrich     /// * `dir`: The [`dma::DataDirection`] of the DMA transfer.
405*05aa6fb1SDanilo Krummrich     /// * `flags`: Allocation flags for internal allocations (e.g., [`GFP_KERNEL`]).
406*05aa6fb1SDanilo Krummrich     ///
407*05aa6fb1SDanilo Krummrich     /// # Examples
408*05aa6fb1SDanilo Krummrich     ///
409*05aa6fb1SDanilo Krummrich     /// ```
410*05aa6fb1SDanilo Krummrich     /// use kernel::{
411*05aa6fb1SDanilo Krummrich     ///     device::{Bound, Device},
412*05aa6fb1SDanilo Krummrich     ///     dma, page,
413*05aa6fb1SDanilo Krummrich     ///     prelude::*,
414*05aa6fb1SDanilo Krummrich     ///     scatterlist::{SGTable, Owned},
415*05aa6fb1SDanilo Krummrich     /// };
416*05aa6fb1SDanilo Krummrich     ///
417*05aa6fb1SDanilo Krummrich     /// fn test(dev: &Device<Bound>) -> Result {
418*05aa6fb1SDanilo Krummrich     ///     let size = 4 * page::PAGE_SIZE;
419*05aa6fb1SDanilo Krummrich     ///     let pages = VVec::<u8>::with_capacity(size, GFP_KERNEL)?;
420*05aa6fb1SDanilo Krummrich     ///
421*05aa6fb1SDanilo Krummrich     ///     let sgt = KBox::pin_init(SGTable::new(
422*05aa6fb1SDanilo Krummrich     ///         dev,
423*05aa6fb1SDanilo Krummrich     ///         pages,
424*05aa6fb1SDanilo Krummrich     ///         dma::DataDirection::ToDevice,
425*05aa6fb1SDanilo Krummrich     ///         GFP_KERNEL,
426*05aa6fb1SDanilo Krummrich     ///     ), GFP_KERNEL)?;
427*05aa6fb1SDanilo Krummrich     ///
428*05aa6fb1SDanilo Krummrich     ///     Ok(())
429*05aa6fb1SDanilo Krummrich     /// }
430*05aa6fb1SDanilo Krummrich     /// ```
431*05aa6fb1SDanilo Krummrich     pub fn new(
432*05aa6fb1SDanilo Krummrich         dev: &Device<Bound>,
433*05aa6fb1SDanilo Krummrich         pages: P,
434*05aa6fb1SDanilo Krummrich         dir: dma::DataDirection,
435*05aa6fb1SDanilo Krummrich         flags: alloc::Flags,
436*05aa6fb1SDanilo Krummrich     ) -> impl PinInit<Self, Error> + '_ {
437*05aa6fb1SDanilo Krummrich         try_pin_init!(Self {
438*05aa6fb1SDanilo Krummrich             inner <- Owned::new(dev, pages, dir, flags)?
439*05aa6fb1SDanilo Krummrich         })
440*05aa6fb1SDanilo Krummrich     }
441*05aa6fb1SDanilo Krummrich }
442*05aa6fb1SDanilo Krummrich 
443*05aa6fb1SDanilo Krummrich impl<P> Deref for SGTable<Owned<P>> {
444*05aa6fb1SDanilo Krummrich     type Target = SGTable;
445*05aa6fb1SDanilo Krummrich 
446*05aa6fb1SDanilo Krummrich     #[inline]
447*05aa6fb1SDanilo Krummrich     fn deref(&self) -> &Self::Target {
448*05aa6fb1SDanilo Krummrich         // SAFETY:
449*05aa6fb1SDanilo Krummrich         // - `self.inner.sgt.as_raw()` is a valid pointer to a `struct sg_table` for the entire
450*05aa6fb1SDanilo Krummrich         //   lifetime of `self`.
451*05aa6fb1SDanilo Krummrich         // - The backing `struct sg_table` is not modified for the entire lifetime of `self`.
452*05aa6fb1SDanilo Krummrich         unsafe { SGTable::from_raw(self.inner.sgt.as_raw()) }
453*05aa6fb1SDanilo Krummrich     }
454*05aa6fb1SDanilo Krummrich }
455*05aa6fb1SDanilo Krummrich 
456*05aa6fb1SDanilo Krummrich mod private {
457*05aa6fb1SDanilo Krummrich     pub trait Sealed {}
458*05aa6fb1SDanilo Krummrich 
459*05aa6fb1SDanilo Krummrich     impl Sealed for super::Borrowed {}
460*05aa6fb1SDanilo Krummrich     impl<P> Sealed for super::Owned<P> {}
461*05aa6fb1SDanilo Krummrich }
462*05aa6fb1SDanilo Krummrich 
463*05aa6fb1SDanilo Krummrich /// An [`Iterator`] over the DMA mapped [`SGEntry`] items of an [`SGTable`].
464*05aa6fb1SDanilo Krummrich ///
465*05aa6fb1SDanilo Krummrich /// Note that the existence of an [`SGTableIter`] does not guarantee that the [`SGEntry`] items
466*05aa6fb1SDanilo Krummrich /// actually remain DMA mapped; they are prone to be unmapped on device unbind.
467*05aa6fb1SDanilo Krummrich pub struct SGTableIter<'a> {
468*05aa6fb1SDanilo Krummrich     pos: Option<&'a SGEntry>,
469*05aa6fb1SDanilo Krummrich     /// The number of DMA mapped entries in a `struct sg_table`.
470*05aa6fb1SDanilo Krummrich     nents: c_uint,
471*05aa6fb1SDanilo Krummrich }
472*05aa6fb1SDanilo Krummrich 
473*05aa6fb1SDanilo Krummrich impl<'a> Iterator for SGTableIter<'a> {
474*05aa6fb1SDanilo Krummrich     type Item = &'a SGEntry;
475*05aa6fb1SDanilo Krummrich 
476*05aa6fb1SDanilo Krummrich     fn next(&mut self) -> Option<Self::Item> {
477*05aa6fb1SDanilo Krummrich         let entry = self.pos?;
478*05aa6fb1SDanilo Krummrich         self.nents = self.nents.saturating_sub(1);
479*05aa6fb1SDanilo Krummrich 
480*05aa6fb1SDanilo Krummrich         // SAFETY: `entry.as_raw()` is a valid pointer to a `struct scatterlist`.
481*05aa6fb1SDanilo Krummrich         let next = unsafe { bindings::sg_next(entry.as_raw()) };
482*05aa6fb1SDanilo Krummrich 
483*05aa6fb1SDanilo Krummrich         self.pos = (!next.is_null() && self.nents > 0).then(|| {
484*05aa6fb1SDanilo Krummrich             // SAFETY: If `next` is not NULL, `sg_next()` guarantees to return a valid pointer to
485*05aa6fb1SDanilo Krummrich             // the next `struct scatterlist`.
486*05aa6fb1SDanilo Krummrich             unsafe { SGEntry::from_raw(next) }
487*05aa6fb1SDanilo Krummrich         });
488*05aa6fb1SDanilo Krummrich 
489*05aa6fb1SDanilo Krummrich         Some(entry)
490*05aa6fb1SDanilo Krummrich     }
491*05aa6fb1SDanilo Krummrich }
492