Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2
3// Copyright (C) 2025 Google LLC.
4
5//! Sample DebugFS exporting platform driver
6//!
7//! To successfully probe this driver with ACPI, use an ssdt that looks like
8//!
9//! ```dsl
10//! DefinitionBlock ("", "SSDT", 2, "TEST", "VIRTACPI", 0x00000001)
11//! {
12//! Scope (\_SB)
13//! {
14//! Device (T432)
15//! {
16//! Name (_HID, "LNUXBEEF") // ACPI hardware ID to match
17//! Name (_UID, 1)
18//! Name (_STA, 0x0F) // Device present, enabled
19//! Name (_DSD, Package () { // Sample attribute
20//! ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
21//! Package() {
22//! Package(2) {"compatible", "sample-debugfs"}
23//! }
24//! })
25//! Name (_CRS, ResourceTemplate ()
26//! {
27//! Memory32Fixed (ReadWrite, 0xFED00000, 0x1000)
28//! })
29//! }
30//! }
31//! }
32//! ```
33
34use core::str::FromStr;
35use kernel::c_str;
36use kernel::debugfs::{Dir, File};
37use kernel::new_mutex;
38use kernel::prelude::*;
39use kernel::sizes::*;
40use kernel::sync::atomic::{Atomic, Relaxed};
41use kernel::sync::Mutex;
42use kernel::{acpi, device::Core, of, platform, str::CString, types::ARef};
43
44kernel::module_platform_driver! {
45 type: RustDebugFs,
46 name: "rust_debugfs",
47 authors: ["Matthew Maurer"],
48 description: "Rust DebugFS usage sample",
49 license: "GPL",
50}
51
52#[pin_data]
53struct RustDebugFs {
54 pdev: ARef<platform::Device>,
55 // As we only hold these for drop effect (to remove the directory/files) we have a leading
56 // underscore to indicate to the compiler that we don't expect to use this field directly.
57 _debugfs: Dir,
58 #[pin]
59 _compatible: File<CString>,
60 #[pin]
61 counter: File<Atomic<usize>>,
62 #[pin]
63 inner: File<Mutex<Inner>>,
64 #[pin]
65 array_blob: File<Mutex<[u8; 4]>>,
66 #[pin]
67 vector_blob: File<Mutex<KVec<u8>>>,
68}
69
70#[derive(Debug)]
71struct Inner {
72 x: u32,
73 y: u32,
74}
75
76impl FromStr for Inner {
77 type Err = Error;
78 fn from_str(s: &str) -> Result<Self> {
79 let mut parts = s.split_whitespace();
80 let x = parts
81 .next()
82 .ok_or(EINVAL)?
83 .parse::<u32>()
84 .map_err(|_| EINVAL)?;
85 let y = parts
86 .next()
87 .ok_or(EINVAL)?
88 .parse::<u32>()
89 .map_err(|_| EINVAL)?;
90 if parts.next().is_some() {
91 return Err(EINVAL);
92 }
93 Ok(Inner { x, y })
94 }
95}
96
97kernel::acpi_device_table!(
98 ACPI_TABLE,
99 MODULE_ACPI_TABLE,
100 <RustDebugFs as platform::Driver>::IdInfo,
101 [(acpi::DeviceId::new(c_str!("LNUXBEEF")), ())]
102);
103
104impl platform::Driver for RustDebugFs {
105 type IdInfo = ();
106 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
107 const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
108
109 fn probe(
110 pdev: &platform::Device<Core>,
111 _info: Option<&Self::IdInfo>,
112 ) -> impl PinInit<Self, Error> {
113 RustDebugFs::new(pdev).pin_chain(|this| {
114 this.counter.store(91, Relaxed);
115 {
116 let mut guard = this.inner.lock();
117 guard.x = guard.y;
118 guard.y = 42;
119 }
120
121 Ok(())
122 })
123 }
124}
125
126impl RustDebugFs {
127 fn build_counter(dir: &Dir) -> impl PinInit<File<Atomic<usize>>> + '_ {
128 dir.read_write_file(c_str!("counter"), Atomic::<usize>::new(0))
129 }
130
131 fn build_inner(dir: &Dir) -> impl PinInit<File<Mutex<Inner>>> + '_ {
132 dir.read_write_file(c_str!("pair"), new_mutex!(Inner { x: 3, y: 10 }))
133 }
134
135 fn new(pdev: &platform::Device<Core>) -> impl PinInit<Self, Error> + '_ {
136 let debugfs = Dir::new(c_str!("sample_debugfs"));
137 let dev = pdev.as_ref();
138
139 try_pin_init! {
140 Self {
141 _compatible <- debugfs.read_only_file(
142 c_str!("compatible"),
143 dev.fwnode()
144 .ok_or(ENOENT)?
145 .property_read::<CString>(c_str!("compatible"))
146 .required_by(dev)?,
147 ),
148 counter <- Self::build_counter(&debugfs),
149 inner <- Self::build_inner(&debugfs),
150 array_blob <- debugfs.read_write_binary_file(
151 c_str!("array_blob"),
152 new_mutex!([0x62, 0x6c, 0x6f, 0x62]),
153 ),
154 vector_blob <- debugfs.read_write_binary_file(
155 c_str!("vector_blob"),
156 new_mutex!(kernel::kvec!(0x42; SZ_4K)?),
157 ),
158 _debugfs: debugfs,
159 pdev: pdev.into(),
160 }
161 }
162 }
163}