xref: /linux/rust/kernel/device/property.rs (revision d3393e845038f5fd32c24b841bb4b6026aa1cf4b)
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