From nobody Fri Dec 19 17:52:13 2025 Received: from mout-p-102.mailbox.org (mout-p-102.mailbox.org [80.241.56.152]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A2BC71EB5DB; Sat, 24 May 2025 19:22:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=80.241.56.152 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748114582; cv=none; b=V2WDpeQuCKjNqGKhaa6i2VWiy8Oz96EOk3LZfFpxeyVAGTv/KC8nlR6K07GNjH8kZdOE23c0glwYiVTxzHqP9EoM59S1ZgtayxwVg6RaHHTDvpz1lC5Dr6Urv2sM8HqBsZYkSg+zF8lWIHt8reNoZ1PkVgYyPlzVm5IjYK1M8As= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748114582; c=relaxed/simple; bh=qwgpYuIBLX4VZKbCkjuqe3U5WXe9DP6is+Rd9RgGVO4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=W3iOG3BvRyOPUYHd3ONWDR/TvhSNv8KQX8hxVPt8ajU3zqWl6L+19SocsoUKMvuN+lf7hDfOLhBEjPMX9U44VptZZXxDJXUQpWKuTCTzGG8C2T+1D2gEhWJt9LppbaifsIQNpoDSFQB1EpZwGMsFERCDj4XTfFG89AEif+VacIA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=buenzli.dev; spf=pass smtp.mailfrom=buenzli.dev; arc=none smtp.client-ip=80.241.56.152 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=buenzli.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=buenzli.dev Received: from smtp102.mailbox.org (smtp102.mailbox.org [10.196.197.102]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-102.mailbox.org (Postfix) with ESMTPS id 4b4X3t3l0Xz9tTZ; Sat, 24 May 2025 21:22:50 +0200 (CEST) From: Remo Senekowitsch To: Rob Herring , Saravana Kannan , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Greg Kroah-Hartman , "Rafael J. Wysocki" , Dirk Behme , Remo Senekowitsch Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, rust-for-linux@vger.kernel.org Subject: [PATCH v6 1/9] rust: device: Create FwNode abstraction for accessing device properties Date: Sat, 24 May 2025 21:22:24 +0200 Message-ID: <20250524192232.705860-2-remo@buenzli.dev> In-Reply-To: <20250524192232.705860-1-remo@buenzli.dev> References: <20250524192232.705860-1-remo@buenzli.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Accessing device properties is currently done via methods on `Device` itself, using bindings to device_property_* functions. This is sufficient for the existing method property_present. However, it's not sufficient for other device properties we want to access. For example, iterating over child nodes of a device will yield a fwnode_handle. That's not a device, so it wouldn't be possible to read the properties of that child node. Thus, we need an abstraction over fwnode_handle and methods for reading its properties. Add a struct FwNode which abstracts over the C struct fwnode_handle. Implement its reference counting analogous to other Rust abstractions over reference-counted C structs. Subsequent patches will add functionality to access FwNode and read properties with it. Signed-off-by: Remo Senekowitsch --- MAINTAINERS | 1 + rust/helpers/helpers.c | 1 + rust/helpers/property.c | 8 ++++++ rust/kernel/device.rs | 2 ++ rust/kernel/device/property.rs | 49 ++++++++++++++++++++++++++++++++++ 5 files changed, 61 insertions(+) create mode 100644 rust/helpers/property.c create mode 100644 rust/kernel/device/property.rs diff --git a/MAINTAINERS b/MAINTAINERS index e58cafb019e63..52e2cff786cac 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7249,6 +7249,7 @@ F: include/linux/property.h F: include/linux/sysfs.h F: lib/kobj* F: rust/kernel/device.rs +F: rust/kernel/device/ F: rust/kernel/device_id.rs F: rust/kernel/devres.rs F: rust/kernel/driver.rs diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 80785b1e7a63e..b5cffc08190da 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -25,6 +25,7 @@ #include "platform.c" #include "pci.c" #include "pid_namespace.c" +#include "property.c" #include "rbtree.c" #include "rcu.c" #include "refcount.c" diff --git a/rust/helpers/property.c b/rust/helpers/property.c new file mode 100644 index 0000000000000..08f68e2dac4a9 --- /dev/null +++ b/rust/helpers/property.c @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +void rust_helper_fwnode_handle_put(struct fwnode_handle *fwnode) +{ + fwnode_handle_put(fwnode); +} diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index 1edebb88e496f..56ee463a4bd11 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -14,6 +14,8 @@ #[cfg(CONFIG_PRINTK)] use crate::c_str; =20 +pub mod property; + /// A reference-counted device. /// /// This structure represents the Rust abstraction for a C `struct device`= . This implementation diff --git a/rust/kernel/device/property.rs b/rust/kernel/device/property.rs new file mode 100644 index 0000000000000..ca525ed0e8e8f --- /dev/null +++ b/rust/kernel/device/property.rs @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Unified device property interface. +//! +//! C header: [`include/linux/property.h`](srctree/include/linux/property.= h) + +use core::ptr; + +use crate::{bindings, types::Opaque}; + +/// A reference-counted fwnode_handle. +/// +/// This structure represents the Rust abstraction for a +/// C `struct fwnode_handle`. This implementation abstracts the usage of an +/// already existing C `struct fwnode_handle` within Rust code that we get +/// passed from the C side. +/// +/// # Invariants +/// +/// A `FwNode` instance represents a valid `struct fwnode_handle` created = by the +/// C portion of the kernel. +/// +/// Instances of this type are always reference-counted, that is, a call to +/// `fwnode_handle_get` ensures that the allocation remains valid at least= until +/// the matching call to `fwnode_handle_put`. +#[repr(transparent)] +pub struct FwNode(Opaque); + +impl FwNode { + /// Obtain the raw `struct fwnode_handle *`. + pub(crate) fn as_raw(&self) -> *mut bindings::fwnode_handle { + self.0.get() + } +} + +// SAFETY: Instances of `FwNode` are always reference-counted. +unsafe impl crate::types::AlwaysRefCounted for FwNode { + fn inc_ref(&self) { + // SAFETY: The existence of a shared reference guarantees that the + // refcount is non-zero. + unsafe { bindings::fwnode_handle_get(self.as_raw()) }; + } + + unsafe fn dec_ref(obj: ptr::NonNull) { + // SAFETY: The safety requirements guarantee that the refcount is + // non-zero. + unsafe { bindings::fwnode_handle_put(obj.cast().as_ptr()) } + } +} --=20 2.49.0