Skip to content

Commit a6d63d6

Browse files
Lyudejannau
authored andcommitted
rust: drm: gem: Introduce shmem::SGTable
Currently we expose the ability to retrieve an SGTable for an shmem gem object using gem::shmem::Object::<T>::sg_table(). However, this only gives us a borrowed reference. This being said - retrieving an SGTable is a fallible operation, and as such it's reasonable that a driver may want to hold onto an SGTable for longer then a reference would allow in order to avoid having to deal with fallibility every time they want to access the SGTable. One such driver with this usecase is the Asahi driver. So to support this, let's introduce shmem::SGTable - which both holds a pointer to the SGTable and a reference to its respective GEM object in order to keep the GEM object alive for as long as the shmem::SGTable. The type can be used identically to a normal SGTable. Signed-off-by: Lyude Paul <lyude@redhat.com>
1 parent 49a1a71 commit a6d63d6

1 file changed

Lines changed: 50 additions & 0 deletions

File tree

rust/kernel/drm/gem/shmem.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,25 @@ impl<T: DriverObject> Object<T> {
173173
// pointer to a scatterlist
174174
Ok(unsafe { scatterlist::SGTable::from_raw(sgt) })
175175
}
176+
177+
/// Creates (if necessary) and returns an owned reference to a scatter-gather table of DMA pages
178+
/// for this object.
179+
///
180+
/// This is the same as [`sg_table`](Self::sg_table), except that it instead returns an
181+
/// [`shmem::SGTable`] which holds a reference to the associated gem object, instead of a
182+
/// reference to an [`scatterlist::SGTable`].
183+
///
184+
/// This will pin the object in memory.
185+
///
186+
/// [`shmem::SGTable`]: SGTable
187+
pub fn owned_sg_table(&self) -> Result<SGTable<T>> {
188+
Ok(SGTable {
189+
sgt: self.sg_table()?.into(),
190+
// INVARIANT: We take an owned refcount to `self` here, ensuring that `sgt` remains
191+
// valid for as long as this `SGTable`.
192+
_owner: self.into(),
193+
})
194+
}
176195
}
177196

178197
impl<T: DriverObject> Deref for Object<T> {
@@ -223,3 +242,34 @@ impl<T: DriverObject> driver::AllocImpl for Object<T> {
223242
dumb_map_offset: None,
224243
};
225244
}
245+
246+
/// An owned reference to a scatter-gather table of DMA address spans for a GEM shmem object.
247+
///
248+
/// This object holds an owned reference to the underlying GEM shmem object, ensuring that the
249+
/// [`scatterlist::SGTable`] referenced by this type remains valid for the lifetime of this object.
250+
///
251+
/// # Invariants
252+
///
253+
/// - `sgt` is kept alive by `_owner`, ensuring it remains valid for as long as `Self`.
254+
/// - `sgt` corresponds to the owned object in `_owner`.
255+
/// - This object is only exposed in situations where we know the underlying `SGTable` will not be
256+
/// modified for the lifetime of this object. Thus, it is safe to send/access this type across
257+
/// threads.
258+
pub struct SGTable<T: DriverObject> {
259+
sgt: NonNull<scatterlist::SGTable>,
260+
_owner: ARef<Object<T>>,
261+
}
262+
263+
// SAFETY: This object is thread-safe via our type invariants.
264+
unsafe impl<T: DriverObject> Send for SGTable<T> {}
265+
// SAFETY: This object is thread-safe via our type invariants.
266+
unsafe impl<T: DriverObject> Sync for SGTable<T> {}
267+
268+
impl<T: DriverObject> Deref for SGTable<T> {
269+
type Target = scatterlist::SGTable;
270+
271+
fn deref(&self) -> &Self::Target {
272+
// SAFETY: Creating an immutable reference to this is safe via our type invariants.
273+
unsafe { self.sgt.as_ref() }
274+
}
275+
}

0 commit comments

Comments
 (0)