From: Mike Lothian <mike@fireburn.co.uk>
To: dri-devel@lists.freedesktop.org
Cc: "Mike Lothian" <mike@fireburn.co.uk>,
"Danilo Krummrich" <dakr@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Trevor Gross" <tmgross@umich.edu>,
"Daniel Almeida" <daniel.almeida@collabora.com>,
"Tamir Duberstein" <tamird@kernel.org>,
"Alexandre Courbot" <acourbot@nvidia.com>,
"Onur Özkan" <work@onurozkan.dev>,
"Lyude Paul" <lyude@redhat.com>,
"Mukesh Kumar Chaurasiya (IBM)" <mkchauras@gmail.com>,
"Asahi Lina" <lina+kernel@asahilina.net>,
rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v3 15/23] rust: drm: pin the owner while DRM files remain open
Date: Wed, 26 Aug 2026 17:31:46 +0100 [thread overview]
Message-ID: <20260826163359.4998-16-mike@fireburn.co.uk> (raw)
In-Reply-To: <20260826163359.4998-1-mike@fireburn.co.uk>
Give each Rust DRM device its own driver and file-operations tables
so file_operations::owner can identify the module that owns the
implementation. Open DRM file descriptors then hold the same module
reference that C DRM drivers receive through DEFINE_DRM_GEM_*_FOPS().
Pass the owning module to UnregisteredDevice::new() and use the
built-in null module for the shmem KUnit device.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Mike Lothian <mike@fireburn.co.uk>
---
rust/kernel/drm/device.rs | 46 ++++++++++++++++++++++++++++++++++--
rust/kernel/drm/gem/shmem.rs | 8 ++++++-
2 files changed, 51 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index bc2cdcd2b695..efbec3f42bda 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -208,9 +208,14 @@ const fn compute_features() -> u32 {
/// Create a new `UnregisteredDevice` for a `drm::Driver`.
///
/// This can be used to create a [`Registration`](kernel::drm::Registration).
+ ///
+ /// `module` must be the module that owns the driver implementation, i.e. `&THIS_MODULE`. It is
+ /// stamped into this device's `file_operations::owner` so that an open `/dev/dri/cardN` file
+ /// descriptor pins the module, exactly as `DEFINE_DRM_GEM_*_FOPS()` does in C.
pub fn new(
dev: &T::ParentDevice<device::Bound>,
data: impl PinInit<T::Data, Error>,
+ module: &'static ThisModule,
) -> Result<Self> {
// `__drm_dev_alloc` uses `kmalloc()` to allocate memory, hence ensure a `kmalloc()`
// compatible `Layout`.
@@ -253,8 +258,37 @@ pub fn new(
unsafe { bindings::drm_dev_put(drm_dev) };
})?;
- // SAFETY: `drm_dev` is still private to this function.
- unsafe { (*drm_dev).driver = const { &Self::VTABLE } };
+ // Give this device its own `file_operations`/`drm_driver` pair so that the owning module
+ // can be stamped into the fops. `fops->owner` is what makes `fops_get()` in
+ // `drm_stub_open()` take a module reference for every open DRM file: without it nothing
+ // pins the module, and unloading the driver while a compositor still has
+ // `/dev/dri/cardN` in a poll set frees the `file_operations` out from under
+ // `do_sys_poll()`, which then faults on `f_op->poll`.
+ //
+ // SAFETY: `raw_drm` is a valid pointer to `Self`, still private to this function, and
+ // both fields are plain data that need no drop.
+ let raw_fops = unsafe { Opaque::cast_into(ptr::addr_of!((*raw_drm.as_ptr()).fops)) };
+ // SAFETY: `raw_fops` is valid, aligned and points at uninitialized memory we own.
+ unsafe {
+ raw_fops.write(bindings::file_operations {
+ owner: module.as_ptr(),
+ ..Self::GEM_FOPS
+ })
+ };
+
+ // SAFETY: as above, for the per-device `drm_driver` copy.
+ let raw_vtable = unsafe { Opaque::cast_into(ptr::addr_of!((*raw_drm.as_ptr()).vtable)) };
+ // SAFETY: `raw_vtable` is valid, aligned and points at uninitialized memory we own.
+ unsafe {
+ raw_vtable.write(bindings::drm_driver {
+ fops: raw_fops,
+ ..Self::VTABLE
+ })
+ };
+
+ // SAFETY: `drm_dev` is still private to this function; `raw_vtable` lives inside the DRM
+ // device allocation and so outlives every use of `drm_device::driver`.
+ unsafe { (*drm_dev).driver = raw_vtable };
// SAFETY: `raw_drm` is valid; no concurrent access before registration.
unsafe { (*raw_drm.as_ptr()).registration_data = UnsafeCell::new(NonNull::dangling()) };
@@ -277,12 +311,20 @@ pub fn new(
///
/// * `self.dev` is a valid instance of a `struct device`.
/// * The data layout of `Self` remains the same across all implementations of `C`.
+/// * `self.vtable` and `self.fops` are initialized before the device is registered and are never
+/// mutated afterwards; `self.dev.driver` points at `self.vtable`, whose `fops` points at
+/// `self.fops`.
/// * Any invariants for `C` also apply.
#[repr(C)]
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>>>,
+ /// Per-device copy of the driver vtable, so that `fops` below can be referenced from it.
+ vtable: Opaque<bindings::drm_driver>,
+ /// Per-device copy of the DRM file operations, carrying the owning module in `owner` so that
+ /// an open DRM file descriptor pins the module.
+ fops: Opaque<bindings::file_operations>,
_ctx: PhantomData<C>,
}
diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs
index 86797ab39ffd..8751000c92bb 100644
--- a/rust/kernel/drm/gem/shmem.rs
+++ b/rust/kernel/drm/gem/shmem.rs
@@ -642,12 +642,18 @@ impl drm::Driver for KunitDriver {
const IOCTLS: &'static [drm::ioctl::DrmIoctlDescriptor] = &[];
}
+ // These tests only ever build into the kernel image, so there is no module to pin. A null
+ // `file_operations::owner` is exactly what a built-in driver uses.
+ //
+ // SAFETY: `NULL` is the correct `THIS_MODULE` for built-in code.
+ static KUNIT_MODULE: ThisModule = unsafe { ThisModule::from_ptr(ptr::null_mut()) };
+
fn create_drm_dev() -> Result<(faux::Registration, UnregisteredDevice<KunitDriver>)> {
// Create a faux DRM device so we can test gem object creation.
let data = try_pin_init!(KunitData {});
let reg = faux::Registration::new(c"Kunit", None)?;
let fdev = reg.as_ref();
- let drm = UnregisteredDevice::new(fdev, data)?;
+ let drm = UnregisteredDevice::new(fdev, data, &KUNIT_MODULE)?;
Ok((reg, drm))
}
next prev parent reply other threads:[~2026-08-26 16:36 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-26 16:31 [PATCH v3 0/23] rust: drm: KMS abstractions for a Rust display driver Mike Lothian
2026-08-26 16:31 ` [PATCH v3 1/23] rust: drm: kms: adapt Lyude's KMS series to current DRM APIs Mike Lothian
2026-08-26 16:31 ` [PATCH v3 2/23] rust: drm: kms: tie mode-object references to their owners Mike Lothian
2026-08-26 16:31 ` [PATCH v3 3/23] rust: drm: kms: constrain connector encoder attachment Mike Lothian
2026-08-26 16:31 ` [PATCH v3 4/23] rust: drm: reject cross-device GEM handle creation Mike Lothian
2026-08-26 16:31 ` [PATCH v3 5/23] rust: drm: kms: add common state and connector helpers Mike Lothian
2026-08-26 16:31 ` [PATCH v3 6/23] rust: drm: expose HDCP 2.2 message identifiers Mike Lothian
2026-08-26 16:31 ` [PATCH v3 7/23] rust: drm: kms: add typed color and rotation properties Mike Lothian
2026-08-26 16:31 ` [PATCH v3 8/23] rust: drm: kms: add connector detect() and mode_valid() hooks Mike Lothian
2026-08-26 16:31 ` [PATCH v3 9/23] rust: drm: kms: add plane damage-clip accessors Mike Lothian
2026-08-26 16:31 ` [PATCH v3 10/23] rust: drm: framebuffer: add validated shmem scanout views Mike Lothian
2026-08-26 16:31 ` [PATCH v3 11/23] rust: drm: kms: expose checked plane geometry Mike Lothian
2026-08-26 16:31 ` [PATCH v3 12/23] rust: drm: kms: add owned CRTC and vblank references Mike Lothian
2026-08-26 16:31 ` [PATCH v3 13/23] rust: drm: kms: plane: add FB_DAMAGE_CLIPS property support Mike Lothian
2026-08-26 16:31 ` [PATCH v3 14/23] rust: drm: add a safe constructor for owned registration data Mike Lothian
2026-08-26 16:31 ` Mike Lothian [this message]
2026-08-26 16:31 ` [PATCH v3 16/23] rust: drm: kms: add the plane blend-mode property Mike Lothian
2026-08-26 16:31 ` [PATCH v3 17/23] rust: drm: add an owned display mode constructor Mike Lothian
2026-08-26 16:31 ` [PATCH v3 18/23] rust: drm: expose mode flags and CTA VIC matching Mike Lothian
2026-08-26 16:31 ` [PATCH v3 19/23] rust: drm: expose CRTC mode changes Mike Lothian
2026-08-26 16:31 ` [PATCH v3 20/23] rust: drm: kms: add synthesized CVT connector modes Mike Lothian
2026-08-26 16:31 ` [PATCH v3 21/23] rust: drm: kms: read a connector's colorimetry and HDR metadata Mike Lothian
2026-08-26 16:31 ` [PATCH v3 22/23] rust: drm: kms: walk the CRTCs an atomic commit carries Mike Lothian
2026-08-26 16:31 ` [PATCH v3 23/23] rust: drm: kms: expose a connector's requested link depth Mike Lothian
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=20260826163359.4998-16-mike@fireburn.co.uk \
--to=mike@fireburn.co.uk \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=airlied@gmail.com \
--cc=aliceryhl@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=gary@garyguo.net \
--cc=lina+kernel@asahilina.net \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=lyude@redhat.com \
--cc=mkchauras@gmail.com \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=simona@ffwll.ch \
--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