summaryrefslogtreecommitdiff
path: root/rust/kernel
diff options
context:
space:
mode:
authorRemo Senekowitsch <remo@buenzli.dev>2025-06-11 12:29:00 +0200
committerDanilo Krummrich <dakr@kernel.org>2025-06-12 23:56:42 +0200
commita2801affa7103862d549050401a9f53b3365fca4 (patch)
treeedbb87db9147201aadb1e63d4f215faa726d6f30 /rust/kernel
parent19272b37aa4f83ca52bdf9c16d5d81bdd1354494 (diff)
rust: device: Create FwNode abstraction for accessing device properties
Accessing device properties is currently done via methods on `Device` itself, using bindings to device_property_* functions. This is sufficient for the existing method property_present. However, it's not sufficient for other device properties we want to access. For example, iterating over child nodes of a device will yield a fwnode_handle. That's not a device, so it wouldn't be possible to read the properties of that child node. Thus, we need an abstraction over fwnode_handle and methods for reading its properties. Add a struct FwNode which abstracts over the C struct fwnode_handle. Implement its reference counting analogous to other Rust abstractions over reference-counted C structs. Subsequent patches will add functionality to access FwNode and read properties with it. Tested-by: Dirk Behme <dirk.behme@de.bosch.com> Signed-off-by: Remo Senekowitsch <remo@buenzli.dev> Link: https://lore.kernel.org/r/20250611102908.212514-2-remo@buenzli.dev [ Add temporary #[expect(dead_code)] to avoid a warning. - Danilo ] Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Diffstat (limited to 'rust/kernel')
-rw-r--r--rust/kernel/device.rs2
-rw-r--r--rust/kernel/device/property.rs74
2 files changed, 76 insertions, 0 deletions
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index dea06b79ecb5..d6237827a936 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -14,6 +14,8 @@ use core::{fmt, marker::PhantomData, ptr};
#[cfg(CONFIG_PRINTK)]
use crate::c_str;
+pub mod property;
+
/// A reference-counted device.
///
/// This structure represents the Rust abstraction for a C `struct device`. This implementation
diff --git a/rust/kernel/device/property.rs b/rust/kernel/device/property.rs
new file mode 100644
index 000000000000..82ef54b54f18
--- /dev/null
+++ b/rust/kernel/device/property.rs
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Unified device property interface.
+//!
+//! C header: [`include/linux/property.h`](srctree/include/linux/property.h)
+
+use core::ptr;
+
+use crate::{
+ bindings,
+ types::{ARef, Opaque},
+};
+
+/// A reference-counted fwnode_handle.
+///
+/// This structure represents the Rust abstraction for a
+/// C `struct fwnode_handle`. This implementation abstracts the usage of an
+/// already existing C `struct fwnode_handle` within Rust code that we get
+/// passed from the C side.
+///
+/// # Invariants
+///
+/// A `FwNode` instance represents a valid `struct fwnode_handle` created by the
+/// C portion of the kernel.
+///
+/// Instances of this type are always reference-counted, that is, a call to
+/// `fwnode_handle_get` ensures that the allocation remains valid at least until
+/// the matching call to `fwnode_handle_put`.
+#[repr(transparent)]
+pub struct FwNode(Opaque<bindings::fwnode_handle>);
+
+impl FwNode {
+ /// # Safety
+ ///
+ /// Callers must ensure that:
+ /// - The reference count was incremented at least once.
+ /// - They relinquish that increment. That is, if there is only one
+ /// increment, callers must not use the underlying object anymore -- it is
+ /// only safe to do so via the newly created `ARef<FwNode>`.
+ #[expect(dead_code)]
+ unsafe fn from_raw(raw: *mut bindings::fwnode_handle) -> ARef<Self> {
+ // SAFETY: As per the safety requirements of this function:
+ // - `NonNull::new_unchecked`:
+ // - `raw` is not null.
+ // - `ARef::from_raw`:
+ // - `raw` has an incremented refcount.
+ // - that increment is relinquished, i.e. it won't be decremented
+ // elsewhere.
+ // CAST: It is safe to cast from a `*mut fwnode_handle` to
+ // `*mut FwNode`, because `FwNode` is defined as a
+ // `#[repr(transparent)]` wrapper around `fwnode_handle`.
+ unsafe { ARef::from_raw(ptr::NonNull::new_unchecked(raw.cast())) }
+ }
+
+ /// Obtain the raw `struct fwnode_handle *`.
+ pub(crate) fn as_raw(&self) -> *mut bindings::fwnode_handle {
+ self.0.get()
+ }
+}
+
+// SAFETY: Instances of `FwNode` are always reference-counted.
+unsafe impl crate::types::AlwaysRefCounted for FwNode {
+ fn inc_ref(&self) {
+ // SAFETY: The existence of a shared reference guarantees that the
+ // refcount is non-zero.
+ unsafe { bindings::fwnode_handle_get(self.as_raw()) };
+ }
+
+ unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
+ // SAFETY: The safety requirements guarantee that the refcount is
+ // non-zero.
+ unsafe { bindings::fwnode_handle_put(obj.cast().as_ptr()) }
+ }
+}