mirror of https://github.com/torvalds/linux.git
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>
This commit is contained in:
parent
19272b37aa
commit
a2801affa7
|
|
@ -7366,6 +7366,7 @@ F: include/linux/property.h
|
|||
F: include/linux/sysfs.h
|
||||
F: lib/kobj*
|
||||
F: rust/kernel/device.rs
|
||||
F: rust/kernel/device/
|
||||
F: rust/kernel/device_id.rs
|
||||
F: rust/kernel/devres.rs
|
||||
F: rust/kernel/driver.rs
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "platform.c"
|
||||
#include "pci.c"
|
||||
#include "pid_namespace.c"
|
||||
#include "property.c"
|
||||
#include "rbtree.c"
|
||||
#include "rcu.c"
|
||||
#include "refcount.c"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/property.h>
|
||||
|
||||
void rust_helper_fwnode_handle_put(struct fwnode_handle *fwnode)
|
||||
{
|
||||
fwnode_handle_put(fwnode);
|
||||
}
|
||||
|
|
@ -14,6 +14,8 @@
|
|||
#[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
|
||||
|
|
|
|||
|
|
@ -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()) }
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue