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 str::CStr, 12 types::{ARef, Opaque}, 13 }; 14 15 /// A reference-counted fwnode_handle. 16 /// 17 /// This structure represents the Rust abstraction for a 18 /// C `struct fwnode_handle`. This implementation abstracts the usage of an 19 /// already existing C `struct fwnode_handle` within Rust code that we get 20 /// passed from the C side. 21 /// 22 /// # Invariants 23 /// 24 /// A `FwNode` instance represents a valid `struct fwnode_handle` created by the 25 /// C portion of the kernel. 26 /// 27 /// Instances of this type are always reference-counted, that is, a call to 28 /// `fwnode_handle_get` ensures that the allocation remains valid at least until 29 /// the matching call to `fwnode_handle_put`. 30 #[repr(transparent)] 31 pub struct FwNode(Opaque<bindings::fwnode_handle>); 32 33 impl FwNode { 34 /// # Safety 35 /// 36 /// Callers must ensure that: 37 /// - The reference count was incremented at least once. 38 /// - They relinquish that increment. That is, if there is only one 39 /// increment, callers must not use the underlying object anymore -- it is 40 /// only safe to do so via the newly created `ARef<FwNode>`. 41 #[expect(dead_code)] 42 unsafe fn from_raw(raw: *mut bindings::fwnode_handle) -> ARef<Self> { 43 // SAFETY: As per the safety requirements of this function: 44 // - `NonNull::new_unchecked`: 45 // - `raw` is not null. 46 // - `ARef::from_raw`: 47 // - `raw` has an incremented refcount. 48 // - that increment is relinquished, i.e. it won't be decremented 49 // elsewhere. 50 // CAST: It is safe to cast from a `*mut fwnode_handle` to 51 // `*mut FwNode`, because `FwNode` is defined as a 52 // `#[repr(transparent)]` wrapper around `fwnode_handle`. 53 unsafe { ARef::from_raw(ptr::NonNull::new_unchecked(raw.cast())) } 54 } 55 56 /// Obtain the raw `struct fwnode_handle *`. 57 pub(crate) fn as_raw(&self) -> *mut bindings::fwnode_handle { 58 self.0.get() 59 } 60 61 /// Checks if property is present or not. 62 pub fn property_present(&self, name: &CStr) -> bool { 63 // SAFETY: By the invariant of `CStr`, `name` is null-terminated. 64 unsafe { bindings::fwnode_property_present(self.as_raw().cast_const(), name.as_char_ptr()) } 65 } 66 } 67 68 // SAFETY: Instances of `FwNode` are always reference-counted. 69 unsafe impl crate::types::AlwaysRefCounted for FwNode { 70 fn inc_ref(&self) { 71 // SAFETY: The existence of a shared reference guarantees that the 72 // refcount is non-zero. 73 unsafe { bindings::fwnode_handle_get(self.as_raw()) }; 74 } 75 76 unsafe fn dec_ref(obj: ptr::NonNull<Self>) { 77 // SAFETY: The safety requirements guarantee that the refcount is 78 // non-zero. 79 unsafe { bindings::fwnode_handle_put(obj.cast().as_ptr()) } 80 } 81 } 82