rust: device: Enable printing fwnode name and path
Add two new public methods `display_name` and `display_path` to `FwNode`. They can be used by driver authors for logging purposes. In addition, they will be used by core property abstractions for automatic logging, for example when a driver attempts to read a required but missing property. 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-5-remo@buenzli.dev [ Remove #[expect(dead_code)] from FwNode::from_raw(). - Danilo ] Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
committed by
Danilo Krummrich
parent
d3393e8450
commit
ecea245981
@@ -38,7 +38,6 @@ impl FwNode {
|
||||
/// - 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`:
|
||||
@@ -58,6 +57,32 @@ impl FwNode {
|
||||
self.0.get()
|
||||
}
|
||||
|
||||
/// Returns an object that implements [`Display`](core::fmt::Display) for
|
||||
/// printing the name of a node.
|
||||
///
|
||||
/// This is an alternative to the default `Display` implementation, which
|
||||
/// prints the full path.
|
||||
pub fn display_name(&self) -> impl core::fmt::Display + '_ {
|
||||
struct FwNodeDisplayName<'a>(&'a FwNode);
|
||||
|
||||
impl core::fmt::Display for FwNodeDisplayName<'_> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
// SAFETY: `self` is valid by its type invariant.
|
||||
let name = unsafe { bindings::fwnode_get_name(self.0.as_raw()) };
|
||||
if name.is_null() {
|
||||
return Ok(());
|
||||
}
|
||||
// SAFETY:
|
||||
// - `fwnode_get_name` returns null or a valid C string.
|
||||
// - `name` was checked to be non-null.
|
||||
let name = unsafe { CStr::from_char_ptr(name) };
|
||||
write!(f, "{name}")
|
||||
}
|
||||
}
|
||||
|
||||
FwNodeDisplayName(self)
|
||||
}
|
||||
|
||||
/// Checks if property is present or not.
|
||||
pub fn property_present(&self, name: &CStr) -> bool {
|
||||
// SAFETY: By the invariant of `CStr`, `name` is null-terminated.
|
||||
@@ -79,3 +104,53 @@ unsafe impl crate::types::AlwaysRefCounted for FwNode {
|
||||
unsafe { bindings::fwnode_handle_put(obj.cast().as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
enum Node<'a> {
|
||||
Borrowed(&'a FwNode),
|
||||
Owned(ARef<FwNode>),
|
||||
}
|
||||
|
||||
impl core::fmt::Display for FwNode {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
// The logic here is the same as the one in lib/vsprintf.c
|
||||
// (fwnode_full_name_string).
|
||||
|
||||
// SAFETY: `self.as_raw()` is valid by its type invariant.
|
||||
let num_parents = unsafe { bindings::fwnode_count_parents(self.as_raw()) };
|
||||
|
||||
for depth in (0..=num_parents).rev() {
|
||||
let fwnode = if depth == 0 {
|
||||
Node::Borrowed(self)
|
||||
} else {
|
||||
// SAFETY: `self.as_raw()` is valid.
|
||||
let ptr = unsafe { bindings::fwnode_get_nth_parent(self.as_raw(), depth) };
|
||||
// SAFETY:
|
||||
// - The depth passed to `fwnode_get_nth_parent` is
|
||||
// within the valid range, so the returned pointer is
|
||||
// not null.
|
||||
// - The reference count was incremented by
|
||||
// `fwnode_get_nth_parent`.
|
||||
// - That increment is relinquished to
|
||||
// `FwNode::from_raw`.
|
||||
Node::Owned(unsafe { FwNode::from_raw(ptr) })
|
||||
};
|
||||
// Take a reference to the owned or borrowed `FwNode`.
|
||||
let fwnode: &FwNode = match &fwnode {
|
||||
Node::Borrowed(f) => f,
|
||||
Node::Owned(f) => f,
|
||||
};
|
||||
|
||||
// SAFETY: `fwnode` is valid by its type invariant.
|
||||
let prefix = unsafe { bindings::fwnode_get_name_prefix(fwnode.as_raw()) };
|
||||
if !prefix.is_null() {
|
||||
// SAFETY: `fwnode_get_name_prefix` returns null or a
|
||||
// valid C string.
|
||||
let prefix = unsafe { CStr::from_char_ptr(prefix) };
|
||||
write!(f, "{prefix}")?;
|
||||
}
|
||||
write!(f, "{}", fwnode.display_name())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user