@@ -30,13 +30,31 @@ pub struct Registration {
30
30
// (it is fine for multiple threads to have a shared reference to it).
31
31
unsafe impl Sync for Registration { }
32
32
33
+ extern "C" {
34
+ #[ allow( improper_ctypes) ]
35
+ fn rust_helper_platform_get_drvdata (
36
+ pdev : * const bindings:: platform_device ,
37
+ ) -> * mut c_types:: c_void ;
38
+
39
+ #[ allow( improper_ctypes) ]
40
+ fn rust_helper_platform_set_drvdata (
41
+ pdev : * mut bindings:: platform_device ,
42
+ data : * mut c_types:: c_void ,
43
+ ) ;
44
+ }
45
+
33
46
extern "C" fn probe_callback < P : PlatformDriver > (
34
47
pdev : * mut bindings:: platform_device ,
35
48
) -> c_types:: c_int {
36
49
from_kernel_result ! {
37
50
// SAFETY: `pdev` is guaranteed to be a valid, non-null pointer.
38
51
let device_id = unsafe { ( * pdev) . id } ;
39
- P :: probe( device_id) ?;
52
+ let drv_data = P :: probe( device_id) ?;
53
+ let drv_data = drv_data. into_pointer( ) as * mut c_types:: c_void;
54
+ // SAFETY: `pdev` is guaranteed to be a valid, non-null pointer.
55
+ unsafe {
56
+ rust_helper_platform_set_drvdata( pdev, drv_data) ;
57
+ }
40
58
Ok ( 0 )
41
59
}
42
60
}
@@ -47,7 +65,16 @@ extern "C" fn remove_callback<P: PlatformDriver>(
47
65
from_kernel_result ! {
48
66
// SAFETY: `pdev` is guaranteed to be a valid, non-null pointer.
49
67
let device_id = unsafe { ( * pdev) . id } ;
50
- P :: remove( device_id) ?;
68
+ // SAFETY: `pdev` is guaranteed to be a valid, non-null pointer.
69
+ let ptr = unsafe { rust_helper_platform_get_drvdata( pdev) } ;
70
+ // SAFETY:
71
+ // - we allocated this pointer using `P::DrvData::into_pointer`,
72
+ // so it is safe to turn back into a `P::DrvData`.
73
+ // - the allocation happened in `probe`, no-one freed the memory,
74
+ // `remove` is the canonical kernel location to free driver data. so OK
75
+ // to convert the pointer back to a Rust structure here.
76
+ let drv_data = unsafe { P :: DrvData :: from_pointer( ptr) } ;
77
+ P :: remove( device_id, drv_data) ?;
51
78
Ok ( 0 )
52
79
}
53
80
}
@@ -124,15 +151,25 @@ impl Drop for Registration {
124
151
///
125
152
/// Implement this trait whenever you create a platform driver.
126
153
pub trait PlatformDriver {
154
+ /// Device driver data.
155
+ ///
156
+ /// Corresponds to the data set or retrieved via the kernel's
157
+ /// `platform_{set,get}_drvdata()` functions.
158
+ ///
159
+ /// Require that `DrvData` implements `PointerWrapper`. We guarantee to
160
+ /// never move the underlying wrapped data structure. This allows
161
+ /// driver writers to use pinned or self-referential data structures.
162
+ type DrvData : PointerWrapper ;
163
+
127
164
/// Platform driver probe.
128
165
///
129
166
/// Called when a new platform device is added or discovered.
130
167
/// Implementers should attempt to initialize the device here.
131
- fn probe ( device_id : i32 ) -> Result ;
168
+ fn probe ( device_id : i32 ) -> Result < Self :: DrvData > ;
132
169
133
170
/// Platform driver remove.
134
171
///
135
172
/// Called when a platform device is removed.
136
173
/// Implementers should prepare the device for complete removal here.
137
- fn remove ( device_id : i32 ) -> Result ;
174
+ fn remove ( device_id : i32 , drv_data : Self :: DrvData ) -> Result ;
138
175
}
0 commit comments