at master 4.7 kB view raw
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}