mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 14:30:06 -04:00
rust: device: Add child accessor and iterator
Allow Rust drivers to access children of a fwnode either by name or by iterating over all of them. In C, there is the function `fwnode_get_next_child_node` for iteration and the macro `fwnode_for_each_child_node` that helps with handling the pointers. Instead of a macro, a native iterator is used in Rust such that regular for-loops can be used. Tested-by: Dirk Behme <dirk.behme@de.bosch.com> Signed-off-by: Remo Senekowitsch <remo@buenzli.dev> Link: https://lore.kernel.org/r/20250616154511.1862909-2-remo@buenzli.dev Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
committed by
Danilo Krummrich
parent
63dafeb392
commit
c942dba380
@@ -190,6 +190,62 @@ pub fn property_read<'fwnode, 'name, T: Property>(
|
||||
name,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns first matching named child node handle.
|
||||
pub fn get_child_by_name(&self, name: &CStr) -> Option<ARef<Self>> {
|
||||
// SAFETY: `self` and `name` are valid by their type invariants.
|
||||
let child =
|
||||
unsafe { bindings::fwnode_get_named_child_node(self.as_raw(), name.as_char_ptr()) };
|
||||
if child.is_null() {
|
||||
return None;
|
||||
}
|
||||
// SAFETY:
|
||||
// - `fwnode_get_named_child_node` returns a pointer with its refcount
|
||||
// incremented.
|
||||
// - That increment is relinquished, i.e. the underlying object is not
|
||||
// used anymore except via the newly created `ARef`.
|
||||
Some(unsafe { Self::from_raw(child) })
|
||||
}
|
||||
|
||||
/// Returns an iterator over a node's children.
|
||||
pub fn children<'a>(&'a self) -> impl Iterator<Item = ARef<FwNode>> + 'a {
|
||||
let mut prev: Option<ARef<FwNode>> = None;
|
||||
|
||||
core::iter::from_fn(move || {
|
||||
let prev_ptr = match prev.take() {
|
||||
None => ptr::null_mut(),
|
||||
Some(prev) => {
|
||||
// We will pass `prev` to `fwnode_get_next_child_node`,
|
||||
// which decrements its refcount, so we use
|
||||
// `ARef::into_raw` to avoid decrementing the refcount
|
||||
// twice.
|
||||
let prev = ARef::into_raw(prev);
|
||||
prev.as_ptr().cast()
|
||||
}
|
||||
};
|
||||
// SAFETY:
|
||||
// - `self.as_raw()` is valid by its type invariant.
|
||||
// - `prev_ptr` may be null, which is allowed and corresponds to
|
||||
// getting the first child. Otherwise, `prev_ptr` is valid, as it
|
||||
// is the stored return value from the previous invocation.
|
||||
// - `prev_ptr` has its refount incremented.
|
||||
// - The increment of `prev_ptr` is relinquished, i.e. the
|
||||
// underlying object won't be used anymore.
|
||||
let next = unsafe { bindings::fwnode_get_next_child_node(self.as_raw(), prev_ptr) };
|
||||
if next.is_null() {
|
||||
return None;
|
||||
}
|
||||
// SAFETY:
|
||||
// - `next` is valid because `fwnode_get_next_child_node` returns a
|
||||
// pointer with its refcount incremented.
|
||||
// - That increment is relinquished, i.e. the underlying object
|
||||
// won't be used anymore, except via the newly created
|
||||
// `ARef<Self>`.
|
||||
let next = unsafe { FwNode::from_raw(next) };
|
||||
prev = Some(next.clone());
|
||||
Some(next)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: Instances of `FwNode` are always reference-counted.
|
||||
|
||||
Reference in New Issue
Block a user