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: 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>

authored by

Remo Senekowitsch and committed by
Danilo Krummrich
ecea2459 d3393e84

+76 -1
+76 -1
rust/kernel/device/property.rs
··· 38 38 /// - They relinquish that increment. That is, if there is only one 39 39 /// increment, callers must not use the underlying object anymore -- it is 40 40 /// only safe to do so via the newly created `ARef<FwNode>`. 41 - #[expect(dead_code)] 42 41 unsafe fn from_raw(raw: *mut bindings::fwnode_handle) -> ARef<Self> { 43 42 // SAFETY: As per the safety requirements of this function: 44 43 // - `NonNull::new_unchecked`: ··· 55 56 /// Obtain the raw `struct fwnode_handle *`. 56 57 pub(crate) fn as_raw(&self) -> *mut bindings::fwnode_handle { 57 58 self.0.get() 59 + } 60 + 61 + /// Returns an object that implements [`Display`](core::fmt::Display) for 62 + /// printing the name of a node. 63 + /// 64 + /// This is an alternative to the default `Display` implementation, which 65 + /// prints the full path. 66 + pub fn display_name(&self) -> impl core::fmt::Display + '_ { 67 + struct FwNodeDisplayName<'a>(&'a FwNode); 68 + 69 + impl core::fmt::Display for FwNodeDisplayName<'_> { 70 + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 71 + // SAFETY: `self` is valid by its type invariant. 72 + let name = unsafe { bindings::fwnode_get_name(self.0.as_raw()) }; 73 + if name.is_null() { 74 + return Ok(()); 75 + } 76 + // SAFETY: 77 + // - `fwnode_get_name` returns null or a valid C string. 78 + // - `name` was checked to be non-null. 79 + let name = unsafe { CStr::from_char_ptr(name) }; 80 + write!(f, "{name}") 81 + } 82 + } 83 + 84 + FwNodeDisplayName(self) 58 85 } 59 86 60 87 /// Checks if property is present or not. ··· 102 77 // SAFETY: The safety requirements guarantee that the refcount is 103 78 // non-zero. 104 79 unsafe { bindings::fwnode_handle_put(obj.cast().as_ptr()) } 80 + } 81 + } 82 + 83 + enum Node<'a> { 84 + Borrowed(&'a FwNode), 85 + Owned(ARef<FwNode>), 86 + } 87 + 88 + impl core::fmt::Display for FwNode { 89 + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 90 + // The logic here is the same as the one in lib/vsprintf.c 91 + // (fwnode_full_name_string). 92 + 93 + // SAFETY: `self.as_raw()` is valid by its type invariant. 94 + let num_parents = unsafe { bindings::fwnode_count_parents(self.as_raw()) }; 95 + 96 + for depth in (0..=num_parents).rev() { 97 + let fwnode = if depth == 0 { 98 + Node::Borrowed(self) 99 + } else { 100 + // SAFETY: `self.as_raw()` is valid. 101 + let ptr = unsafe { bindings::fwnode_get_nth_parent(self.as_raw(), depth) }; 102 + // SAFETY: 103 + // - The depth passed to `fwnode_get_nth_parent` is 104 + // within the valid range, so the returned pointer is 105 + // not null. 106 + // - The reference count was incremented by 107 + // `fwnode_get_nth_parent`. 108 + // - That increment is relinquished to 109 + // `FwNode::from_raw`. 110 + Node::Owned(unsafe { FwNode::from_raw(ptr) }) 111 + }; 112 + // Take a reference to the owned or borrowed `FwNode`. 113 + let fwnode: &FwNode = match &fwnode { 114 + Node::Borrowed(f) => f, 115 + Node::Owned(f) => f, 116 + }; 117 + 118 + // SAFETY: `fwnode` is valid by its type invariant. 119 + let prefix = unsafe { bindings::fwnode_get_name_prefix(fwnode.as_raw()) }; 120 + if !prefix.is_null() { 121 + // SAFETY: `fwnode_get_name_prefix` returns null or a 122 + // valid C string. 123 + let prefix = unsafe { CStr::from_char_ptr(prefix) }; 124 + write!(f, "{prefix}")?; 125 + } 126 + write!(f, "{}", fwnode.display_name())?; 127 + } 128 + 129 + Ok(()) 105 130 } 106 131 }