From: Danilo Krummrich <dakr@kernel.org>
To: dakr@kernel.org, aliceryhl@google.com, acourbot@nvidia.com,
daniel.almeida@collabora.com, ojeda@kernel.org, boqun@kernel.org,
gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org,
a.hindborg@kernel.org, tmgross@umich.edu, tamird@kernel.org,
work@onurozkan.dev, brauner@kernel.org, lyude@redhat.com,
j@jananu.net, alvin.sun@linux.dev, deborah.brouwer@collabora.com,
laura.nao@collabora.com, beata.michalska@arm.com
Cc: nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org,
rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 6/7] rust: drm: make Driver::File lifetime-parameterized
Date: Sat, 15 Aug 2026 01:09:04 +0200 [thread overview]
Message-ID: <20260814230923.1292966-7-dakr@kernel.org> (raw)
In-Reply-To: <20260814230923.1292966-1-dakr@kernel.org>
Make the DRM file private data lifetime-parameterized, allowing drivers
to borrow from RegistrationData in their per-file data.
Introduce DriverFile<'a> as a lifetime-parameterized trait that receives
both the device and registration data in open(). Parametrize File<D> on
the driver type rather than the file data type, deriving the concrete
file type through ForLt.
Add inner() for covariant file types and inner_with() for invariant ones
to access the driver file data from a File<D> reference.
Ensure file data is always dropped before registration data:
- In Registration::drop(), iterate the filelist under filelist_mutex
and drop driver_priv for all open files, then wait for in-flight
postclose_callback() calls to complete via an open_count / WaitQueue
pair on drm::Device.
- In postclose_callback(), skip the drop if driver_priv has already
been NULLed by the filelist iteration. The NULL write is visible
through the filelist_mutex acquire/release chain in
drm_close_helper().
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
---
drivers/gpu/drm/nova/driver.rs | 5 +-
drivers/gpu/drm/nova/file.rs | 11 ++-
drivers/gpu/drm/nova/gem.rs | 8 +-
drivers/gpu/drm/tyr/driver.rs | 5 +-
drivers/gpu/drm/tyr/file.rs | 11 ++-
rust/kernel/drm/device.rs | 35 ++++++--
rust/kernel/drm/driver.rs | 69 ++++++++++++++-
rust/kernel/drm/file.rs | 150 ++++++++++++++++++++++-----------
rust/kernel/drm/gem/mod.rs | 12 ++-
rust/kernel/drm/gem/shmem.rs | 12 ++-
rust/kernel/drm/ioctl.rs | 2 +-
11 files changed, 231 insertions(+), 89 deletions(-)
diff --git a/drivers/gpu/drm/nova/driver.rs b/drivers/gpu/drm/nova/driver.rs
index 739690bc2db5..a8f61086773d 100644
--- a/drivers/gpu/drm/nova/driver.rs
+++ b/drivers/gpu/drm/nova/driver.rs
@@ -12,7 +12,8 @@
ioctl, //
},
prelude::*,
- sync::aref::ARef, //
+ sync::aref::ARef,
+ types::CovariantForLt, //
};
use crate::file::File;
@@ -75,7 +76,7 @@ fn probe<'bound>(
impl drm::Driver for NovaDriver {
type Data = ();
type RegistrationData<'a> = ();
- type File = File;
+ type File = CovariantForLt!(File);
type Object = gem::Object<NovaObject>;
type ParentDevice<Ctx: DeviceContext> = auxiliary::Device<Ctx>;
diff --git a/drivers/gpu/drm/nova/file.rs b/drivers/gpu/drm/nova/file.rs
index 298c02bacb4b..1f94201af92b 100644
--- a/drivers/gpu/drm/nova/file.rs
+++ b/drivers/gpu/drm/nova/file.rs
@@ -3,7 +3,6 @@
use crate::driver::{NovaDevice, NovaDriver};
use crate::gem::NovaObject;
use kernel::{
- alloc::flags::*,
auxiliary,
device::Bound,
drm::{
@@ -18,10 +17,10 @@
pub(crate) struct File;
-impl drm::file::DriverFile for File {
+impl drm::file::DriverFile<'_> for File {
type Driver = NovaDriver;
- fn open(_dev: &NovaDevice) -> Result<Pin<KBox<Self>>> {
+ fn open(_device: &NovaDevice<Registered>, _reg_data: &()) -> Result<Pin<KBox<Self>>> {
Ok(KBox::new(Self, GFP_KERNEL)?.into())
}
}
@@ -32,7 +31,7 @@ pub(crate) fn get_param(
dev: &NovaDevice<Registered>,
_reg_data: &(),
getparam: &mut uapi::drm_nova_getparam,
- _file: &drm::File<File>,
+ _file: &drm::File<NovaDriver>,
) -> Result<u32> {
let adev: &auxiliary::Device<Bound> = dev.as_ref();
let pdev: &pci::Device<Bound> = adev.parent().try_into()?;
@@ -52,7 +51,7 @@ pub(crate) fn gem_create(
dev: &NovaDevice<Registered>,
_reg_data: &(),
req: &mut uapi::drm_nova_gem_create,
- file: &drm::File<File>,
+ file: &drm::File<NovaDriver>,
) -> Result<u32> {
let obj = NovaObject::new(dev, req.size.try_into()?)?;
@@ -66,7 +65,7 @@ pub(crate) fn gem_info(
_dev: &NovaDevice<Registered>,
_reg_data: &(),
req: &mut uapi::drm_nova_gem_info,
- file: &drm::File<File>,
+ file: &drm::File<NovaDriver>,
) -> Result<u32> {
let bo = NovaObject::lookup_handle(file, req.handle)?;
diff --git a/drivers/gpu/drm/nova/gem.rs b/drivers/gpu/drm/nova/gem.rs
index 2b6fe9dc0bfa..2a21ff8ba579 100644
--- a/drivers/gpu/drm/nova/gem.rs
+++ b/drivers/gpu/drm/nova/gem.rs
@@ -11,9 +11,9 @@
sync::aref::ARef,
};
-use crate::{
- driver::{NovaDevice, NovaDriver},
- file::File,
+use crate::driver::{
+ NovaDevice,
+ NovaDriver, //
};
/// GEM Object inner driver data
@@ -43,7 +43,7 @@ pub(crate) fn new(dev: &NovaDevice, size: usize) -> Result<ARef<gem::Object<Self
/// Look up a GEM object handle for a `File` and return an `ObjectRef` for it.
#[inline]
pub(crate) fn lookup_handle(
- file: &drm::File<File>,
+ file: &drm::File<NovaDriver>,
handle: u32,
) -> Result<ARef<gem::Object<Self>>> {
gem::Object::lookup_handle(file, handle)
diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs
index d78ad9d292ff..94bc85635725 100644
--- a/drivers/gpu/drm/tyr/driver.rs
+++ b/drivers/gpu/drm/tyr/driver.rs
@@ -32,7 +32,8 @@
Arc,
Mutex, //
},
- time, //
+ time,
+ types::CovariantForLt, //
};
use crate::{
@@ -206,7 +207,7 @@ fn drop(self: Pin<&mut Self>) {}
impl drm::Driver for TyrDrmDriver {
type Data = ();
type RegistrationData<'drm> = TyrDrmRegistrationData<'drm>;
- type File = TyrDrmFileData;
+ type File = CovariantForLt!(TyrDrmFileData);
type Object = Bo;
type ParentDevice<Ctx: DeviceContext> = platform::Device<Ctx>;
diff --git a/drivers/gpu/drm/tyr/file.rs b/drivers/gpu/drm/tyr/file.rs
index 9f60a90d4948..0e0878090de6 100644
--- a/drivers/gpu/drm/tyr/file.rs
+++ b/drivers/gpu/drm/tyr/file.rs
@@ -19,13 +19,16 @@
#[pin_data]
pub(crate) struct TyrDrmFileData {}
-/// Convenience type alias for our DRM `File` type
-pub(crate) type TyrDrmFile = drm::file::File<TyrDrmFileData>;
+/// Convenience type alias for our DRM `File` type.
+pub(crate) type TyrDrmFile = drm::file::File<TyrDrmDriver>;
-impl drm::file::DriverFile for TyrDrmFileData {
+impl drm::file::DriverFile<'_> for TyrDrmFileData {
type Driver = TyrDrmDriver;
- fn open(_dev: &drm::Device<Self::Driver>) -> Result<Pin<KBox<Self>>> {
+ fn open(
+ _device: &TyrDrmDevice<Registered>,
+ _reg_data: &TyrDrmRegistrationData<'_>,
+ ) -> Result<Pin<KBox<Self>>> {
KBox::try_pin_init(try_pin_init!(Self {}), GFP_KERNEL)
}
}
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index 09903ed783e1..29512d0e2ddb 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -15,11 +15,16 @@
},
error::from_err_ptr,
prelude::*,
- sync::aref::{
- ARef,
- AlwaysRefCounted, //
+ sync::{
+ aref::{
+ ARef,
+ AlwaysRefCounted, //
+ },
+ atomic::Atomic,
+ WaitQueue,
},
types::{
+ ForLt,
NotThreadSafe,
Opaque, //
},
@@ -190,7 +195,10 @@ fn deref(&self) -> &Self::Target {
}
}
-impl<T: drm::Driver> UnregisteredDevice<T> {
+impl<T: drm::Driver> UnregisteredDevice<T>
+where
+ for<'a> <T::File as ForLt>::Of<'a>: drm::file::DriverFile<'a, Driver = T>,
+{
const fn compute_features() -> u32 {
let mut features = drm::driver::FEAT_GEM;
@@ -203,8 +211,8 @@ const fn compute_features() -> u32 {
const VTABLE: bindings::drm_driver = drm_legacy_fields! {
load: None,
- open: Some(drm::File::<T::File>::open_callback),
- postclose: Some(drm::File::<T::File>::postclose_callback),
+ open: Some(drm::File::<T>::open_callback),
+ postclose: Some(drm::File::<T>::postclose_callback),
unload: None,
release: Some(Device::<T>::release),
master_set: None,
@@ -333,6 +341,19 @@ pub fn new(
// SAFETY: `raw_drm` is valid; no concurrent access before registration.
unsafe { (*raw_drm.as_ptr()).registration_data = UnsafeCell::new(NonNull::dangling()) };
+ // SAFETY: `raw_drm` is valid; no concurrent access before registration.
+ unsafe { (*raw_drm.as_ptr()).open_count = Atomic::new(0) };
+
+ // SAFETY:
+ // - `raw_drm` is valid; no concurrent access before registration.
+ // - The field is pinned because the Device is pinned (refcounted, allocated by
+ // `__drm_dev_alloc()`, never moved).
+ // - The init is infallible.
+ let Ok(()) = unsafe {
+ crate::new_waitqueue!("drm_open_count")
+ .__pinned_init(&raw mut (*raw_drm.as_ptr()).open_count_wq)
+ };
+
// SAFETY: The reference count is one, and now we take ownership of that reference as a
// `drm::Device`.
// INVARIANT: We just created the device above, but have yet to call `drm_dev_register`.
@@ -357,6 +378,8 @@ pub struct Device<T: drm::Driver, C: DeviceContext = Normal> {
dev: Opaque<bindings::drm_device>,
data: T::Data,
pub(super) registration_data: UnsafeCell<NonNull<T::RegistrationData<'static>>>,
+ pub(super) open_count: Atomic<i32>,
+ pub(super) open_count_wq: WaitQueue,
_ctx: PhantomData<C>,
}
diff --git a/rust/kernel/drm/driver.rs b/rust/kernel/drm/driver.rs
index 74f6ed690d8b..2aa534149d78 100644
--- a/rust/kernel/drm/driver.rs
+++ b/rust/kernel/drm/driver.rs
@@ -9,8 +9,17 @@
device,
drm,
error::to_result,
+ interop::list::clist_create,
prelude::*,
- sync::aref::ARef, //
+ sync::{
+ aref::ARef,
+ atomic::{
+ Acquire,
+ Release, //
+ },
+ Mutex, //
+ },
+ types::ForLt, //
};
use core::ptr::NonNull;
@@ -117,8 +126,15 @@ pub trait Driver {
/// The type used to manage memory for this driver.
type Object: AllocImpl;
- /// The type used to represent a DRM File (client)
- type File: drm::file::DriverFile;
+ /// The type used to represent a DRM File (client).
+ ///
+ /// File data may borrow from [`RegistrationData`](Driver::RegistrationData). File data is
+ /// guaranteed to be dropped before registration data, either when the file is closed or
+ /// when the device is unregistered, whichever comes first.
+ ///
+ /// Drivers set this to `CovariantForLt!(MyFileData)` (or `ForLt!` for invariant types)
+ /// and implement [`DriverFile`](drm::file::DriverFile) for their file data type.
+ type File: ForLt + 'static;
/// The bus device type of the parent device that the DRM device is associated with.
type ParentDevice<Ctx: device::DeviceContext>: device::AsBusDevice<Ctx>;
@@ -221,6 +237,51 @@ fn drop(&mut self) {
unsafe { bindings::drm_dev_unplug(self.drm.as_raw()) };
// After drm_dev_unplug(), the SRCU barrier guarantees that all RegistrationGuard critical
// sections have completed, so no one holds a reference to reg_data anymore.
- // reg_data is dropped here automatically.
+
+ // Drop all remaining file private data before dropping registration data. This guarantees
+ // that file data (which may borrow from RegistrationData) is always dropped first.
+ let raw = self.drm.as_raw();
+
+ // SAFETY: `filelist_mutex` is initialized by `drm_dev_init()` and remains valid for
+ // the lifetime of the `struct drm_device`.
+ let filelist_mutex = unsafe { Mutex::from_raw(&raw mut (*raw).filelist_mutex) };
+ {
+ let _guard = filelist_mutex.lock();
+
+ // SAFETY: `filelist` is a valid, initialized sentinel `list_head`; the mutex
+ // guard prevents concurrent modification.
+ let filelist = unsafe {
+ clist_create!(
+ &raw mut (*raw).filelist,
+ drm::File<T>,
+ bindings::drm_file,
+ lhead
+ )
+ };
+
+ for file in filelist.iter() {
+ // SAFETY: `file` is a valid `drm_file` on this device's filelist.
+ let priv_ptr = unsafe { (*file.as_raw()).driver_priv };
+
+ // SAFETY: Setting `driver_priv` to NULL is visible to `postclose_callback()`
+ // through the `filelist_mutex` acquire/release chain in `drm_close_helper()`.
+ unsafe { (*file.as_raw()).driver_priv = core::ptr::null_mut() };
+
+ // SAFETY: `driver_priv` was created by `open_callback()` via `KBox::into_raw` and
+ // has not yet been freed (the file is still in the list, so `postclose_callback()`
+ // has not run).
+ drop(unsafe { KBox::from_raw(priv_ptr.cast::<<T::File as ForLt>::Of<'static>>()) });
+
+ self.drm.open_count.fetch_sub(1, Release);
+ }
+ }
+
+ // Wait for in-flight `postclose_callback()` calls to complete. After `drm_dev_unplug()`, no
+ // new opens can succeed, so `open_count` is monotonically decreasing.
+ self.drm
+ .open_count_wq
+ .wait_event(|| self.drm.open_count.load(Acquire) == 0);
+
+ // `_reg_data` is dropped here automatically, after all file data has been dropped.
}
}
diff --git a/rust/kernel/drm/file.rs b/rust/kernel/drm/file.rs
index 10160601ce5a..6491ec5707a0 100644
--- a/rust/kernel/drm/file.rs
+++ b/rust/kernel/drm/file.rs
@@ -8,17 +8,34 @@
bindings,
drm,
prelude::*,
- types::Opaque, //
+ sync::atomic::{
+ Relaxed,
+ Release, //
+ },
+ types::{
+ CovariantForLt,
+ ForLt,
+ Opaque, //
+ }, //
};
use core::marker::PhantomData;
/// Trait that must be implemented by DRM drivers to represent a DRM File (a client instance).
-pub trait DriverFile {
+///
+/// The lifetime `'a` allows the file data to borrow from
+/// [`RegistrationData`](drm::Driver::RegistrationData).
+pub trait DriverFile<'a>: Sized {
/// The parent `Driver` implementation for this `DriverFile`.
type Driver: drm::Driver;
- /// Open a new file (called when a client opens the DRM device).
- fn open(device: &drm::Device<Self::Driver>) -> Result<Pin<KBox<Self>>>;
+ /// Open a new DRM file, creating the per-file driver data.
+ ///
+ /// Called when a client opens the DRM device. The returned file data may borrow from
+ /// `reg_data` with lifetime `'a`.
+ fn open(
+ device: &drm::Device<Self::Driver, drm::Registered>,
+ reg_data: &'a <Self::Driver as drm::Driver>::RegistrationData<'a>,
+ ) -> Result<Pin<KBox<Self>>>;
}
/// An open DRM File.
@@ -27,17 +44,17 @@ pub trait DriverFile {
///
/// `self.0` is a valid instance of a `struct drm_file`.
#[repr(transparent)]
-pub struct File<T: DriverFile>(Opaque<bindings::drm_file>, PhantomData<T>);
+pub struct File<D: drm::Driver>(Opaque<bindings::drm_file>, PhantomData<D>);
-impl<T: DriverFile> File<T> {
+impl<D: drm::Driver> File<D> {
#[doc(hidden)]
/// Not intended to be called externally, except via declare_drm_ioctls!()
///
/// # Safety
///
- /// `raw_file` must be a valid pointer to an open `struct drm_file`, opened through `T::open`.
- pub unsafe fn from_raw<'a>(ptr: *mut bindings::drm_file) -> &'a File<T> {
- // SAFETY: `raw_file` is valid by the safety requirements of this function.
+ /// `ptr` must be a valid pointer to an open `struct drm_file`.
+ pub unsafe fn from_raw<'a>(ptr: *mut bindings::drm_file) -> &'a File<D> {
+ // SAFETY: `ptr` is valid by the safety requirements of this function.
unsafe { &*ptr.cast() }
}
@@ -45,59 +62,94 @@ pub(super) fn as_raw(&self) -> *mut bindings::drm_file {
self.0.get()
}
- fn driver_priv(&self) -> *mut T {
- // SAFETY: By the type invariants of `Self`, `self.as_raw()` is always valid.
- unsafe { (*self.as_raw()).driver_priv }.cast()
+ /// Return a pinned reference to the driver file data.
+ ///
+ /// Only available when `D::File` implements [`trait@CovariantForLt`]. For invariant types, use
+ /// [`inner_with()`](Self::inner_with).
+ pub fn inner(&self) -> Pin<&<D::File as ForLt>::Of<'_>>
+ where
+ D::File: CovariantForLt,
+ {
+ // SAFETY: `driver_priv` was initialized by `open_callback()`. `CovariantForLt` guarantees
+ // the lifetime shortening from `'static` to `'_` is sound.
+ unsafe { Pin::new_unchecked(&*(*self.as_raw()).driver_priv.cast_const().cast()) }
}
- /// Return a pinned reference to the driver file structure.
- pub fn inner(&self) -> Pin<&T> {
- // SAFETY: By the type invariant the pointer `self.as_raw()` points to a valid and opened
- // `struct drm_file`, hence `driver_priv` has been properly initialized by `open_callback`.
- unsafe { Pin::new_unchecked(&*(self.driver_priv())) }
+ /// Access the driver file data through a closure.
+ ///
+ /// This works for all file data types, including invariant ones. For covariant types,
+ /// [`inner()`](Self::inner) provides direct access without a closure.
+ pub fn inner_with<R, F>(&self, f: F) -> R
+ where
+ F: for<'a> FnOnce(Pin<&'a <D::File as ForLt>::Of<'a>>) -> R,
+ {
+ // SAFETY: `driver_priv` was initialized by `open_callback()`. The HRTB `for<'a>` prevents
+ // the caller from choosing a concrete lifetime, making the lifetime shortening sound
+ // regardless of variance.
+ f(unsafe { Pin::new_unchecked(&*(*self.as_raw()).driver_priv.cast_const().cast()) })
}
/// The open callback of a `struct drm_file`.
+ ///
+ /// Called from `drm_open()`, which is itself called from `fops_open()`. The latter holds a
+ /// `RegistrationGuard`, so the device is guaranteed to be registered for the duration of this
+ /// callback.
pub(crate) extern "C" fn open_callback(
raw_dev: *mut bindings::drm_device,
raw_file: *mut bindings::drm_file,
- ) -> core::ffi::c_int {
- // SAFETY: A callback from `struct drm_driver::open` guarantees that
- // - `raw_dev` is valid pointer to a `struct drm_device`,
- // - the corresponding `struct drm_device` has been registered.
- let drm = unsafe { drm::Device::from_raw(raw_dev) };
-
- // SAFETY: `raw_file` is a valid pointer to a `struct drm_file`.
- let file = unsafe { File::<T>::from_raw(raw_file) };
-
- let inner = match T::open(drm) {
- Err(e) => {
- return e.to_errno();
- }
- Ok(i) => i,
- };
-
- // SAFETY: This pointer is treated as pinned, and the Drop guarantee is upheld in
- // `postclose_callback()`.
- let driver_priv = KBox::into_raw(unsafe { Pin::into_inner_unchecked(inner) });
-
- // SAFETY: By the type invariants of `Self`, `self.as_raw()` is always valid.
- unsafe { (*file.as_raw()).driver_priv = driver_priv.cast() };
-
- 0
+ ) -> core::ffi::c_int
+ where
+ for<'a> <D::File as ForLt>::Of<'a>: DriverFile<'a, Driver = D>,
+ {
+ // SAFETY: The DRM core guarantees that `raw_dev` is valid. `fops_open()` holds a
+ // `RegistrationGuard`, so the device is registered and the `Registered` context holds.
+ let dev: &drm::device::Device<D, drm::Registered> =
+ unsafe { drm::device::Device::from_raw(raw_dev) };
+
+ dev.registration_data_with(|reg_data| {
+ let inner = match <<D::File as ForLt>::Of<'_> as DriverFile<'_>>::open(dev, reg_data) {
+ Err(e) => return e.to_errno(),
+ Ok(i) => i,
+ };
+
+ // SAFETY: This pointer is treated as pinned, and the Drop guarantee is upheld in
+ // `postclose_callback()` or the filelist iteration in `Registration::drop()`.
+ let driver_priv = KBox::into_raw(unsafe { Pin::into_inner_unchecked(inner) });
+
+ dev.open_count.fetch_add(1, Relaxed);
+
+ // SAFETY: `raw_file` is a valid pointer to a `struct drm_file`.
+ unsafe { (*raw_file).driver_priv = driver_priv.cast() };
+
+ 0
+ })
}
/// The postclose callback of a `struct drm_file`.
pub(crate) extern "C" fn postclose_callback(
- _raw_dev: *mut bindings::drm_device,
+ raw_dev: *mut bindings::drm_device,
raw_file: *mut bindings::drm_file,
- ) {
- // SAFETY: This reference won't escape this function
- let file = unsafe { File::<T>::from_raw(raw_file) };
-
- // SAFETY: `file.driver_priv` has been created in `open_callback` through `KBox::into_raw`.
- let _ = unsafe { KBox::from_raw(file.driver_priv()) };
+ ) where
+ for<'a> <D::File as ForLt>::Of<'a>: DriverFile<'a, Driver = D>,
+ {
+ // SAFETY: `raw_file` is a valid pointer to a `struct drm_file`.
+ let driver_priv = unsafe { (*raw_file).driver_priv };
+
+ if driver_priv.is_null() {
+ return;
+ }
+
+ // SAFETY: `driver_priv` was created in `open_callback()` through `KBox::into_raw` and has
+ // not been dropped yet (the NULL check above guards against double-free from the filelist
+ // iteration in `Registration::drop()`).
+ let _ = unsafe { KBox::from_raw(driver_priv.cast::<<D::File as ForLt>::Of<'static>>()) };
+
+ // SAFETY: `raw_dev` is valid for the lifetime of the `struct drm_file`.
+ let dev: &drm::device::Device<D> = unsafe { drm::device::Device::from_raw(raw_dev) };
+ if dev.open_count.fetch_sub(1, Release) == 1 {
+ dev.open_count_wq.wake_up();
+ }
}
}
-impl<T: DriverFile> super::private::Sealed for File<T> {}
+impl<D: drm::Driver> super::private::Sealed for File<D> {}
diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs
index ee048febfbdc..1aa18f0b172c 100644
--- a/rust/kernel/drm/gem/mod.rs
+++ b/rust/kernel/drm/gem/mod.rs
@@ -76,7 +76,7 @@ unsafe fn dec_ref(obj: core::ptr::NonNull<Self>) {
///
/// [`Driver`]: drm::Driver
/// [`DriverFile`]: drm::file::DriverFile
-pub type DriverFile<T> = drm::File<<<T as DriverObject>::Driver as drm::Driver>::File>;
+pub type DriverFile<T> = drm::File<<T as DriverObject>::Driver>;
/// A type alias for retrieving the current [`AllocImpl`] for a given [`DriverObject`].
///
@@ -196,11 +196,10 @@ fn size(&self) -> usize {
/// Creates a new handle for the object associated with a given `File`
/// (or returns an existing one).
- fn create_handle<D, F>(&self, file: &drm::File<F>) -> Result<u32>
+ fn create_handle<D>(&self, file: &drm::File<D>) -> Result<u32>
where
Self: AllocImpl<Driver = D>,
- D: drm::Driver<Object = Self, File = F>,
- F: drm::file::DriverFile<Driver = D>,
+ D: drm::Driver<Object = Self>,
{
let mut handle: u32 = 0;
// SAFETY: The arguments are all valid per the type invariants.
@@ -211,11 +210,10 @@ fn create_handle<D, F>(&self, file: &drm::File<F>) -> Result<u32>
}
/// Looks up an object by its handle for a given `File`.
- fn lookup_handle<D, F>(file: &drm::File<F>, handle: u32) -> Result<ARef<Self>>
+ fn lookup_handle<D>(file: &drm::File<D>, handle: u32) -> Result<ARef<Self>>
where
Self: AllocImpl<Driver = D> + AlwaysRefCounted,
- D: drm::Driver<Object = Self, File = F>,
- F: drm::file::DriverFile<Driver = D>,
+ D: drm::Driver<Object = Self>,
{
// SAFETY: The arguments are all valid per the type invariants.
let ptr = unsafe { bindings::drm_gem_object_lookup(file.as_raw().cast(), handle) };
diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs
index a687d46d170d..793b4883de3a 100644
--- a/rust/kernel/drm/gem/shmem.rs
+++ b/rust/kernel/drm/gem/shmem.rs
@@ -584,7 +584,8 @@ mod tests {
},
faux,
io::Io,
- page::PAGE_SIZE, //
+ page::PAGE_SIZE,
+ types::CovariantForLt, //
};
// The bare minimum needed to create a fake drm driver for kunit
@@ -604,10 +605,13 @@ struct KunitObject {}
desc: c"Kunit",
};
- impl drm::file::DriverFile for KunitFile {
+ impl drm::file::DriverFile<'_> for KunitFile {
type Driver = KunitDriver;
- fn open(_dev: &drm::Device<KunitDriver>) -> Result<Pin<KBox<Self>>> {
+ fn open(
+ _device: &drm::Device<KunitDriver, drm::Registered>,
+ _reg_data: &(),
+ ) -> Result<Pin<KBox<Self>>> {
Ok(KBox::new(Self, GFP_KERNEL)?.into())
}
}
@@ -629,7 +633,7 @@ fn new(
impl drm::Driver for KunitDriver {
type Data = KunitData;
type RegistrationData<'a> = ();
- type File = KunitFile;
+ type File = CovariantForLt!(KunitFile);
type Object = Object<KunitObject>;
type ParentDevice<Ctx: device::DeviceContext> = faux::Device<Ctx>;
diff --git a/rust/kernel/drm/ioctl.rs b/rust/kernel/drm/ioctl.rs
index 9934b23c36eb..8ac7fb1d4ec2 100644
--- a/rust/kernel/drm/ioctl.rs
+++ b/rust/kernel/drm/ioctl.rs
@@ -97,7 +97,7 @@ pub const fn __dev_ctx_cast<T: crate::drm::Driver>(
/// fn foo(device: &kernel::drm::Device<Self, kernel::drm::Registered>,
/// reg_data: &Self::RegistrationData<'_>,
/// data: &mut uapi::argument_type,
-/// file: &kernel::drm::File<Self::File>,
+/// file: &kernel::drm::File<Self>,
/// ) -> Result<u32>
/// ```
/// where `Self` is the drm::drv::Driver implementation these ioctls are being declared within.
--
2.55.0
next prev parent reply other threads:[~2026-08-14 23:10 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-14 23:08 [PATCH 0/7] lifetime-parameterized DRM File private data Danilo Krummrich
2026-08-14 23:08 ` [PATCH 1/7] rust: drm: rename Ioctl device context to Userspace Danilo Krummrich
2026-08-14 23:09 ` [PATCH 2/7] rust: drm: gem: gate open/close callbacks with RegistrationGuard Danilo Krummrich
2026-08-14 23:09 ` [PATCH 3/7] rust: drm: move file_operations from gem to device Danilo Krummrich
2026-08-14 23:09 ` [PATCH 4/7] rust: fs: add iminor() helper Danilo Krummrich
2026-08-14 23:09 ` [PATCH 5/7] rust: drm: wrap fops open with RegistrationGuard Danilo Krummrich
2026-08-14 23:09 ` Danilo Krummrich [this message]
2026-08-14 23:09 ` [PATCH 7/7] rust: drm: return impl PinInit from DriverFile::open() 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=20260814230923.1292966-7-dakr@kernel.org \
--to=dakr@kernel.org \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=aliceryhl@google.com \
--cc=alvin.sun@linux.dev \
--cc=beata.michalska@arm.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=brauner@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=deborah.brouwer@collabora.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=gary@garyguo.net \
--cc=j@jananu.net \
--cc=laura.nao@collabora.com \
--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=tamird@kernel.org \
--cc=tmgross@umich.edu \
--cc=work@onurozkan.dev \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox