From nobody Mon Oct 6 20:43:39 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 D2BC6244686; Thu, 17 Jul 2025 22:48:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752792503; cv=none; b=pLfQ5wUG5GsjxgJBpcp0Z8Bjy1J6DWW4lBk+o57DBisl5WMYxMxxy+lftb4nXCVSl1qqkJA4GgVRviowOD9vhMe7qFkvrKUJypRoPl9yc/ySrHe/mgWv17mbj1dLhCewd1d4SE9eC+hVVWXUQmBDVo+/TMb9PaKlwdtOoBFZsGs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752792503; c=relaxed/simple; bh=qfqlSvvIDzTlxJUrCtARXaehrvsE3tyuylvblajHCyk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mBYfaQ0A/ogUUZCZzuWNp4E2RN8zmjAuQjkEXPw48kc7NyAfzOSnlGhBgQnZd0s4NuaM9T977gZb8IAMFf82JHkNcZZH7zUypZo8k6yCw+5CF24xVU3w57nKmQpGckx52xlgR//Xt8hrVcrZH65qs7gmJ/pKNr2ClSg0PCquqmY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=i4KoN78m; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="i4KoN78m" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D1A72C4CEF0; Thu, 17 Jul 2025 22:48:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1752792503; bh=qfqlSvvIDzTlxJUrCtARXaehrvsE3tyuylvblajHCyk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=i4KoN78mLYULahr58Iq1zfSVPcbVHPKd5J0zj7xWMjCgxXBXwCWBL3zuo+9KOdF6n AUSrhL+tTjv3iOlfwf8Emb5YBTtvEMLjYwrpbhlXMX5CbfKuMRkORRmi+W55/6fbAb sGKM7XqnCCbTdgKvTtgrNNtBb0btnHA/SykGsCS/aSxskKK6TM5vpAAKXVa5YER3t+ tN7c+YqQPxltUHRYlvEi0Zi2xRAMpvmfAz/gt2DU94bUlkUcGJzlKjQvE2x0OJlE44 1z64MF4ooiMYXhzH//R75wAif/riP63Bqo56kSqG4SkziW/dsixqFZ+SdvvcwZu5/z PWKKa3IHSgVXA== From: Danilo Krummrich To: gregkh@linuxfoundation.org, rafael@kernel.org, ojeda@kernel.org, alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Danilo Krummrich Subject: [PATCH 2/3] device: rust: expand documentation for Device Date: Fri, 18 Jul 2025 00:45:38 +0200 Message-ID: <20250717224806.54763-3-dakr@kernel.org> X-Mailer: git-send-email 2.50.0 In-Reply-To: <20250717224806.54763-1-dakr@kernel.org> References: <20250717224806.54763-1-dakr@kernel.org> 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" The documentation for the generic Device type is outdated and deserves much more detail. Hence, expand the documentation and cover topics such as device types, device contexts, as well as information on how to use the generic device infrastructure to implement bus and class specific device types. Signed-off-by: Danilo Krummrich Reviewed-by: Daniel Almeida --- rust/kernel/device.rs | 135 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 122 insertions(+), 13 deletions(-) diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index d7ac56628fe5..1a2ae16d8f11 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -15,23 +15,132 @@ =20 pub mod property; =20 -/// A reference-counted device. +/// The core representation of a device in the kernel's driver model. /// -/// This structure represents the Rust abstraction for a C `struct device`= . This implementation -/// abstracts the usage of an already existing C `struct device` within Ru= st code that we get -/// passed from the C side. +/// This structure represents the Rust abstraction for a C `struct device`= . A [`Device`] can either +/// exist as temporary reference (see also [`Device::from_raw`]), which is= only valid within a +/// certain scope or as [`ARef`], owning a dedicated reference cou= nt. /// -/// An instance of this abstraction can be obtained temporarily or permane= nt. +/// # Device Types /// -/// A temporary one is bound to the lifetime of the C `struct device` poin= ter used for creation. -/// A permanent instance is always reference-counted and hence not restric= ted by any lifetime -/// boundaries. +/// A [`Device`] can represent either a bus device or a class device. /// -/// For subsystems it is recommended to create a permanent instance to wra= p into a subsystem -/// specific device structure (e.g. `pci::Device`). This is useful for pas= sing it to drivers in -/// `T::probe()`, such that a driver can store the `ARef` (equival= ent to storing a -/// `struct device` pointer in a C driver) for arbitrary purposes, e.g. al= locating DMA coherent -/// memory. +/// ## Bus Devices +/// +/// A bus device is a [`Device`] that is associated with a physical or vir= tual bus. Examples of +/// buses include PCI, USB, I2C, and SPI. Devices attached to a bus are re= gistered with a specific +/// bus type, which facilitates matching devices with appropriate drivers = based on IDs or other +/// identifying information. Bus devices are visible in sysfs under `/sys/= bus//devices/`. +/// +/// ## Class Devices +/// +/// A class device is a [`Device`] that is associated with a logical categ= ory of functionality +/// rather than a physical bus. Examples of classes include block devices,= network interfaces, sound +/// cards, and input devices. Class devices are grouped under a common cla= ss and exposed to +/// userspace via entries in `/sys/class//`. +/// +/// # Device Context +/// +/// [`Device`] references are generic over a [`DeviceContext`], which repr= esents the type state of +/// a [`Device`]. +/// +/// As the name indicates, this type state represents the context of the s= cope the [`Device`] +/// reference is valid in. For instance, the [`Bound`] context guarantees = that the [`Device`] is +/// bound to a driver for the entire duration of the existence of a [`Devi= ce`] reference. +/// +/// Other [`DeviceContext`] types besides [`Bound`] are [`Normal`], [`Core= `] and [`CoreInternal`]. +/// +/// Unless selected otherwise [`Device`] defaults to the [`Normal`] [`Devi= ceContext`], which by +/// itself has no additional requirements. +/// +/// It is always up to the caller of [`Device::from_raw`] to select the co= rrect [`DeviceContext`] +/// type for the corresponding scope the [`Device`] reference is created i= n. +/// +/// All [`DeviceContext`] types other than [`Normal`] are intended to be u= sed with +/// [bus devices](#bus-devices) only. +/// +/// # Implementing Bus Devices +/// +/// This section provides a guideline to implement bus specific devices, s= uch as +/// [`pci::Device`](kernel::pci::Device) or [`platform::Device`](kernel::p= latform::Device). +/// +/// A bus specific device should be defined as follows. +/// +/// ```ignore +/// #[repr(transparent)] +/// pub struct Device( +/// Opaque, +/// PhantomData, +/// ); +/// ``` +/// +/// Since devices are reference counted, [`AlwaysRefCounted`](kernel::type= s::AlwaysRefCounted) +/// should be implemented for `Device` (i.e. `Device`). Note that +/// [`AlwaysRefCounted`](kernel::types::AlwaysRefCounted) must not be impl= emented for any other +/// [`DeviceContext`], since all other device context types are only valid= in a certain scope. +/// +/// In order to be able to implement the [`DeviceContext`] dereference hie= rarchy, bus device +/// implementations should call the [`impl_device_context_deref`](kernel::= impl_device_context_deref) +/// macro as shown below. +/// +/// ```ignore +/// // SAFETY: `Device` is a transparent wrapper of a type that doesn't de= pend on `Device`'s +/// // generic argument. +/// kernel::impl_device_context_deref!(unsafe { Device }); +/// ``` +/// In order to convert from a any [`Device`] to [`ARef`], bu= s devices can implement +/// the following macro call. +/// +/// ```ignore +/// kernel::impl_device_context_into_aref!(Device); +/// ``` +/// Bus devices should also implement the following [`AsRef`] implementati= on, such that users can +/// easily derive a generic [`Device`] reference. +/// +/// ```ignore +/// impl AsRef> for Device= { +/// fn as_ref(&self) -> &device::Device { +/// ... +/// } +/// } +/// ``` +/// +/// # Implementing Class Devices +/// +/// Class device implementations require less infrastructure and depend sl= ightly more on the +/// specific subsystem. +/// +/// An example implementation for a class device could look like this. +/// +/// ```ignore +/// #[repr(C)] +/// #[pin_data] +/// pub struct Device { +/// dev: Opaque, +/// #[pin] +/// data: T::Data, +/// } +/// ``` +/// +/// This class device uses the sub-classing pattern to embed the driver's = private data within the +/// allocation of the class device. For this to be possible the class devi= ce is generic over the +/// class specific `Driver` trait implementation. +/// +/// Just like any device, class devices are reference counted and should h= ence implement +/// [`AlwaysRefCounted`](kernel::types::AlwaysRefCounted) for `Device`. +/// +/// Class devices should also implement the following [`AsRef`] implementa= tion, such that users can +/// easily derive a generic [`Device`] reference. +/// +/// ```ignore +/// impl AsRef for Device { +/// fn as_ref(&self) -> &device::Device { +/// ... +/// } +/// } +/// ``` +/// +/// An example for a class device implementation is [`drm::Device`](kernel= ::drm::Device). /// /// # Invariants /// --=20 2.50.0