@@ -15,23 +15,130 @@ use crate::c_str;
1515
1616pub mod property;
1717
18- /// A reference-counted device.
18+ /// The core representation of a device in the kernel's driver model .
1919///
20- /// This structure represents the Rust abstraction for a C `struct device`. This implementation
21- /// abstracts the usage of an already existing C `struct device` within Rust code that we get
22- /// passed from the C side .
20+ /// This structure represents the Rust abstraction for a C `struct device`. A [`Device`] can either
21+ /// exist as temporary reference (see also [`Device::from_raw`]), which is only valid within a
22+ /// certain scope or as [`ARef<Device>`], owning a dedicated reference count .
2323///
24- /// An instance of this abstraction can be obtained temporarily or permanent.
24+ /// # Device Types
2525///
26- /// A temporary one is bound to the lifetime of the C `struct device` pointer used for creation.
27- /// A permanent instance is always reference-counted and hence not restricted by any lifetime
28- /// boundaries.
26+ /// A [`Device`] can represent either a bus device or a class device.
2927///
30- /// For subsystems it is recommended to create a permanent instance to wrap into a subsystem
31- /// specific device structure (e.g. `pci::Device`). This is useful for passing it to drivers in
32- /// `T::probe()`, such that a driver can store the `ARef<Device>` (equivalent to storing a
33- /// `struct device` pointer in a C driver) for arbitrary purposes, e.g. allocating DMA coherent
34- /// memory.
28+ /// ## Bus Devices
29+ ///
30+ /// A bus device is a [`Device`] that is associated with a physical or virtual bus. Examples of
31+ /// buses include PCI, USB, I2C, and SPI. Devices attached to a bus are registered with a specific
32+ /// bus type, which facilitates matching devices with appropriate drivers based on IDs or other
33+ /// identifying information. Bus devices are visible in sysfs under `/sys/bus/<bus-name>/devices/`.
34+ ///
35+ /// ## Class Devices
36+ ///
37+ /// A class device is a [`Device`] that is associated with a logical category of functionality
38+ /// rather than a physical bus. Examples of classes include block devices, network interfaces, sound
39+ /// cards, and input devices. Class devices are grouped under a common class and exposed to
40+ /// userspace via entries in `/sys/class/<class-name>/`.
41+ ///
42+ /// # Device Context
43+ ///
44+ /// [`Device`] references are generic over a [`DeviceContext`], which represents the type state of
45+ /// a [`Device`].
46+ ///
47+ /// As the name indicates, this type state represents the context of the scope the [`Device`]
48+ /// reference is valid in. For instance, the [`Bound`] context guarantees that the [`Device`] is
49+ /// bound to a driver for the entire duration of the existence of a [`Device<Bound>`] reference.
50+ ///
51+ /// Other [`DeviceContext`] types besides [`Bound`] are [`Normal`], [`Core`] and [`CoreInternal`].
52+ ///
53+ /// Unless selected otherwise [`Device`] defaults to the [`Normal`] [`DeviceContext`], which by
54+ /// itself has no additional requirements.
55+ ///
56+ /// It is always up to the caller of [`Device::from_raw`] to select the correct [`DeviceContext`]
57+ /// type for the corresponding scope the [`Device`] reference is created in.
58+ ///
59+ /// All [`DeviceContext`] types other than [`Normal`] are intended to be used with
60+ /// [bus devices](#bus-devices) only.
61+ ///
62+ /// # Implementing Bus Devices
63+ ///
64+ /// This section provides a guideline to implement bus specific devices, such as [`pci::Device`] or
65+ /// [`platform::Device`].
66+ ///
67+ /// A bus specific device should be defined as follows.
68+ ///
69+ /// ```ignore
70+ /// #[repr(transparent)]
71+ /// pub struct Device<Ctx: device::DeviceContext = device::Normal>(
72+ /// Opaque<bindings::bus_device_type>,
73+ /// PhantomData<Ctx>,
74+ /// );
75+ /// ```
76+ ///
77+ /// Since devices are reference counted, [`AlwaysRefCounted`] should be implemented for `Device`
78+ /// (i.e. `Device<Normal>`). Note that [`AlwaysRefCounted`] must not be implemented for any other
79+ /// [`DeviceContext`], since all other device context types are only valid within a certain scope.
80+ ///
81+ /// In order to be able to implement the [`DeviceContext`] dereference hierarchy, bus device
82+ /// implementations should call the [`impl_device_context_deref`] macro as shown below.
83+ ///
84+ /// ```ignore
85+ /// // SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s
86+ /// // generic argument.
87+ /// kernel::impl_device_context_deref!(unsafe { Device });
88+ /// ```
89+ ///
90+ /// In order to convert from a any [`Device<Ctx>`] to [`ARef<Device>`], bus devices can implement
91+ /// the following macro call.
92+ ///
93+ /// ```ignore
94+ /// kernel::impl_device_context_into_aref!(Device);
95+ /// ```
96+ ///
97+ /// Bus devices should also implement the following [`AsRef`] implementation, such that users can
98+ /// easily derive a generic [`Device`] reference.
99+ ///
100+ /// ```ignore
101+ /// impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> {
102+ /// fn as_ref(&self) -> &device::Device<Ctx> {
103+ /// ...
104+ /// }
105+ /// }
106+ /// ```
107+ ///
108+ /// # Implementing Class Devices
109+ ///
110+ /// Class device implementations require less infrastructure and depend slightly more on the
111+ /// specific subsystem.
112+ ///
113+ /// An example implementation for a class device could look like this.
114+ ///
115+ /// ```ignore
116+ /// #[repr(C)]
117+ /// pub struct Device<T: class::Driver> {
118+ /// dev: Opaque<bindings::class_device_type>,
119+ /// data: T::Data,
120+ /// }
121+ /// ```
122+ ///
123+ /// This class device uses the sub-classing pattern to embed the driver's private data within the
124+ /// allocation of the class device. For this to be possible the class device is generic over the
125+ /// class specific `Driver` trait implementation.
126+ ///
127+ /// Just like any device, class devices are reference counted and should hence implement
128+ /// [`AlwaysRefCounted`] for `Device`.
129+ ///
130+ /// Class devices should also implement the following [`AsRef`] implementation, such that users can
131+ /// easily derive a generic [`Device`] reference.
132+ ///
133+ /// ```ignore
134+ /// impl<T: class::Driver> AsRef<device::Device> for Device<T> {
135+ /// fn as_ref(&self) -> &device::Device {
136+ /// ...
137+ /// }
138+ /// }
139+ /// ```
140+ ///
141+ /// An example for a class device implementation is [`drm::Device`].
35142///
36143/// # Invariants
37144///
@@ -42,6 +149,12 @@ pub mod property;
42149///
43150/// `bindings::device::release` is valid to be called from any thread, hence `ARef<Device>` can be
44151/// dropped from any thread.
152+ ///
153+ /// [`AlwaysRefCounted`]: kernel::types::AlwaysRefCounted
154+ /// [`drm::Device`]: kernel::drm::Device
155+ /// [`impl_device_context_deref`]: kernel::impl_device_context_deref
156+ /// [`pci::Device`]: kernel::pci::Device
157+ /// [`platform::Device`]: kernel::platform::Device
45158#[ repr( transparent) ]
46159pub struct Device < Ctx : DeviceContext = Normal > ( Opaque < bindings:: device > , PhantomData < Ctx > ) ;
47160
@@ -311,28 +424,75 @@ unsafe impl Send for Device {}
311424// synchronization in `struct device`.
312425unsafe impl Sync for Device { }
313426
314- /// Marker trait for the context of a bus specific device.
427+ /// Marker trait for the context or scope of a bus specific device.
428+ ///
429+ /// [`DeviceContext`] is a marker trait for types representing the context of a bus specific
430+ /// [`Device`].
431+ ///
432+ /// The specific device context types are: [`CoreInternal`], [`Core`], [`Bound`] and [`Normal`].
315433///
316- /// Some functions of a bus specific device should only be called from a certain context, i.e. bus
317- /// callbacks, such as `probe()`.
434+ /// [`DeviceContext`] types are hierarchical, which means that there is a strict hierarchy that
435+ /// defines which [`DeviceContext`] type can be derived from another. For instance, any
436+ /// [`Device<Core>`] can dereference to a [`Device<Bound>`].
318437///
319- /// This is the marker trait for structures representing the context of a bus specific device.
438+ /// The following enumeration illustrates the dereference hierarchy of [`DeviceContext`] types.
439+ ///
440+ /// - [`CoreInternal`] => [`Core`] => [`Bound`] => [`Normal`]
441+ ///
442+ /// Bus devices can automatically implement the dereference hierarchy by using
443+ /// [`impl_device_context_deref`].
444+ ///
445+ /// Note that the guarantee for a [`Device`] reference to have a certain [`DeviceContext`] comes
446+ /// from the specific scope the [`Device`] reference is valid in.
447+ ///
448+ /// [`impl_device_context_deref`]: kernel::impl_device_context_deref
320449pub trait DeviceContext : private:: Sealed { }
321450
322- /// The [`Normal`] context is the context of a bus specific device when it is not an argument of
323- /// any bus callback.
451+ /// The [`Normal`] context is the default [`DeviceContext`] of any [`Device`].
452+ ///
453+ /// The normal context does not indicate any specific context. Any `Device<Ctx>` is also a valid
454+ /// [`Device<Normal>`]. It is the only [`DeviceContext`] for which it is valid to implement
455+ /// [`AlwaysRefCounted`] for.
456+ ///
457+ /// [`AlwaysRefCounted`]: kernel::types::AlwaysRefCounted
324458pub struct Normal ;
325459
326- /// The [`Core`] context is the context of a bus specific device when it is supplied as argument of
327- /// any of the bus callbacks, such as `probe()`.
460+ /// The [`Core`] context is the context of a bus specific device when it appears as argument of
461+ /// any bus specific callback, such as `probe()`.
462+ ///
463+ /// The core context indicates that the [`Device<Core>`] reference's scope is limited to the bus
464+ /// callback it appears in. It is intended to be used for synchronization purposes. Bus device
465+ /// implementations can implement methods for [`Device<Core>`], such that they can only be called
466+ /// from bus callbacks.
328467pub struct Core ;
329468
330- /// Semantically the same as [`Core`] but reserved for internal usage of the corresponding bus
469+ /// Semantically the same as [`Core`], but reserved for internal usage of the corresponding bus
331470/// abstraction.
471+ ///
472+ /// The internal core context is intended to be used in exactly the same way as the [`Core`]
473+ /// context, with the difference that this [`DeviceContext`] is internal to the corresponding bus
474+ /// abstraction.
475+ ///
476+ /// This context mainly exists to share generic [`Device`] infrastructure that should only be called
477+ /// from bus callbacks with bus abstractions, but without making them accessible for drivers.
332478pub struct CoreInternal ;
333479
334- /// The [`Bound`] context is the context of a bus specific device reference when it is guaranteed to
335- /// be bound for the duration of its lifetime.
480+ /// The [`Bound`] context is the [`DeviceContext`] of a bus specific device when it is guaranteed to
481+ /// be bound to a driver.
482+ ///
483+ /// The bound context indicates that for the entire duration of the lifetime of a [`Device<Bound>`]
484+ /// reference, the [`Device`] is guaranteed to be bound to a driver.
485+ ///
486+ /// Some APIs, such as [`dma::CoherentAllocation`] or [`Devres`] rely on the [`Device`] to be bound,
487+ /// which can be proven with the [`Bound`] device context.
488+ ///
489+ /// Any abstraction that can guarantee a scope where the corresponding bus device is bound, should
490+ /// provide a [`Device<Bound>`] reference to its users for this scope. This allows users to benefit
491+ /// from optimizations for accessing device resources, see also [`Devres::access`].
492+ ///
493+ /// [`Devres`]: kernel::devres::Devres
494+ /// [`Devres::access`]: kernel::devres::Devres::access
495+ /// [`dma::CoherentAllocation`]: kernel::dma::CoherentAllocation
336496pub struct Bound ;
337497
338498mod private {
0 commit comments