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 kernel::c_str; 36 use kernel::debugfs::{Dir, File}; 37 use kernel::new_mutex; 38 use kernel::prelude::*; 39 use kernel::sizes::*; 40 use kernel::sync::atomic::{Atomic, Relaxed}; 41 use kernel::sync::Mutex; 42 use kernel::{acpi, device::Core, of, platform, str::CString, types::ARef}; 43 44 kernel::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] 53 struct 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)] 71 struct Inner { 72 x: u32, 73 y: u32, 74 } 75 76 impl FromStr for Inner { 77 type Err = Error; from_str(s: &str) -> Result<Self>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 97 kernel::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 104 impl 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 probe( pdev: &platform::Device<Core>, _info: Option<&Self::IdInfo>, ) -> impl PinInit<Self, Error>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 126 impl RustDebugFs { build_counter(dir: &Dir) -> impl PinInit<File<Atomic<usize>>> + '_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 build_inner(dir: &Dir) -> impl PinInit<File<Mutex<Inner>>> + '_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 new(pdev: &platform::Device<Core>) -> impl PinInit<Self, Error> + '_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 } 164