[PATCH v2 6/9] rust: drm: add DrmSeqShow seq_file adapter

Alvin Sun <[email protected]> Fri, 31 Jul 2026 01:05:44 +0800
Newsgroups dev.linux.lists.driver-core,org.freedesktop.lists.dri-devel,org.kernel.feeds.b4-sent,org.kernel.vger.rust-for-linux
Message-ID <[email protected]>
Add DrmSeqShow trait and its SeqShow blanket impl for Device<T, Normal>,
enabling Rust DRM drivers to expose device state via debugfs seq_file
entries. Device registration data is kept alive for the duration of
each seq_file read.

Signed-off-by: Alvin Sun <[email protected]>
---
 rust/kernel/drm/debugfs.rs | 49 ++++++++++++++++++++++++++++++++++++++++++++++
 rust/kernel/drm/mod.rs     |  1 +
 2 files changed, 50 insertions(+)

diff --git a/rust/kernel/drm/debugfs.rs b/rust/kernel/drm/debugfs.rs
new file mode 100644
index 0000000000000..26f3b400e24ac
--- /dev/null
+++ b/rust/kernel/drm/debugfs.rs
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+
+//! DRM-specific debugfs seq_file helpers.
+
+use crate::{
+    debugfs,
+    drm,
+    prelude::*,
+    seq_file,
+    sync::aref::AlwaysRefCounted, //
+};
+use core::ptr::NonNull;
+
+/// Renders DRM device state into a seq_file under SRCU protection.
+///
+/// Pass an implementing type to
+/// [`debugfs::ScopedDir::seq_file`]. The `show`
+/// method receives a [`drm::RegistrationGuard`] that keeps DRM device data alive
+/// for its duration.
+pub trait DrmSeqShow<T: drm::Driver> {
+    /// Writes debugfs output for the file.
+    fn show(guard: &drm::RegistrationGuard<'_, T>, m: &seq_file::SeqFile) -> Result;
+}
+
+impl<S: DrmSeqShow<T>, T: drm::Driver> debugfs::SeqShow<drm::Device<T, drm::Normal>> for S {
+    fn show(dev: &drm::Device<T, drm::Normal>, m: &seq_file::SeqFile) -> Result {
+        // SAFETY: `debugfs_init` runs after `dev->registered = true` is set,
+        // so the `Ioctl` invariant is satisfied. `Normal` and `Ioctl` share
+        // an identical layout.
+        let dev = unsafe { dev.assume_ctx::<drm::Ioctl>() };
+
+        let Some(guard) = dev.registration_guard() else {
+            return Err(ENODEV);
+        };
+        S::show(&guard, m)
+    }
+
+    fn open(dev: &drm::Device<T, drm::Normal>) -> Result {
+        // Hold a device reference so the device is not freed while the file is open.
+        dev.inc_ref();
+        Ok(())
+    }
+
+    unsafe fn release(dev: NonNull<drm::Device<T, drm::Normal>>) {
+        // Drop the reference taken in `open`.
+        // SAFETY: `dev` is valid per this function's safety contract.
+        unsafe { drm::Device::<T>::dec_ref(dev) };
+    }
+}
diff --git a/rust/kernel/drm/mod.rs b/rust/kernel/drm/mod.rs
index fd6ed35bc35a9..5ed2e6bb764eb 100644
--- a/rust/kernel/drm/mod.rs
+++ b/rust/kernel/drm/mod.rs
@@ -2,6 +2,7 @@
 
 //! DRM subsystem abstractions.
 
+pub mod debugfs;
 pub mod device;
 pub mod driver;
 pub mod file;

-- 
2.43.0