[PATCH v3 5/8] rust: drm: add debugfs_init callback to Driver trait

Alvin Sun <[email protected]>
Newsgroups org.kernel.vger.rust-for-linux,dev.linux.lists.driver-core,org.freedesktop.lists.dri-devel,org.kernel.feeds.b4-sent
Message-ID <[email protected]>
Add debugfs_init method to the Driver trait, enabling Rust DRM drivers
to populate debugfs entries during device registration.

Signed-off-by: Alvin Sun <[email protected]>
---
 rust/kernel/drm/device.rs | 41 ++++++++++++++++++++++++++++++++++++++++-
 rust/kernel/drm/driver.rs | 11 +++++++++++
 2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index 7a3a0e21e9557..35fd514fec274 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -7,6 +7,7 @@
 use crate::{
     alloc::allocator::Kmalloc,
     bindings,
+    debugfs,
     device,
     drm::{
         self,
@@ -170,7 +171,7 @@ const fn compute_features() -> u32 {
         release: Some(Device::<T>::release),
         master_set: None,
         master_drop: None,
-        debugfs_init: None,
+        debugfs_init: Some(Device::<T>::debugfs_init_callback),
 
         gem_create_object: T::Object::ALLOC_OPS.gem_create_object,
         prime_handle_to_fd: T::Object::ALLOC_OPS.prime_handle_to_fd,
@@ -353,6 +354,44 @@ extern "C" fn release(ptr: *mut bindings::drm_device) {
         unsafe { core::ptr::drop_in_place(this) };
     }
 
+    /// C callback for `drm_driver.debugfs_init`.
+    ///
+    /// # Safety
+    ///
+    /// The DRM core guarantees that `minor` is valid and non-null, that
+    /// `minor->dev` is a valid `drm_device` embedded in a `Device<T>`.
+    unsafe extern "C" fn debugfs_init_callback(minor: *mut bindings::drm_minor) {
+        // SAFETY: `minor` is valid and non-null per the function's safety
+        // precondition.
+        let dev_ptr = unsafe { (*minor).dev };
+        // SAFETY: `minor` is valid per the function's safety precondition.
+        let debugfs_root = unsafe { (*minor).debugfs_root };
+
+        // Debugfs may be disabled.
+        if debugfs_root.is_null() {
+            return;
+        }
+
+        // SAFETY: `dev_ptr` points to a valid `drm_device` embedded in
+        // `Device<T>`.
+        let dev = unsafe { Self::from_raw(dev_ptr) };
+
+        // SAFETY: The device is in the registered state per the function's
+        // safety precondition.
+        let dev = unsafe { dev.assume_ctx::<Registered>() };
+
+        dev.registration_data_with(|reg_data| {
+            // SAFETY: `debugfs_root` is valid as long as the DRM device is
+            // registered. The debugfs proxy fops wait for in-progress file
+            // operations and block new ones during `debugfs_remove()`, so no
+            // access to `reg_data` can outlive it. `debugfs_remove()` runs
+            // before `Registration::drop` frees `reg_data`.
+            let dir = unsafe { debugfs::ScopeRef::new(debugfs_root, reg_data) };
+
+            T::debugfs_init(&dir);
+        });
+    }
+
     /// Change the [`DeviceContext`] for a [`Device`].
     ///
     /// # Safety
diff --git a/rust/kernel/drm/driver.rs b/rust/kernel/drm/driver.rs
index 08b2a318cf02a..f850b11fd5c53 100644
--- a/rust/kernel/drm/driver.rs
+++ b/rust/kernel/drm/driver.rs
@@ -6,6 +6,7 @@
 
 use crate::{
     bindings,
+    debugfs,
     device,
     drm,
     error::to_result,
@@ -138,6 +139,16 @@ pub trait Driver {
     /// usable from the render node (i.e. marked DRM_RENDER_ALLOW), whereas
     /// userspace processes using the master node can invoke any ioctl.
     const FEAT_RENDER: bool = false;
+
+    /// Populates debugfs for this DRM device.
+    ///
+    /// Called by the DRM core during registration. The `ScopeRef` provides
+    /// access to the device's `RegistrationData` for creating debugfs files.
+    fn debugfs_init(_dir: &debugfs::ScopeRef<'_, Self::RegistrationData<'_>>)
+    where
+        Self: Sized,
+    {
+    }
 }
 
 /// The registration type of a `drm::Device`.

-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.