]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
rust/kernel: Add faux device bindings
authorLyude Paul <lyude@redhat.com>
Mon, 10 Feb 2025 12:30:26 +0000 (13:30 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Feb 2025 15:58:58 +0000 (16:58 +0100)
This introduces a module for working with faux devices in rust, along with
adding sample code to show how the API is used. Unlike other types of
devices, we don't provide any hooks for device probe/removal - since these
are optional for the faux API and are unnecessary in rust.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Cc: MaĆ­ra Canal <mairacanal@riseup.net>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
Acked-by: Danilo Krummrich <dakr@kernel.org>
Link: https://lore.kernel.org/r/2025021026-exert-accent-b4c6@gregkh
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
MAINTAINERS
rust/bindings/bindings_helper.h
rust/kernel/faux.rs [new file with mode: 0644]
rust/kernel/lib.rs
samples/rust/Kconfig
samples/rust/Makefile
samples/rust/rust_driver_faux.rs [new file with mode: 0644]

index 25c86f47353de25c88291cc7fd6c4e9bfb12d5c4..19ea159b2309154dba43a343fa993c8ccb013c66 100644 (file)
@@ -7116,8 +7116,10 @@ F:       rust/kernel/device.rs
 F:     rust/kernel/device_id.rs
 F:     rust/kernel/devres.rs
 F:     rust/kernel/driver.rs
+F:     rust/kernel/faux.rs
 F:     rust/kernel/platform.rs
 F:     samples/rust/rust_driver_platform.rs
+F:     samples/rust/rust_driver_faux.rs
 
 DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS)
 M:     Nishanth Menon <nm@ti.com>
index 55354e4dec14e9859ace33a6b0afb6d9a6653ea1..f46cf3bb70695b0e38ef27d5e630afe9d265f27b 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/blk_types.h>
 #include <linux/blkdev.h>
 #include <linux/cred.h>
+#include <linux/device/faux.h>
 #include <linux/errname.h>
 #include <linux/ethtool.h>
 #include <linux/file.h>
diff --git a/rust/kernel/faux.rs b/rust/kernel/faux.rs
new file mode 100644 (file)
index 0000000..5acc0c0
--- /dev/null
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+//! Abstractions for the faux bus.
+//!
+//! This module provides bindings for working with faux devices in kernel modules.
+//!
+//! C header: [`include/linux/device/faux.h`]
+
+use crate::{bindings, device, error::code::*, prelude::*};
+use core::ptr::{addr_of_mut, null, null_mut, NonNull};
+
+/// The registration of a faux device.
+///
+/// This type represents the registration of a [`struct faux_device`]. When an instance of this type
+/// is dropped, its respective faux device will be unregistered from the system.
+///
+/// # Invariants
+///
+/// `self.0` always holds a valid pointer to an initialized and registered [`struct faux_device`].
+///
+/// [`struct faux_device`]: srctree/include/linux/device/faux.h
+#[repr(transparent)]
+pub struct Registration(NonNull<bindings::faux_device>);
+
+impl Registration {
+    /// Create and register a new faux device with the given name.
+    pub fn new(name: &CStr) -> Result<Self> {
+        // SAFETY:
+        // - `name` is copied by this function into its own storage
+        // - `faux_ops` is safe to leave NULL according to the C API
+        let dev = unsafe { bindings::faux_device_create(name.as_char_ptr(), null_mut(), null()) };
+
+        // The above function will return either a valid device, or NULL on failure
+        // INVARIANT: The device will remain registered until faux_device_destroy() is called, which
+        // happens in our Drop implementation.
+        Ok(Self(NonNull::new(dev).ok_or(ENODEV)?))
+    }
+
+    fn as_raw(&self) -> *mut bindings::faux_device {
+        self.0.as_ptr()
+    }
+}
+
+impl AsRef<device::Device> for Registration {
+    fn as_ref(&self) -> &device::Device {
+        // SAFETY: The underlying `device` in `faux_device` is guaranteed by the C API to be
+        // a valid initialized `device`.
+        unsafe { device::Device::as_ref(addr_of_mut!((*self.as_raw()).dev)) }
+    }
+}
+
+impl Drop for Registration {
+    fn drop(&mut self) {
+        // SAFETY: `self.0` is a valid registered faux_device via our type invariants.
+        unsafe { bindings::faux_device_destroy(self.as_raw()) }
+    }
+}
+
+// SAFETY: The faux device API is thread-safe as guaranteed by the device core, as long as
+// faux_device_destroy() is guaranteed to only be called once - which is guaranteed by our type not
+// having Copy/Clone.
+unsafe impl Send for Registration {}
+
+// SAFETY: The faux device API is thread-safe as guaranteed by the device core, as long as
+// faux_device_destroy() is guaranteed to only be called once - which is guaranteed by our type not
+// having Copy/Clone.
+unsafe impl Sync for Registration {}
index 496ed32b0911a9fdbce5d26738b9cf7ef910b269..398242f92a961c3a445d681c65449047a847968a 100644 (file)
@@ -46,6 +46,7 @@ pub mod device_id;
 pub mod devres;
 pub mod driver;
 pub mod error;
+pub mod faux;
 #[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]
 pub mod firmware;
 pub mod fs;
index 918dbead2c0b4d2bda1aac0eff342b9e3654688d..3b6eae84b2977d7e33be6d65d278f5739f07672b 100644 (file)
@@ -61,6 +61,16 @@ config SAMPLE_RUST_DRIVER_PLATFORM
 
          If unsure, say N.
 
+config SAMPLE_RUST_DRIVER_FAUX
+       tristate "Faux Driver"
+       help
+         This option builds the Rust Faux driver sample.
+
+         To compile this as a module, choose M here:
+         the module will be called rust_driver_faux.
+
+         If unsure, say N.
+
 config SAMPLE_RUST_HOSTPROGS
        bool "Host programs"
        help
index 5a8ab0df0567cb3f5acc92b7e927b61087c5834a..0dbc6d90f1ef9cd2a51c65666c6262abf417b276 100644 (file)
@@ -6,6 +6,7 @@ obj-$(CONFIG_SAMPLE_RUST_MISC_DEVICE)           += rust_misc_device.o
 obj-$(CONFIG_SAMPLE_RUST_PRINT)                        += rust_print.o
 obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI)           += rust_driver_pci.o
 obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM)      += rust_driver_platform.o
+obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX)          += rust_driver_faux.o
 
 rust_print-y := rust_print_main.o rust_print_events.o
 
diff --git a/samples/rust/rust_driver_faux.rs b/samples/rust/rust_driver_faux.rs
new file mode 100644 (file)
index 0000000..048c6cb
--- /dev/null
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+//! Rust faux device sample.
+
+use kernel::{c_str, faux, prelude::*, Module};
+
+module! {
+    type: SampleModule,
+    name: "rust_faux_driver",
+    author: "Lyude Paul",
+    description: "Rust faux device sample",
+    license: "GPL",
+}
+
+struct SampleModule {
+    _reg: faux::Registration,
+}
+
+impl Module for SampleModule {
+    fn init(_module: &'static ThisModule) -> Result<Self> {
+        pr_info!("Initialising Rust Faux Device Sample\n");
+
+        let reg = faux::Registration::new(c_str!("rust-faux-sample-device"))?;
+
+        dev_info!(reg.as_ref(), "Hello from faux device!\n");
+
+        Ok(Self { _reg: reg })
+    }
+}