5
5
//! C header: [`include/linux/platform_device.h`](srctree/include/linux/platform_device.h)
6
6
7
7
use crate :: {
8
- bindings, container_of , device, driver,
8
+ bindings, device, driver,
9
9
error:: { to_result, Result } ,
10
10
of,
11
11
prelude:: * ,
@@ -14,7 +14,11 @@ use crate::{
14
14
ThisModule ,
15
15
} ;
16
16
17
- use core:: ptr:: addr_of_mut;
17
+ use core:: {
18
+ marker:: PhantomData ,
19
+ ops:: Deref ,
20
+ ptr:: { addr_of_mut, NonNull } ,
21
+ } ;
18
22
19
23
/// An adapter for the registration of platform drivers.
20
24
pub struct Adapter < T : Driver > ( T ) ;
@@ -54,14 +58,14 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
54
58
55
59
impl < T : Driver + ' static > Adapter < T > {
56
60
extern "C" fn probe_callback ( pdev : * mut bindings:: platform_device ) -> kernel:: ffi:: c_int {
57
- // SAFETY: The platform bus only ever calls the probe callback with a valid `pdev`.
58
- let dev = unsafe { device :: Device :: get_device ( addr_of_mut ! ( ( * pdev ) . dev ) ) } ;
59
- // SAFETY: `dev` is guaranteed to be embedded in a valid `struct platform_device` by the
60
- // call above .
61
- let mut pdev = unsafe { Device :: from_dev ( dev ) } ;
61
+ // SAFETY: The platform bus only ever calls the probe callback with a valid pointer to a
62
+ // `struct platform_device`.
63
+ //
64
+ // INVARIANT: `pdev` is valid for the duration of `probe_callback()` .
65
+ let pdev = unsafe { & * pdev . cast :: < Device < device :: Core > > ( ) } ;
62
66
63
67
let info = <Self as driver:: Adapter >:: id_info ( pdev. as_ref ( ) ) ;
64
- match T :: probe ( & mut pdev, info) {
68
+ match T :: probe ( pdev, info) {
65
69
Ok ( data) => {
66
70
// Let the `struct platform_device` own a reference of the driver's private data.
67
71
// SAFETY: By the type invariant `pdev.as_raw` returns a valid pointer to a
@@ -120,7 +124,7 @@ macro_rules! module_platform_driver {
120
124
/// # Example
121
125
///
122
126
///```
123
- /// # use kernel::{bindings, c_str, of, platform};
127
+ /// # use kernel::{bindings, c_str, device::Core, of, platform};
124
128
///
125
129
/// struct MyDriver;
126
130
///
@@ -138,7 +142,7 @@ macro_rules! module_platform_driver {
138
142
/// const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
139
143
///
140
144
/// fn probe(
141
- /// _pdev: &mut platform::Device,
145
+ /// _pdev: &platform::Device<Core> ,
142
146
/// _id_info: Option<&Self::IdInfo>,
143
147
/// ) -> Result<Pin<KBox<Self>>> {
144
148
/// Err(ENODEV)
@@ -160,41 +164,72 @@ pub trait Driver {
160
164
///
161
165
/// Called when a new platform device is added or discovered.
162
166
/// Implementers should attempt to initialize the device here.
163
- fn probe ( dev : & mut Device , id_info : Option < & Self :: IdInfo > ) -> Result < Pin < KBox < Self > > > ;
167
+ fn probe ( dev : & Device < device:: Core > , id_info : Option < & Self :: IdInfo > )
168
+ -> Result < Pin < KBox < Self > > > ;
164
169
}
165
170
166
171
/// The platform device representation.
167
172
///
168
- /// A platform device is based on an always reference counted `device:Device` instance. Cloning a
169
- /// platform device, hence, also increments the base device' reference count.
173
+ /// This structure represents the Rust abstraction for a C `struct platform_device`. The
174
+ /// implementation abstracts the usage of an already existing C `struct platform_device` within Rust
175
+ /// code that we get passed from the C side.
170
176
///
171
177
/// # Invariants
172
178
///
173
- /// `Device` holds a valid reference of `ARef<device::Device>` whose underlying `struct device` is a
174
- /// member of a `struct platform_device`.
175
- #[ derive( Clone ) ]
176
- pub struct Device ( ARef < device:: Device > ) ;
179
+ /// A [`Device`] instance represents a valid `struct platform_device` created by the C portion of
180
+ /// the kernel.
181
+ #[ repr( transparent) ]
182
+ pub struct Device < Ctx : device:: DeviceContext = device:: Normal > (
183
+ Opaque < bindings:: platform_device > ,
184
+ PhantomData < Ctx > ,
185
+ ) ;
177
186
178
187
impl Device {
179
- /// Convert a raw kernel device into a `Device`
180
- ///
181
- /// # Safety
182
- ///
183
- /// `dev` must be an `Aref<device::Device>` whose underlying `bindings::device` is a member of a
184
- /// `bindings::platform_device`.
185
- unsafe fn from_dev ( dev : ARef < device:: Device > ) -> Self {
186
- Self ( dev)
188
+ fn as_raw ( & self ) -> * mut bindings:: platform_device {
189
+ self . 0 . get ( )
187
190
}
191
+ }
188
192
189
- fn as_raw ( & self ) -> * mut bindings:: platform_device {
190
- // SAFETY: By the type invariant `self.0.as_raw` is a pointer to the `struct device`
191
- // embedded in `struct platform_device`.
192
- unsafe { container_of ! ( self . 0 . as_raw( ) , bindings:: platform_device, dev) } . cast_mut ( )
193
+ impl Deref for Device < device:: Core > {
194
+ type Target = Device ;
195
+
196
+ fn deref ( & self ) -> & Self :: Target {
197
+ let ptr: * const Self = self ;
198
+
199
+ // CAST: `Device<Ctx>` is a transparent wrapper of `Opaque<bindings::platform_device>`.
200
+ let ptr = ptr. cast :: < Device > ( ) ;
201
+
202
+ // SAFETY: `ptr` was derived from `&self`.
203
+ unsafe { & * ptr }
204
+ }
205
+ }
206
+
207
+ impl From < & Device < device:: Core > > for ARef < Device > {
208
+ fn from ( dev : & Device < device:: Core > ) -> Self {
209
+ ( & * * dev) . into ( )
210
+ }
211
+ }
212
+
213
+ // SAFETY: Instances of `Device` are always reference-counted.
214
+ unsafe impl crate :: types:: AlwaysRefCounted for Device {
215
+ fn inc_ref ( & self ) {
216
+ // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
217
+ unsafe { bindings:: get_device ( self . as_ref ( ) . as_raw ( ) ) } ;
218
+ }
219
+
220
+ unsafe fn dec_ref ( obj : NonNull < Self > ) {
221
+ // SAFETY: The safety requirements guarantee that the refcount is non-zero.
222
+ unsafe { bindings:: platform_device_put ( obj. cast ( ) . as_ptr ( ) ) }
193
223
}
194
224
}
195
225
196
226
impl AsRef < device:: Device > for Device {
197
227
fn as_ref ( & self ) -> & device:: Device {
198
- & self . 0
228
+ // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid
229
+ // `struct platform_device`.
230
+ let dev = unsafe { addr_of_mut ! ( ( * self . as_raw( ) ) . dev) } ;
231
+
232
+ // SAFETY: `dev` points to a valid `struct device`.
233
+ unsafe { device:: Device :: as_ref ( dev) }
199
234
}
200
235
}
0 commit comments