@@ -99,31 +99,51 @@ use crate::{acpi, device, of, str::CStr, try_pin_init, types::Opaque, ThisModule
9999use core:: pin:: Pin ;
100100use pin_init:: { pin_data, pinned_drop, PinInit } ;
101101
102+ /// Trait describing the layout of a specific device driver.
103+ ///
104+ /// This trait describes the layout of a specific driver structure, such as `struct pci_driver` or
105+ /// `struct platform_driver`.
106+ ///
107+ /// # Safety
108+ ///
109+ /// Implementors must guarantee that:
110+ /// - `DriverType` is `repr(C)`,
111+ /// - `DriverData` is the type of the driver's device private data.
112+ /// - `DriverType` embeds a valid `struct device_driver` at byte offset `DEVICE_DRIVER_OFFSET`.
113+ pub unsafe trait DriverLayout {
114+ /// The specific driver type embedding a `struct device_driver`.
115+ type DriverType : Default ;
116+
117+ /// The type of the driver's device private data.
118+ type DriverData ;
119+
120+ /// Byte offset of the embedded `struct device_driver` within `DriverType`.
121+ ///
122+ /// This must correspond exactly to the location of the embedded `struct device_driver` field.
123+ const DEVICE_DRIVER_OFFSET : usize ;
124+ }
125+
102126/// The [`RegistrationOps`] trait serves as generic interface for subsystems (e.g., PCI, Platform,
103127/// Amba, etc.) to provide the corresponding subsystem specific implementation to register /
104- /// unregister a driver of the particular type (`RegType `).
128+ /// unregister a driver of the particular type (`DriverType `).
105129///
106- /// For instance, the PCI subsystem would set `RegType ` to `bindings::pci_driver` and call
130+ /// For instance, the PCI subsystem would set `DriverType ` to `bindings::pci_driver` and call
107131/// `bindings::__pci_register_driver` from `RegistrationOps::register` and
108132/// `bindings::pci_unregister_driver` from `RegistrationOps::unregister`.
109133///
110134/// # Safety
111135///
112- /// A call to [`RegistrationOps::unregister`] for a given instance of `RegType` is only valid if a
113- /// preceding call to [`RegistrationOps::register`] has been successful.
114- pub unsafe trait RegistrationOps {
115- /// The type that holds information about the registration. This is typically a struct defined
116- /// by the C portion of the kernel.
117- type RegType : Default ;
118-
136+ /// A call to [`RegistrationOps::unregister`] for a given instance of `DriverType` is only valid if
137+ /// a preceding call to [`RegistrationOps::register`] has been successful.
138+ pub unsafe trait RegistrationOps : DriverLayout {
119139 /// Registers a driver.
120140 ///
121141 /// # Safety
122142 ///
123143 /// On success, `reg` must remain pinned and valid until the matching call to
124144 /// [`RegistrationOps::unregister`].
125145 unsafe fn register (
126- reg : & Opaque < Self :: RegType > ,
146+ reg : & Opaque < Self :: DriverType > ,
127147 name : & ' static CStr ,
128148 module : & ' static ThisModule ,
129149 ) -> Result ;
@@ -134,7 +154,7 @@ pub unsafe trait RegistrationOps {
134154 ///
135155 /// Must only be called after a preceding successful call to [`RegistrationOps::register`] for
136156 /// the same `reg`.
137- unsafe fn unregister ( reg : & Opaque < Self :: RegType > ) ;
157+ unsafe fn unregister ( reg : & Opaque < Self :: DriverType > ) ;
138158}
139159
140160/// A [`Registration`] is a generic type that represents the registration of some driver type (e.g.
@@ -146,7 +166,7 @@ pub unsafe trait RegistrationOps {
146166#[ pin_data( PinnedDrop ) ]
147167pub struct Registration < T : RegistrationOps > {
148168 #[ pin]
149- reg : Opaque < T :: RegType > ,
169+ reg : Opaque < T :: DriverType > ,
150170}
151171
152172// SAFETY: `Registration` has no fields or methods accessible via `&Registration`, so it is safe to
@@ -157,17 +177,51 @@ unsafe impl<T: RegistrationOps> Sync for Registration<T> {}
157177// any thread, so `Registration` is `Send`.
158178unsafe impl < T : RegistrationOps > Send for Registration < T > { }
159179
160- impl < T : RegistrationOps > Registration < T > {
180+ impl < T : RegistrationOps + ' static > Registration < T > {
181+ extern "C" fn post_unbind_callback ( dev : * mut bindings:: device ) {
182+ // SAFETY: The driver core only ever calls the post unbind callback with a valid pointer to
183+ // a `struct device`.
184+ //
185+ // INVARIANT: `dev` is valid for the duration of the `post_unbind_callback()`.
186+ let dev = unsafe { & * dev. cast :: < device:: Device < device:: CoreInternal > > ( ) } ;
187+
188+ // `remove()` and all devres callbacks have been completed at this point, hence drop the
189+ // driver's device private data.
190+ //
191+ // SAFETY: By the safety requirements of the `Driver` trait, `T::DriverData` is the
192+ // driver's device private data type.
193+ drop ( unsafe { dev. drvdata_obtain :: < T :: DriverData > ( ) } ) ;
194+ }
195+
196+ /// Attach generic `struct device_driver` callbacks.
197+ fn callbacks_attach ( drv : & Opaque < T :: DriverType > ) {
198+ let ptr = drv. get ( ) . cast :: < u8 > ( ) ;
199+
200+ // SAFETY:
201+ // - `drv.get()` yields a valid pointer to `Self::DriverType`.
202+ // - Adding `DEVICE_DRIVER_OFFSET` yields the address of the embedded `struct device_driver`
203+ // as guaranteed by the safety requirements of the `Driver` trait.
204+ let base = unsafe { ptr. add ( T :: DEVICE_DRIVER_OFFSET ) } ;
205+
206+ // CAST: `base` points to the offset of the embedded `struct device_driver`.
207+ let base = base. cast :: < bindings:: device_driver > ( ) ;
208+
209+ // SAFETY: It is safe to set the fields of `struct device_driver` on initialization.
210+ unsafe { ( * base) . p_cb . post_unbind_rust = Some ( Self :: post_unbind_callback) } ;
211+ }
212+
161213 /// Creates a new instance of the registration object.
162214 pub fn new ( name : & ' static CStr , module : & ' static ThisModule ) -> impl PinInit < Self , Error > {
163215 try_pin_init ! ( Self {
164- reg <- Opaque :: try_ffi_init( |ptr: * mut T :: RegType | {
216+ reg <- Opaque :: try_ffi_init( |ptr: * mut T :: DriverType | {
165217 // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write.
166- unsafe { ptr. write( T :: RegType :: default ( ) ) } ;
218+ unsafe { ptr. write( T :: DriverType :: default ( ) ) } ;
167219
168220 // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write, and it has
169221 // just been initialised above, so it's also valid for read.
170- let drv = unsafe { & * ( ptr as * const Opaque <T :: RegType >) } ;
222+ let drv = unsafe { & * ( ptr as * const Opaque <T :: DriverType >) } ;
223+
224+ Self :: callbacks_attach( drv) ;
171225
172226 // SAFETY: `drv` is guaranteed to be pinned until `T::unregister`.
173227 unsafe { T :: register( drv, name, module) }
0 commit comments