[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAGSQo02rWt1nDOMeMXR1+nB9we59O-VR4annwrtOQSA+mWoDeA@mail.gmail.com>
Date: Wed, 9 Jul 2025 16:35:01 -0700
From: Matthew Maurer <mmaurer@...gle.com>
To: Danilo Krummrich <dakr@...nel.org>
Cc: Miguel Ojeda <ojeda@...nel.org>, Alex Gaynor <alex.gaynor@...il.com>,
Boqun Feng <boqun.feng@...il.com>, Gary Guo <gary@...yguo.net>,
Björn Roy Baron <bjorn3_gh@...tonmail.com>,
Andreas Hindborg <a.hindborg@...nel.org>, Alice Ryhl <aliceryhl@...gle.com>,
Trevor Gross <tmgross@...ch.edu>, Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
"Rafael J. Wysocki" <rafael@...nel.org>, Sami Tolvanen <samitolvanen@...gle.com>,
Timur Tabi <ttabi@...dia.com>, Benno Lossin <lossin@...nel.org>, linux-kernel@...r.kernel.org,
rust-for-linux@...r.kernel.org
Subject: Re: [PATCH v9 5/5] rust: samples: Add debugfs sample
> Keep it simple, Create some driver private data in probe() and export a couple
> of fields of this driver private data through debugfs.
>
> If you really want to showcase that those values can change, queue some work and
> modify the counter and / or the Inner type that is protected by a mutex.
I've included an example of what a simplified sample of the sort you
asked for might look like below. I'll include it in the updated series
unless someone wants the original functionality.
Provides an example of using the Rust DebugFS bindings.
Signed-off-by: Matthew Maurer <mmaurer@...gle.com>
---
MAINTAINERS | 1 +
samples/rust/Kconfig | 11 +++
samples/rust/Makefile | 1 +
samples/rust/rust_debugfs.rs | 136 +++++++++++++++++++++++++++++++++++
4 files changed, 149 insertions(+)
create mode 100644 samples/rust/rust_debugfs.rs
diff --git a/MAINTAINERS b/MAINTAINERS
index 1427af9d9779..0d9cb77b54b4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7376,6 +7376,7 @@ F: rust/kernel/devres.rs
F: rust/kernel/driver.rs
F: rust/kernel/faux.rs
F: rust/kernel/platform.rs
+F: samples/rust/rust_debugfs.rs
F: samples/rust/rust_driver_platform.rs
F: samples/rust/rust_driver_faux.rs
diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig
index 7f7371a004ee..01101db41ae3 100644
--- a/samples/rust/Kconfig
+++ b/samples/rust/Kconfig
@@ -62,6 +62,17 @@ config SAMPLE_RUST_DMA
If unsure, say N.
+config SAMPLE_RUST_DEBUGFS
+ tristate "DebugFS Test Module"
+ depends on DEBUG_FS
+ help
+ This option builds the Rust DebugFS Test module sample.
+
+ To compile this as a module, choose M here:
+ the module will be called rust_debugfs.
+
+ If unsure, say N.
+
config SAMPLE_RUST_DRIVER_PCI
tristate "PCI Driver"
depends on PCI
diff --git a/samples/rust/Makefile b/samples/rust/Makefile
index bd2faad63b4f..61276222a99f 100644
--- a/samples/rust/Makefile
+++ b/samples/rust/Makefile
@@ -4,6 +4,7 @@ ccflags-y += -I$(src) #
needed for trace events
obj-$(CONFIG_SAMPLE_RUST_MINIMAL) += rust_minimal.o
obj-$(CONFIG_SAMPLE_RUST_MISC_DEVICE) += rust_misc_device.o
obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o
+obj-$(CONFIG_SAMPLE_RUST_DEBUGFS) += rust_debugfs.o
obj-$(CONFIG_SAMPLE_RUST_DMA) += rust_dma.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) += rust_driver_pci.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) += rust_driver_platform.o
diff --git a/samples/rust/rust_debugfs.rs b/samples/rust/rust_debugfs.rs
new file mode 100644
index 000000000000..47b337f2e960
--- /dev/null
+++ b/samples/rust/rust_debugfs.rs
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2025 Google LLC.
+
+//! Sample DebugFS exporting platform driver
+//!
+//! To successfully probe this driver with ACPI, use an ssdt that looks like
+//!
+//! ```dsl
+//! DefinitionBlock ("", "SSDT", 2, "TEST", "VIRTACPI", 0x00000001)
+//! {
+//! Scope (\_SB)
+//! {
+//! Device (T432)
+//! {
+//! Name (_HID, "LNUXDEBF") // ACPI hardware ID to match
+//! Name (_UID, 1)
+//! Name (_STA, 0x0F) // Device present, enabled
+//! Name (_DSD, Package () { // Sample attribute
+//! ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+//! Package() {
+//! Package(2) {"compatible", "sample-debugfs"}
+//! }
+//! })
+//! Name (_CRS, ResourceTemplate ()
+//! {
+//! Memory32Fixed (ReadWrite, 0xFED00000, 0x1000)
+//! })
+//! }
+//! }
+//! }
+//! ```
+
+use core::sync::atomic::AtomicUsize;
+use core::sync::atomic::Ordering;
+use kernel::c_str;
+use kernel::debugfs::{Dir, File};
+use kernel::new_mutex;
+use kernel::prelude::*;
+use kernel::sync::Mutex;
+
+use kernel::{acpi, device::Core, of, platform, str::CString, types::ARef};
+
+kernel::module_platform_driver! {
+ type: RustDebugFs,
+ name: "rust_debugfs",
+ authors: ["Matthew Maurer"],
+ description: "Rust DebugFS usage sample",
+ license: "GPL",
+}
+
+#[pin_data]
+struct RustDebugFs {
+ pdev: ARef<platform::Device>,
+ // As we only hold these for drop effect (to remove the
directory/files) we have a leading
+ // underscore to indicate to the compiler that we don't expect to
use this field directly.
+ _debugfs: Dir,
+ #[pin]
+ _compatible: File<CString>,
+ #[pin]
+ counter: File<AtomicUsize>,
+ #[pin]
+ inner: File<Mutex<Inner>>,
+}
+
+#[derive(Debug)]
+struct Inner {
+ x: u32,
+ y: u32,
+}
+
+kernel::acpi_device_table!(
+ ACPI_TABLE,
+ MODULE_ACPI_TABLE,
+ <RustDebugFs as platform::Driver>::IdInfo,
+ [(acpi::DeviceId::new(c_str!("LNUXDEBF")), ())]
+);
+
+impl platform::Driver for RustDebugFs {
+ type IdInfo = ();
+ const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
+ const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> =
Some(&ACPI_TABLE);
+
+ fn probe(
+ pdev: &platform::Device<Core>,
+ _info: Option<&Self::IdInfo>,
+ ) -> Result<Pin<KBox<Self>>> {
+ let result = KBox::try_pin_init(RustDebugFs::new(pdev), GFP_KERNEL)?;
+ // We can still mutate fields through the files which are
atomic or mutexed:
+ result.counter.store(91, Ordering::Relaxed);
+ {
+ let mut guard = result.inner.lock();
+ guard.x = guard.y;
+ guard.y = 42;
+ }
+ Ok(result)
+ }
+}
+
+impl RustDebugFs {
+ fn build_counter(dir: &Dir) -> impl PinInit<File<AtomicUsize>> + use<'_> {
+ dir.fmt_file(c_str!("counter"), AtomicUsize::new(0), &|counter, fmt| {
+ writeln!(fmt, "{}", counter.load(Ordering::Relaxed))
+ })
+ }
+
+ fn build_inner(dir: &Dir) -> impl PinInit<File<Mutex<Inner>>> + use<'_> {
+ dir.fmt_file(
+ c_str!("pair"),
+ new_mutex!(Inner { x: 3, y: 10 }),
+ &|i, fmt| writeln!(fmt, "{:?}", *i.lock()),
+ )
+ }
+
+ fn new(pdev: &platform::Device<Core>) -> impl PinInit<Self,
Error> + use<'_> {
+ let debugfs = Dir::new(c_str!("sample_debugfs"));
+ let dev = pdev.as_ref();
+
+ try_pin_init! {
+ Self {
+ _compatible <- debugfs.fmt_file(
+ c_str!("compatible"),
+ dev.fwnode()
+ .ok_or(ENOENT)?
+ .property_read::<CString>(c_str!("compatible"))
+ .required_by(dev)?,
+ &|cs, w| writeln!(w, "{cs:?}"),
+ ),
+ counter <- Self::build_counter(&debugfs),
+ inner <- Self::build_inner(&debugfs),
+ _debugfs: debugfs,
+ pdev: pdev.into(),
+ }
+ }
+ }
+}
--
2.50.0.727.gbf7dc18ff4-goog
Powered by blists - more mailing lists