Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/samples/rust/rust_debugfs.rs
29266 views
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
34
use core::str::FromStr;
35
use core::sync::atomic::AtomicUsize;
36
use core::sync::atomic::Ordering;
37
use kernel::c_str;
38
use kernel::debugfs::{Dir, File};
39
use kernel::new_mutex;
40
use kernel::prelude::*;
41
use kernel::sync::Mutex;
42
43
use kernel::{acpi, device::Core, of, platform, str::CString, types::ARef};
44
45
kernel::module_platform_driver! {
46
type: RustDebugFs,
47
name: "rust_debugfs",
48
authors: ["Matthew Maurer"],
49
description: "Rust DebugFS usage sample",
50
license: "GPL",
51
}
52
53
#[pin_data]
54
struct RustDebugFs {
55
pdev: ARef<platform::Device>,
56
// As we only hold these for drop effect (to remove the directory/files) we have a leading
57
// underscore to indicate to the compiler that we don't expect to use this field directly.
58
_debugfs: Dir,
59
#[pin]
60
_compatible: File<CString>,
61
#[pin]
62
counter: File<AtomicUsize>,
63
#[pin]
64
inner: File<Mutex<Inner>>,
65
}
66
67
#[derive(Debug)]
68
struct Inner {
69
x: u32,
70
y: u32,
71
}
72
73
impl FromStr for Inner {
74
type Err = Error;
75
fn from_str(s: &str) -> Result<Self> {
76
let mut parts = s.split_whitespace();
77
let x = parts
78
.next()
79
.ok_or(EINVAL)?
80
.parse::<u32>()
81
.map_err(|_| EINVAL)?;
82
let y = parts
83
.next()
84
.ok_or(EINVAL)?
85
.parse::<u32>()
86
.map_err(|_| EINVAL)?;
87
if parts.next().is_some() {
88
return Err(EINVAL);
89
}
90
Ok(Inner { x, y })
91
}
92
}
93
94
kernel::acpi_device_table!(
95
ACPI_TABLE,
96
MODULE_ACPI_TABLE,
97
<RustDebugFs as platform::Driver>::IdInfo,
98
[(acpi::DeviceId::new(c_str!("LNUXBEEF")), ())]
99
);
100
101
impl platform::Driver for RustDebugFs {
102
type IdInfo = ();
103
const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
104
const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
105
106
fn probe(
107
pdev: &platform::Device<Core>,
108
_info: Option<&Self::IdInfo>,
109
) -> Result<Pin<KBox<Self>>> {
110
let result = KBox::try_pin_init(RustDebugFs::new(pdev), GFP_KERNEL)?;
111
// We can still mutate fields through the files which are atomic or mutexed:
112
result.counter.store(91, Ordering::Relaxed);
113
{
114
let mut guard = result.inner.lock();
115
guard.x = guard.y;
116
guard.y = 42;
117
}
118
Ok(result)
119
}
120
}
121
122
impl RustDebugFs {
123
fn build_counter(dir: &Dir) -> impl PinInit<File<AtomicUsize>> + '_ {
124
dir.read_write_file(c_str!("counter"), AtomicUsize::new(0))
125
}
126
127
fn build_inner(dir: &Dir) -> impl PinInit<File<Mutex<Inner>>> + '_ {
128
dir.read_write_file(c_str!("pair"), new_mutex!(Inner { x: 3, y: 10 }))
129
}
130
131
fn new(pdev: &platform::Device<Core>) -> impl PinInit<Self, Error> + '_ {
132
let debugfs = Dir::new(c_str!("sample_debugfs"));
133
let dev = pdev.as_ref();
134
135
try_pin_init! {
136
Self {
137
_compatible <- debugfs.read_only_file(
138
c_str!("compatible"),
139
dev.fwnode()
140
.ok_or(ENOENT)?
141
.property_read::<CString>(c_str!("compatible"))
142
.required_by(dev)?,
143
),
144
counter <- Self::build_counter(&debugfs),
145
inner <- Self::build_inner(&debugfs),
146
_debugfs: debugfs,
147
pdev: pdev.into(),
148
}
149
}
150
}
151
}
152
153