Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rust: device: Add property_get_reference_args

Allow Rust code to read reference args from device properties. The
wrapper type `FwNodeReferenceArgs` allows callers to access the buffer
of read args safely.

Signed-off-by: Remo Senekowitsch <remo@buenzli.dev>
Link: https://lore.kernel.org/r/20250616154511.1862909-3-remo@buenzli.dev
[ Move up NArgs; refer to FwNodeReferenceArgs in NArgs doc-comment.
- Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>

authored by

Remo Senekowitsch and committed by
Danilo Krummrich
c3e05bd1 c942dba3

+102
+102
rust/kernel/device/property.rs
··· 246 246 Some(next) 247 247 }) 248 248 } 249 + 250 + /// Finds a reference with arguments. 251 + pub fn property_get_reference_args( 252 + &self, 253 + prop: &CStr, 254 + nargs: NArgs<'_>, 255 + index: u32, 256 + ) -> Result<FwNodeReferenceArgs> { 257 + let mut out_args = FwNodeReferenceArgs::default(); 258 + 259 + let (nargs_prop, nargs) = match nargs { 260 + NArgs::Prop(nargs_prop) => (nargs_prop.as_char_ptr(), 0), 261 + NArgs::N(nargs) => (ptr::null(), nargs), 262 + }; 263 + 264 + // SAFETY: 265 + // - `self.0.get()` is valid. 266 + // - `prop.as_char_ptr()` is valid and zero-terminated. 267 + // - `nargs_prop` is valid and zero-terminated if `nargs` 268 + // is zero, otherwise it is allowed to be a null-pointer. 269 + // - The function upholds the type invariants of `out_args`, 270 + // namely: 271 + // - It may fill the field `fwnode` with a valid pointer, 272 + // in which case its refcount is incremented. 273 + // - It may modify the field `nargs`, in which case it 274 + // initializes at least as many elements in `args`. 275 + let ret = unsafe { 276 + bindings::fwnode_property_get_reference_args( 277 + self.0.get(), 278 + prop.as_char_ptr(), 279 + nargs_prop, 280 + nargs, 281 + index, 282 + &mut out_args.0, 283 + ) 284 + }; 285 + to_result(ret)?; 286 + 287 + Ok(out_args) 288 + } 289 + } 290 + 291 + /// The number of arguments to request [`FwNodeReferenceArgs`]. 292 + pub enum NArgs<'a> { 293 + /// The name of the property of the reference indicating the number of 294 + /// arguments. 295 + Prop(&'a CStr), 296 + /// The known number of arguments. 297 + N(u32), 298 + } 299 + 300 + /// The return value of [`FwNode::property_get_reference_args`]. 301 + /// 302 + /// This structure represents the Rust abstraction for a C 303 + /// `struct fwnode_reference_args` which was initialized by the C side. 304 + /// 305 + /// # Invariants 306 + /// 307 + /// If the field `fwnode` is valid, it owns an increment of its refcount. 308 + /// 309 + /// The field `args` contains at least as many initialized elements as indicated 310 + /// by the field `nargs`. 311 + #[repr(transparent)] 312 + #[derive(Default)] 313 + pub struct FwNodeReferenceArgs(bindings::fwnode_reference_args); 314 + 315 + impl Drop for FwNodeReferenceArgs { 316 + fn drop(&mut self) { 317 + if !self.0.fwnode.is_null() { 318 + // SAFETY: 319 + // - By the type invariants of `FwNodeReferenceArgs`, its field 320 + // `fwnode` owns an increment of its refcount. 321 + // - That increment is relinquished. The underlying object won't be 322 + // used anymore because we are dropping it. 323 + let _ = unsafe { FwNode::from_raw(self.0.fwnode) }; 324 + } 325 + } 326 + } 327 + 328 + impl FwNodeReferenceArgs { 329 + /// Returns the slice of reference arguments. 330 + pub fn as_slice(&self) -> &[u64] { 331 + // SAFETY: As per the safety invariant of `FwNodeReferenceArgs`, `nargs` 332 + // is the minimum number of elements in `args` that is valid. 333 + unsafe { core::slice::from_raw_parts(self.0.args.as_ptr(), self.0.nargs as usize) } 334 + } 335 + 336 + /// Returns the number of reference arguments. 337 + pub fn len(&self) -> usize { 338 + self.0.nargs as usize 339 + } 340 + 341 + /// Returns `true` if there are no reference arguments. 342 + pub fn is_empty(&self) -> bool { 343 + self.0.nargs == 0 344 + } 345 + } 346 + 347 + impl core::fmt::Debug for FwNodeReferenceArgs { 348 + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 349 + write!(f, "{:?}", self.as_slice()) 350 + } 249 351 } 250 352 251 353 // SAFETY: Instances of `FwNode` are always reference-counted.