[PATCH 4/6] rust: drm: Wrap ioctl dispatch in UnbindGuard

From: Danilo Krummrich

Date: Wed May 06 2026 - 18:11:26 EST


Run every ioctl handler inside a drm_dev_enter/exit critical section via
UnbindGuard. If the device has been unplugged, the ioctl returns ENODEV
without calling the handler.

A free-function wrapper is added because the macro context prevents
method resolution from inferring the driver type.

Signed-off-by: Danilo Krummrich <dakr@xxxxxxxxxx>
---
rust/kernel/drm/device.rs | 7 +++++++
rust/kernel/drm/ioctl.rs | 13 +++++++++++--
2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index 11edbe6f9f42..0049ea69f716 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -452,6 +452,13 @@ fn drop(&mut self) {
}
}

+/// Free-function equivalent of [`Device::unbind_guard()`] for use in macro contexts where method
+/// resolution cannot infer the driver type.
+#[doc(hidden)]
+pub fn unbind_guard<T: drm::Driver>(dev: &Device<T, Registered>) -> Option<UnbindGuard<'_, T>> {
+ dev.unbind_guard()
+}
+
impl<T: drm::Driver, C: DeviceContext> Deref for Device<T, C> {
type Target = T::Data;

diff --git a/rust/kernel/drm/ioctl.rs b/rust/kernel/drm/ioctl.rs
index cf328101dde4..aa72b44f645d 100644
--- a/rust/kernel/drm/ioctl.rs
+++ b/rust/kernel/drm/ioctl.rs
@@ -87,7 +87,10 @@ pub mod internal {
/// file: &kernel::drm::File<Self::File>,
/// ) -> Result<u32>
/// ```
-/// where `Self` is the drm::drv::Driver implementation these ioctls are being declared within.
+/// where `Self` is the `drm::Driver` implementation these ioctls are being declared within.
+///
+/// The ioctl runs inside a `drm_dev_enter/exit` critical section. If the device has been
+/// unplugged, the ioctl returns `ENODEV` without calling the handler.
///
/// # Examples
///
@@ -134,7 +137,13 @@ macro_rules! declare_drm_ioctls {
// FIXME: Currently there is nothing enforcing that the types of the
// dev/file match the current driver these ioctls are being declared
// for, and it's not clear how to enforce this within the type system.
- let dev = $crate::drm::device::Device::from_raw(raw_dev);
+ let dev = unsafe {
+ $crate::drm::device::Device::from_raw(raw_dev)
+ };
+ let _guard = match $crate::drm::device::unbind_guard(dev) {
+ Some(g) => g,
+ None => return $crate::error::code::ENODEV.to_errno(),
+ };
// SAFETY: The ioctl argument has size `_IOC_SIZE(cmd)`, which we
// asserted above matches the size of this type, and all bit patterns of
// UAPI structs must be valid.
--
2.54.0