Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Remo Senekowitsch and committed by
Danilo Krummrich
a2801aff 19272b37

+86
+1
MAINTAINERS
··· 7366 7366 F: include/linux/sysfs.h 7367 7367 F: lib/kobj* 7368 7368 F: rust/kernel/device.rs 7369 + F: rust/kernel/device/ 7369 7370 F: rust/kernel/device_id.rs 7370 7371 F: rust/kernel/devres.rs 7371 7372 F: rust/kernel/driver.rs
+1
rust/helpers/helpers.c
··· 30 30 #include "platform.c" 31 31 #include "pci.c" 32 32 #include "pid_namespace.c" 33 + #include "property.c" 33 34 #include "rbtree.c" 34 35 #include "rcu.c" 35 36 #include "refcount.c"
+8
rust/helpers/property.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/property.h> 4 + 5 + void rust_helper_fwnode_handle_put(struct fwnode_handle *fwnode) 6 + { 7 + fwnode_handle_put(fwnode); 8 + }
+2
rust/kernel/device.rs
··· 14 14 #[cfg(CONFIG_PRINTK)] 15 15 use crate::c_str; 16 16 17 + pub mod property; 18 + 17 19 /// A reference-counted device. 18 20 /// 19 21 /// This structure represents the Rust abstraction for a C `struct device`. This implementation
+74
rust/kernel/device/property.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! Unified device property interface. 4 + //! 5 + //! C header: [`include/linux/property.h`](srctree/include/linux/property.h) 6 + 7 + use core::ptr; 8 + 9 + use crate::{ 10 + bindings, 11 + types::{ARef, Opaque}, 12 + }; 13 + 14 + /// A reference-counted fwnode_handle. 15 + /// 16 + /// This structure represents the Rust abstraction for a 17 + /// C `struct fwnode_handle`. This implementation abstracts the usage of an 18 + /// already existing C `struct fwnode_handle` within Rust code that we get 19 + /// passed from the C side. 20 + /// 21 + /// # Invariants 22 + /// 23 + /// A `FwNode` instance represents a valid `struct fwnode_handle` created by the 24 + /// C portion of the kernel. 25 + /// 26 + /// Instances of this type are always reference-counted, that is, a call to 27 + /// `fwnode_handle_get` ensures that the allocation remains valid at least until 28 + /// the matching call to `fwnode_handle_put`. 29 + #[repr(transparent)] 30 + pub struct FwNode(Opaque<bindings::fwnode_handle>); 31 + 32 + impl FwNode { 33 + /// # Safety 34 + /// 35 + /// Callers must ensure that: 36 + /// - The reference count was incremented at least once. 37 + /// - They relinquish that increment. That is, if there is only one 38 + /// increment, callers must not use the underlying object anymore -- it is 39 + /// only safe to do so via the newly created `ARef<FwNode>`. 40 + #[expect(dead_code)] 41 + unsafe fn from_raw(raw: *mut bindings::fwnode_handle) -> ARef<Self> { 42 + // SAFETY: As per the safety requirements of this function: 43 + // - `NonNull::new_unchecked`: 44 + // - `raw` is not null. 45 + // - `ARef::from_raw`: 46 + // - `raw` has an incremented refcount. 47 + // - that increment is relinquished, i.e. it won't be decremented 48 + // elsewhere. 49 + // CAST: It is safe to cast from a `*mut fwnode_handle` to 50 + // `*mut FwNode`, because `FwNode` is defined as a 51 + // `#[repr(transparent)]` wrapper around `fwnode_handle`. 52 + unsafe { ARef::from_raw(ptr::NonNull::new_unchecked(raw.cast())) } 53 + } 54 + 55 + /// Obtain the raw `struct fwnode_handle *`. 56 + pub(crate) fn as_raw(&self) -> *mut bindings::fwnode_handle { 57 + self.0.get() 58 + } 59 + } 60 + 61 + // SAFETY: Instances of `FwNode` are always reference-counted. 62 + unsafe impl crate::types::AlwaysRefCounted for FwNode { 63 + fn inc_ref(&self) { 64 + // SAFETY: The existence of a shared reference guarantees that the 65 + // refcount is non-zero. 66 + unsafe { bindings::fwnode_handle_get(self.as_raw()) }; 67 + } 68 + 69 + unsafe fn dec_ref(obj: ptr::NonNull<Self>) { 70 + // SAFETY: The safety requirements guarantee that the refcount is 71 + // non-zero. 72 + unsafe { bindings::fwnode_handle_put(obj.cast().as_ptr()) } 73 + } 74 + }