diff options
author | 2025-06-11 12:29:04 +0200 | |
---|---|---|
committer | 2025-06-13 00:58:53 +0200 | |
commit | 9bd791d9413b4b65e203c4ff84c8b8b2c8c3b770 (patch) | |
tree | 9862a82ea1d4f5c010374a028d2a06ef1fea3fb8 | |
parent | rust: device: Enable printing fwnode name and path (diff) | |
download | wireguard-linux-9bd791d9413b4b65e203c4ff84c8b8b2c8c3b770.tar.xz wireguard-linux-9bd791d9413b4b65e203c4ff84c8b8b2c8c3b770.zip |
rust: device: Introduce PropertyGuard
This abstraction is a way to force users to specify whether a property
is supposed to be required or not. This allows us to move error
logging of missing required properties into core, preventing a lot of
boilerplate in drivers.
It will be used by upcoming methods for reading device properties.
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-6-remo@buenzli.dev
[ Use prelude::* to avoid build failure; move PropertyGuard below Display
impl of FwNode. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
-rw-r--r-- | rust/kernel/device/property.rs | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/rust/kernel/device/property.rs b/rust/kernel/device/property.rs index 4cac335bad78..2c9482578987 100644 --- a/rust/kernel/device/property.rs +++ b/rust/kernel/device/property.rs @@ -8,6 +8,7 @@ use core::ptr; use crate::{ bindings, + prelude::*, str::CStr, types::{ARef, Opaque}, }; @@ -154,3 +155,62 @@ impl core::fmt::Display for FwNode { Ok(()) } } + +/// A helper for reading device properties. +/// +/// Use [`Self::required_by`] if a missing property is considered a bug and +/// [`Self::optional`] otherwise. +/// +/// For convenience, [`Self::or`] and [`Self::or_default`] are provided. +pub struct PropertyGuard<'fwnode, 'name, T> { + /// The result of reading the property. + inner: Result<T>, + /// The fwnode of the property, used for logging in the "required" case. + fwnode: &'fwnode FwNode, + /// The name of the property, used for logging in the "required" case. + name: &'name CStr, +} + +impl<T> PropertyGuard<'_, '_, T> { + /// Access the property, indicating it is required. + /// + /// If the property is not present, the error is automatically logged. If a + /// missing property is not an error, use [`Self::optional`] instead. The + /// device is required to associate the log with it. + pub fn required_by(self, dev: &super::Device) -> Result<T> { + if self.inner.is_err() { + dev_err!( + dev, + "{}: property '{}' is missing\n", + self.fwnode, + self.name + ); + } + self.inner + } + + /// Access the property, indicating it is optional. + /// + /// In contrast to [`Self::required_by`], no error message is logged if + /// the property is not present. + pub fn optional(self) -> Option<T> { + self.inner.ok() + } + + /// Access the property or the specified default value. + /// + /// Do not pass a sentinel value as default to detect a missing property. + /// Use [`Self::required_by`] or [`Self::optional`] instead. + pub fn or(self, default: T) -> T { + self.inner.unwrap_or(default) + } +} + +impl<T: Default> PropertyGuard<'_, '_, T> { + /// Access the property or a default value. + /// + /// Use [`Self::or`] to specify a custom default value. + pub fn or_default(self) -> T { + self.inner.unwrap_or_default() + } +} |