From: Danilo Krummrich <dakr@kernel.org>
To: dakr@kernel.org, aliceryhl@google.com,
daniel.almeida@collabora.com, acourbot@nvidia.com,
ecourtney@nvidia.com, ojeda@kernel.org, boqun@kernel.org,
gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org,
a.hindborg@kernel.org, tmgross@umich.edu,
deborah.brouwer@collabora.com, boris.brezillon@collabora.com,
lyude@redhat.com
Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org,
nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org,
rust-for-linux@vger.kernel.org
Subject: [PATCH v5 08/19] rust: drm/gem: remove DeviceContext from shmem::Object
Date: Sun, 28 Jun 2026 16:53:28 +0200 [thread overview]
Message-ID: <20260628145406.2107056-9-dakr@kernel.org> (raw)
In-Reply-To: <20260628145406.2107056-1-dakr@kernel.org>
Now that AlwaysRefCounted is restricted to the Normal GEM Object
context, there is no use for instantiating Object<T, C> with a
non-Normal context. Remove the DeviceContext generic parameter from
shmem::Object and all associated types (VMap, VMapRef, VMapOwned,
DmaResvGuard, SGTableMap), simplifying the API.
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
---
rust/kernel/drm/gem/shmem.rs | 121 +++++++++++++++--------------------
1 file changed, 51 insertions(+), 70 deletions(-)
diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs
index cf8410e0f228..e0ef47352e88 100644
--- a/rust/kernel/drm/gem/shmem.rs
+++ b/rust/kernel/drm/gem/shmem.rs
@@ -20,9 +20,7 @@
driver,
gem,
private::Sealed,
- Device,
- DeviceContext,
- Normal, //
+ Device, //
},
error::{
from_err_ptr,
@@ -48,7 +46,6 @@
};
use core::{
ffi::c_void,
- marker::PhantomData,
mem::{
ManuallyDrop,
MaybeUninit, //
@@ -99,22 +96,20 @@ fn default() -> Self {
///
/// - `obj` contains a valid initialized `struct drm_gem_shmem_object` for the lifetime of this
/// object.
-/// - Any type invariants of `C` apply to the parent DRM device for this GEM object.
#[repr(C)]
#[pin_data]
-pub struct Object<T: DriverObject, C: DeviceContext = Normal> {
+pub struct Object<T: DriverObject> {
#[pin]
obj: Opaque<bindings::drm_gem_shmem_object>,
/// Parent object that owns this object's DMA reservation object.
parent_resv_obj: Option<ARef<Object<T>>>,
/// Devres object for unmapping any SGTable on driver-unbind.
- sgt_res: ManuallyDrop<SetOnce<Devres<SGTableMap<T, C>>>>,
+ sgt_res: ManuallyDrop<SetOnce<Devres<SGTableMap<T>>>>,
#[pin]
/// Lock for protecting initialization of `sgt_res`.
sgt_lock: Mutex<()>,
#[pin]
inner: T,
- _ctx: PhantomData<C>,
}
super::impl_aref_for_gem_obj! {
@@ -124,12 +119,12 @@ impl<T> for Object<T>
}
// SAFETY: All GEM objects are thread-safe.
-unsafe impl<T: DriverObject, C: DeviceContext> Send for Object<T, C> {}
+unsafe impl<T: DriverObject> Send for Object<T> {}
// SAFETY: All GEM objects are thread-safe.
-unsafe impl<T: DriverObject, C: DeviceContext> Sync for Object<T, C> {}
+unsafe impl<T: DriverObject> Sync for Object<T> {}
-impl<T: DriverObject, C: DeviceContext> Object<T, C> {
+impl<T: DriverObject> Object<T> {
/// `drm_gem_object_funcs` vtable suitable for GEM shmem objects.
const VTABLE: bindings::drm_gem_object_funcs = bindings::drm_gem_object_funcs {
free: Some(Self::free_callback),
@@ -157,7 +152,7 @@ fn as_raw_shmem(&self) -> *mut bindings::drm_gem_shmem_object {
}
/// Returns the `Device` that owns this GEM object.
- pub fn dev(&self) -> &Device<T::Driver, C> {
+ pub fn dev(&self) -> &Device<T::Driver> {
// SAFETY: `dev` will have been initialized in `Self::new()` by `drm_gem_shmem_init()`.
unsafe { Device::from_raw((*self.as_raw()).dev) }
}
@@ -171,8 +166,8 @@ extern "C" fn free_callback(obj: *mut bindings::drm_gem_object) {
// SAFETY:
// - We verified above that `obj` is valid, which makes `this` valid
- // - This function is set in AllocOps, so we know that `this` is contained within a
- // `Object<T, C>`
+ // - This function is set in AllocOps, so we know that `this` is contained within an
+ // `Object<T>`
let this = unsafe { container_of!(Opaque::cast_from(base), Self, obj) }.cast_mut();
// We need to drop `sgt_res` first, since doing so requires that the GEM object is still
@@ -193,7 +188,7 @@ extern "C" fn free_callback(obj: *mut bindings::drm_gem_object) {
}
/// Attempt to create a vmap from the gem object, and confirm the size of said vmap.
- fn make_vmap<'a, R, const SIZE: usize>(&'a self) -> Result<VMap<T, R, C, SIZE>>
+ fn make_vmap<'a, R, const SIZE: usize>(&'a self) -> Result<VMap<T, R, SIZE>>
where
R: Deref<Target = Self> + From<&'a Self>,
{
@@ -255,7 +250,7 @@ unsafe fn raw_vunmap(&self, mut map: bindings::iosys_map) {
/// Creates and returns a virtual kernel memory mapping for this object.
#[inline]
- pub fn vmap<const SIZE: usize>(&self) -> Result<VMapRef<'_, T, C, SIZE>> {
+ pub fn vmap<const SIZE: usize>(&self) -> Result<VMapRef<'_, T, SIZE>> {
self.make_vmap()
}
@@ -298,9 +293,7 @@ pub fn sg_table<'a>(
Ok(sgt_res.access(dev)?)
}
-}
-impl<T: DriverObject> Object<T> {
/// Create a new shmem-backed DRM object of the given size.
///
/// Additional config options can be specified using `config`.
@@ -317,7 +310,6 @@ pub fn new(
sgt_res: ManuallyDrop::new(SetOnce::new()),
sgt_lock <- new_mutex!(()),
inner <- T::new(dev, size, args),
- _ctx: PhantomData,
}),
GFP_KERNEL,
)?;
@@ -351,12 +343,12 @@ pub fn new(
/// Creates and returns an owned reference to a virtual kernel memory mapping for this object.
#[inline]
- pub fn owned_vmap<const SIZE: usize>(&self) -> Result<VMapOwned<T, Normal, SIZE>> {
+ pub fn owned_vmap<const SIZE: usize>(&self) -> Result<VMapOwned<T, SIZE>> {
self.make_vmap()
}
}
-impl<T: DriverObject, C: DeviceContext> Deref for Object<T, C> {
+impl<T: DriverObject> Deref for Object<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
@@ -364,15 +356,15 @@ fn deref(&self) -> &Self::Target {
}
}
-impl<T: DriverObject, C: DeviceContext> DerefMut for Object<T, C> {
+impl<T: DriverObject> DerefMut for Object<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
-impl<T: DriverObject, C: DeviceContext> Sealed for Object<T, C> {}
+impl<T: DriverObject> Sealed for Object<T> {}
-impl<T: DriverObject, C: DeviceContext> gem::IntoGEMObject for Object<T, C> {
+impl<T: DriverObject> gem::IntoGEMObject for Object<T> {
fn as_raw(&self) -> *mut bindings::drm_gem_object {
// SAFETY:
// - Our immutable reference is proof that this is safe to dereference.
@@ -391,7 +383,7 @@ unsafe fn from_raw<'a>(obj: *mut bindings::drm_gem_object) -> &'a Self {
}
}
-impl<T: DriverObject, C: DeviceContext> driver::AllocImpl for Object<T, C> {
+impl<T: DriverObject> driver::AllocImpl for Object<T> {
type Driver = T::Driver;
const ALLOC_OPS: driver::AllocOps = driver::AllocOps {
@@ -410,14 +402,11 @@ impl<T: DriverObject, C: DeviceContext> driver::AllocImpl for Object<T, C> {
/// When this is dropped, the `dma_resv` lock is dropped as well.
///
// TODO: This should be replace with a WwMutex equivalent once we have such bindings in the kernel.
-struct DmaResvGuard<'a, T: DriverObject, C: DeviceContext = Normal>(
- &'a Object<T, C>,
- NotThreadSafe,
-);
+struct DmaResvGuard<'a, T: DriverObject>(&'a Object<T>, NotThreadSafe);
-impl<'a, T: DriverObject, C: DeviceContext> DmaResvGuard<'a, T, C> {
+impl<'a, T: DriverObject> DmaResvGuard<'a, T> {
#[inline]
- fn new(obj: &'a Object<T, C>) -> Self {
+ fn new(obj: &'a Object<T>) -> Self {
// SAFETY: This lock is initialized throughout the lifetime of `object`.
unsafe { bindings::dma_resv_lock(obj.raw_dma_resv(), ptr::null_mut()) };
@@ -425,7 +414,7 @@ fn new(obj: &'a Object<T, C>) -> Self {
}
}
-impl<'a, T: DriverObject, C: DeviceContext> Drop for DmaResvGuard<'a, T, C> {
+impl<'a, T: DriverObject> Drop for DmaResvGuard<'a, T> {
#[inline]
fn drop(&mut self) {
// SAFETY: We are releasing the lock grabbed during the creation of this object.
@@ -439,40 +428,37 @@ fn drop(&mut self) {
///
/// - The size of `owner` is >= SIZE.
/// - The memory pointed to by `addr` remains valid at least until this object is dropped.
-pub struct VMap<D, R, C = Normal, const SIZE: usize = 0>
+pub struct VMap<D, R, const SIZE: usize = 0>
where
D: DriverObject,
- C: DeviceContext,
- R: Deref<Target = Object<D, C>>,
+ R: Deref<Target = Object<D>>,
{
addr: *mut c_void,
owner: R,
}
/// An alias type for a reference to a shmem-based GEM object's VMap.
-pub type VMapRef<'a, D, C, const SIZE: usize = 0> = VMap<D, &'a Object<D, C>, C, SIZE>;
+pub type VMapRef<'a, D, const SIZE: usize = 0> = VMap<D, &'a Object<D>, SIZE>;
/// An alias type for an owned reference to a shmem-based GEM object's VMap.
-pub type VMapOwned<D, C, const SIZE: usize = 0> = VMap<D, ARef<Object<D, C>>, C, SIZE>;
+pub type VMapOwned<D, const SIZE: usize = 0> = VMap<D, ARef<Object<D>>, SIZE>;
-impl<D, R, C, const SIZE: usize> VMap<D, R, C, SIZE>
+impl<D, R, const SIZE: usize> VMap<D, R, SIZE>
where
D: DriverObject,
- C: DeviceContext,
- R: Deref<Target = Object<D, C>>,
+ R: Deref<Target = Object<D>>,
{
/// Borrows a reference to the object that owns this virtual mapping.
#[inline]
- pub fn owner(&self) -> &Object<D, C> {
+ pub fn owner(&self) -> &Object<D> {
&self.owner
}
}
-impl<D, R, C, const SIZE: usize> Drop for VMap<D, R, C, SIZE>
+impl<D, R, const SIZE: usize> Drop for VMap<D, R, SIZE>
where
D: DriverObject,
- C: DeviceContext,
- R: Deref<Target = Object<D, C>>,
+ R: Deref<Target = Object<D>>,
{
#[inline]
fn drop(&mut self) {
@@ -491,29 +477,26 @@ fn drop(&mut self) {
// SAFETY: `addr` points to a valid memory address for as long as `owner` exists, meaning that so
// long as `owner` is `Send` so is `VMap`.
-unsafe impl<D, R, C, const SIZE: usize> Send for VMap<D, R, C, SIZE>
+unsafe impl<D, R, const SIZE: usize> Send for VMap<D, R, SIZE>
where
D: DriverObject,
- C: DeviceContext,
- R: Deref<Target = Object<D, C>> + Send,
+ R: Deref<Target = Object<D>> + Send,
{
}
// SAFETY: `addr` points to a valid memory address for as long as `owner` exists, meaning that so
// long as `owner` is `Sync` so is `VMap`.
-unsafe impl<D, R, C, const SIZE: usize> Sync for VMap<D, R, C, SIZE>
+unsafe impl<D, R, const SIZE: usize> Sync for VMap<D, R, SIZE>
where
D: DriverObject,
- C: DeviceContext,
- R: Deref<Target = Object<D, C>> + Sync,
+ R: Deref<Target = Object<D>> + Sync,
{
}
-impl<D, R, C, const SIZE: usize> Io for VMap<D, R, C, SIZE>
+impl<D, R, const SIZE: usize> Io for VMap<D, R, SIZE>
where
D: DriverObject,
- C: DeviceContext,
- R: Deref<Target = Object<D, C>>,
+ R: Deref<Target = Object<D>>,
{
#[inline]
fn addr(&self) -> usize {
@@ -526,22 +509,20 @@ fn maxsize(&self) -> usize {
}
}
-impl<D, R, C, const SIZE: usize> IoKnownSize for VMap<D, R, C, SIZE>
+impl<D, R, const SIZE: usize> IoKnownSize for VMap<D, R, SIZE>
where
D: DriverObject,
- C: DeviceContext,
- R: Deref<Target = Object<D, C>>,
+ R: Deref<Target = Object<D>>,
{
const MIN_SIZE: usize = SIZE;
}
macro_rules! impl_vmap_io_capable {
($ty:ty) => {
- impl<D, R, C, const SIZE: usize> IoCapable<$ty> for VMap<D, R, C, SIZE>
+ impl<D, R, const SIZE: usize> IoCapable<$ty> for VMap<D, R, SIZE>
where
D: DriverObject,
- C: DeviceContext,
- R: Deref<Target = Object<D, C>>,
+ R: Deref<Target = Object<D>>,
{
#[inline]
unsafe fn io_read(&self, address: usize) -> $ty {
@@ -584,11 +565,11 @@ unsafe fn io_write(&self, value: $ty, address: usize) {
/// [`SGTable`].
///
/// [`SGTable`]: scatterlist::SGTable
-pub struct SGTableMap<T: DriverObject, C: DeviceContext> {
- obj: NonNull<Object<T, C>>,
+pub struct SGTableMap<T: DriverObject> {
+ obj: NonNull<Object<T>>,
}
-impl<T: DriverObject, C: DeviceContext> Deref for SGTableMap<T, C> {
+impl<T: DriverObject> Deref for SGTableMap<T> {
type Target = scatterlist::SGTable;
fn deref(&self) -> &Self::Target {
@@ -599,7 +580,7 @@ fn deref(&self) -> &Self::Target {
}
}
-impl<T: DriverObject, C: DeviceContext> Drop for SGTableMap<T, C> {
+impl<T: DriverObject> Drop for SGTableMap<T> {
fn drop(&mut self) {
// SAFETY: `obj` is always valid via our type invariants
let obj = unsafe { self.obj.as_ref() };
@@ -610,8 +591,8 @@ fn drop(&mut self) {
}
}
-impl<T: DriverObject, C: DeviceContext> SGTableMap<T, C> {
- fn new(obj: &Object<T, C>) -> impl Init<Self, Error> {
+impl<T: DriverObject> SGTableMap<T> {
+ fn new(obj: &Object<T>) -> impl Init<Self, Error> {
// INVARIANT:
// - We call drm_gem_shmem_get_pages_sgt below and check whether or not it succeeds,
// fulfilling the invariant of SGTableMap that the object's `sgt` field is initialized.
@@ -625,10 +606,10 @@ fn new(obj: &Object<T, C>) -> impl Init<Self, Error> {
// SAFETY: The NonNull in SGTableMap is guaranteed valid by our type invariants, and the GEM object
// it points to is guaranteed to be thread-safe.
-unsafe impl<T: DriverObject, C: DeviceContext> Send for SGTableMap<T, C> {}
+unsafe impl<T: DriverObject> Send for SGTableMap<T> {}
// SAFETY: The NonNull in SGTableMap is guaranteed valid by our type invariants, and the GEM object
// it points to is guaranteed to be thread-safe.
-unsafe impl<T: DriverObject, C: DeviceContext> Sync for SGTableMap<T, C> {}
+unsafe impl<T: DriverObject> Sync for SGTableMap<T> {}
#[kunit_tests(rust_drm_gem_shmem)]
mod tests {
@@ -705,7 +686,7 @@ fn create_drm_dev() -> Result<(faux::Registration, UnregisteredDevice<KunitDrive
fn compile_time_vmap_sizes() -> Result {
let (_dev, drm) = create_drm_dev()?;
- let obj = Object::<KunitObject, _>::new(&drm, PAGE_SIZE, ObjectConfig::default(), ())?;
+ let obj = Object::<KunitObject>::new(&drm, PAGE_SIZE, ObjectConfig::default(), ())?;
// Try creating a normal vmap
obj.vmap::<PAGE_SIZE>()?;
@@ -729,7 +710,7 @@ fn compile_time_vmap_sizes() -> Result {
fn vmap_io() -> Result {
let (_dev, drm) = create_drm_dev()?;
- let obj = Object::<KunitObject, _>::new(&drm, PAGE_SIZE, ObjectConfig::default(), ())?;
+ let obj = Object::<KunitObject>::new(&drm, PAGE_SIZE, ObjectConfig::default(), ())?;
let vmap = obj.vmap::<PAGE_SIZE>()?;
@@ -761,7 +742,7 @@ fn fail_sg_table_on_wrong_dev() -> Result {
let reg = faux::Registration::new(c"EvilKunit", None)?;
let wrong_dev = reg.as_ref();
- let obj = Object::<KunitObject, _>::new(&drm, PAGE_SIZE, ObjectConfig::default(), ())?;
+ let obj = Object::<KunitObject>::new(&drm, PAGE_SIZE, ObjectConfig::default(), ())?;
assert_eq!(obj.sg_table(wrong_dev.as_ref()).err().unwrap(), EINVAL);
--
2.54.0
next prev parent reply other threads:[~2026-06-28 14:54 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-28 14:53 [PATCH v5 00/19] rust: drm: Higher-Ranked Lifetime private data Danilo Krummrich
2026-06-28 14:53 ` [PATCH v5 01/19] rust: drm: ioctl: fix unbounded lifetimes in ioctl handler arguments Danilo Krummrich
2026-06-28 15:03 ` sashiko-bot
2026-06-28 14:53 ` [PATCH v5 02/19] rust: drm: rename Uninit DeviceContext to Normal Danilo Krummrich
2026-06-28 14:53 ` [PATCH v5 03/19] rust: faux: add Device type with AsBusDevice support Danilo Krummrich
2026-06-28 15:05 ` sashiko-bot
2026-06-28 14:53 ` [PATCH v5 04/19] rust: drm: Add Driver::ParentDevice associated type Danilo Krummrich
2026-06-28 14:53 ` [PATCH v5 05/19] rust: drm: change default DeviceContext to Normal Danilo Krummrich
2026-06-28 14:53 ` [PATCH v5 06/19] rust: drm: restrict AlwaysRefCounted to Normal Device context Danilo Krummrich
2026-06-28 14:53 ` [PATCH v5 07/19] rust: drm: restrict AlwaysRefCounted to Normal GEM Object context Danilo Krummrich
2026-06-28 15:13 ` sashiko-bot
2026-06-28 14:53 ` Danilo Krummrich [this message]
2026-06-28 14:53 ` [PATCH v5 09/19] rust: drm: split Deref for Device context typestates Danilo Krummrich
2026-06-28 14:53 ` [PATCH v5 10/19] rust: drm: pin ioctl Device reference to Normal context Danilo Krummrich
2026-06-28 15:05 ` sashiko-bot
2026-06-28 14:53 ` [PATCH v5 11/19] rust: drm: add Ioctl device context typestate Danilo Krummrich
2026-06-28 14:53 ` [PATCH v5 12/19] rust: drm: Add RegistrationGuard for drm_dev_enter/exit critical sections Danilo Krummrich
2026-06-28 15:06 ` sashiko-bot
2026-06-28 14:53 ` [PATCH v5 13/19] rust: drm: Wrap ioctl dispatch in RegistrationGuard Danilo Krummrich
2026-06-28 15:11 ` sashiko-bot
2026-06-28 14:53 ` [PATCH v5 14/19] rust: drm: return ParentDevice from Device AsRef Danilo Krummrich
2026-06-28 14:53 ` [PATCH v5 15/19] rust: drm: add AsRef<ParentDevice<Bound>> for Device<Registered> Danilo Krummrich
2026-06-28 14:53 ` [PATCH v5 16/19] drm: fix race between partial drm_dev_register() failure and ioctl Danilo Krummrich
2026-06-28 15:14 ` sashiko-bot
2026-06-28 14:53 ` [PATCH v5 17/19] rust: drm: Add RegistrationData to drm::Driver Danilo Krummrich
2026-06-28 14:53 ` [PATCH v5 18/19] rust: drm: Pass registration data to ioctl handlers Danilo Krummrich
2026-06-28 15:13 ` sashiko-bot
2026-06-28 14:53 ` [PATCH v5 19/19] drm: nova: Use drm::Device<Registered> to access the parent bus device Danilo Krummrich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260628145406.2107056-9-dakr@kernel.org \
--to=dakr@kernel.org \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=aliceryhl@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=boris.brezillon@collabora.com \
--cc=daniel.almeida@collabora.com \
--cc=deborah.brouwer@collabora.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=driver-core@lists.linux.dev \
--cc=ecourtney@nvidia.com \
--cc=gary@garyguo.net \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=lyude@redhat.com \
--cc=nova-gpu@lists.linux.dev \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.