xref: /linux/rust/kernel/auxiliary.rs (revision 5b0764a53235d3c77e1ed674e836e1b3fe1a4b1f)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 //! Abstractions for the auxiliary bus.
4 //!
5 //! C header: [`include/linux/auxiliary_bus.h`](srctree/include/linux/auxiliary_bus.h)
6 
7 use crate::{
8     bindings,
9     container_of,
10     device,
11     device_id::{
12         RawDeviceId,
13         RawDeviceIdIndex, //
14     },
15 
16     driver,
17     error::{
18         from_result,
19         to_result, //
20     },
21     prelude::*,
22     types::{
23         CovariantForLt,
24         ForLt,
25         ForeignOwnable,
26         Opaque, //
27     },
28     ThisModule, //
29 };
30 use core::{
31     any::TypeId,
32     marker::PhantomData,
33     mem::offset_of,
34     pin::Pin,
35     ptr::{
36         addr_of_mut,
37         NonNull, //
38     },
39 };
40 
41 /// An adapter for the registration of auxiliary drivers.
42 pub struct Adapter<T: Driver>(T);
43 
44 // SAFETY:
45 // - `bindings::auxiliary_driver` is a C type declared as `repr(C)`.
46 // - `T::Data` is the type of the driver's device private data.
47 // - `struct auxiliary_driver` embeds a `struct device_driver`.
48 // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`.
49 unsafe impl<T: Driver> driver::DriverLayout for Adapter<T> {
50     type DriverType = bindings::auxiliary_driver;
51     type DriverData<'bound> = T::Data<'bound>;
52     const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver);
53 }
54 
55 // SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
56 // a preceding call to `register` has been successful.
57 unsafe impl<T: Driver> driver::RegistrationOps for Adapter<T> {
58     unsafe fn register(
59         adrv: &Opaque<Self::DriverType>,
60         name: &'static CStr,
61         module: &'static ThisModule,
62     ) -> Result {
63         // SAFETY: It's safe to set the fields of `struct auxiliary_driver` on initialization.
64         unsafe {
65             (*adrv.get()).name = name.as_char_ptr();
66             (*adrv.get()).probe = Some(Self::probe_callback);
67             (*adrv.get()).remove = Some(Self::remove_callback);
68             (*adrv.get()).id_table = T::ID_TABLE.as_ptr();
69         }
70 
71         // SAFETY: `adrv` is guaranteed to be a valid `DriverType`.
72         to_result(unsafe {
73             bindings::__auxiliary_driver_register(adrv.get(), module.as_ptr(), name.as_char_ptr())
74         })
75     }
76 
77     unsafe fn unregister(adrv: &Opaque<Self::DriverType>) {
78         // SAFETY: `adrv` is guaranteed to be a valid `DriverType`.
79         unsafe { bindings::auxiliary_driver_unregister(adrv.get()) }
80     }
81 }
82 
83 impl<T: Driver> Adapter<T> {
84     extern "C" fn probe_callback(
85         adev: *mut bindings::auxiliary_device,
86         id: *const bindings::auxiliary_device_id,
87     ) -> c_int {
88         // SAFETY: The auxiliary bus only ever calls the probe callback with a valid pointer to a
89         // `struct auxiliary_device`.
90         //
91         // INVARIANT: `adev` is valid for the duration of `probe_callback()`.
92         let adev = unsafe { &*adev.cast::<Device<device::CoreInternal<'_>>>() };
93 
94         // SAFETY: `DeviceId` is a `#[repr(transparent)`] wrapper of `struct auxiliary_device_id`
95         // and does not add additional invariants, so it's safe to transmute.
96         let id = unsafe { &*id.cast::<DeviceId>() };
97 
98         // SAFETY: `id` comes from `T::ID_TABLE` which is of type `IdArray<_, T::IdInfo>`.
99         let info = unsafe { id.info_unchecked::<T::IdInfo>() };
100 
101         from_result(|| {
102             let data = T::probe(adev, info);
103 
104             adev.as_ref().set_drvdata(data)?;
105             Ok(0)
106         })
107     }
108 
109     extern "C" fn remove_callback(adev: *mut bindings::auxiliary_device) {
110         // SAFETY: The auxiliary bus only ever calls the probe callback with a valid pointer to a
111         // `struct auxiliary_device`.
112         //
113         // INVARIANT: `adev` is valid for the duration of `remove_callback()`.
114         let adev = unsafe { &*adev.cast::<Device<device::CoreInternal<'_>>>() };
115 
116         // SAFETY: `remove_callback` is only ever called after a successful call to
117         // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called
118         // and stored a `Pin<KBox<T::Data<'_>>>`.
119         let data = unsafe { adev.as_ref().drvdata_borrow::<T::Data<'_>>() };
120 
121         T::unbind(adev, data);
122     }
123 }
124 
125 /// Declares a kernel module that exposes a single auxiliary driver.
126 #[macro_export]
127 macro_rules! module_auxiliary_driver {
128     ($($f:tt)*) => {
129         $crate::module_driver!(<T>, $crate::auxiliary::Adapter<T>, { $($f)* });
130     };
131 }
132 
133 /// Abstraction for `bindings::auxiliary_device_id`.
134 #[repr(transparent)]
135 #[derive(Clone, Copy)]
136 pub struct DeviceId(bindings::auxiliary_device_id);
137 
138 impl DeviceId {
139     /// Create a new [`DeviceId`] from name.
140     ///
141     /// This is only intended to be called in const context, when constructing a
142     /// device ID table, where exceeding `AUXILIARY_NAME_SIZE` is a compile time error.
143     pub const fn new(modname: &'static CStr, name: &'static CStr) -> Self {
144         let name = name.to_bytes_with_nul();
145         let modname = modname.to_bytes_with_nul();
146 
147         assert!(
148             modname.len().saturating_add(name.len()) <= bindings::AUXILIARY_NAME_SIZE as usize,
149             "auxiliary device ID is too long"
150         );
151 
152         let mut id: bindings::auxiliary_device_id = pin_init::zeroed();
153         let mut i = 0;
154         while i < modname.len() {
155             id.name[i] = modname[i];
156             i += 1;
157         }
158 
159         // Reuse the space of the NULL terminator.
160         id.name[i - 1] = b'.';
161 
162         let mut j = 0;
163         while j < name.len() {
164             id.name[i] = name[j];
165             i += 1;
166             j += 1;
167         }
168 
169         Self(id)
170     }
171 }
172 
173 // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `auxiliary_device_id` and does not add
174 // additional invariants, so it's safe to transmute to `RawType`.
175 unsafe impl RawDeviceId for DeviceId {
176     type RawType = bindings::auxiliary_device_id;
177 }
178 
179 // SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field.
180 unsafe impl RawDeviceIdIndex for DeviceId {
181     const DRIVER_DATA_OFFSET: usize =
182         core::mem::offset_of!(bindings::auxiliary_device_id, driver_data);
183 }
184 
185 /// IdTable type for auxiliary drivers.
186 pub type IdTable<T> = &'static dyn kernel::device_id::IdTable<DeviceId, T>;
187 
188 /// Create a auxiliary `IdTable` with its alias for modpost.
189 #[macro_export]
190 macro_rules! auxiliary_device_table {
191     ($($tt:tt)*) => {
192         $crate::module_device_table!("auxiliary", $crate::auxiliary::DeviceId, $($tt)*);
193     };
194 }
195 
196 /// The auxiliary driver trait.
197 ///
198 /// Drivers must implement this trait in order to get an auxiliary driver registered.
199 pub trait Driver {
200     /// The type holding information about each device id supported by the driver.
201     ///
202     /// TODO: Use associated_type_defaults once stabilized:
203     ///
204     /// type IdInfo: 'static = ();
205     type IdInfo: 'static;
206 
207     /// The type of the driver's bus device private data.
208     type Data<'bound>: Send + 'bound;
209 
210     /// The table of device ids supported by the driver.
211     const ID_TABLE: IdTable<Self::IdInfo>;
212 
213     /// Auxiliary driver probe.
214     ///
215     /// Called when an auxiliary device is matches a corresponding driver.
216     fn probe<'bound>(
217         dev: &'bound Device<device::Core<'_>>,
218         id_info: &'bound Self::IdInfo,
219     ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound;
220 
221     /// Auxiliary driver unbind.
222     ///
223     /// Called when a [`Device`] is unbound from its bound [`Driver`]. Implementing this callback
224     /// is optional.
225     ///
226     /// This callback serves as a place for drivers to perform teardown operations that require a
227     /// `&Device<Core>` or `&Device<Bound>` reference. For instance, drivers may try to perform I/O
228     /// operations to gracefully tear down the device.
229     ///
230     /// Otherwise, release operations for driver resources should be performed in `Drop`.
231     fn unbind<'bound>(dev: &'bound Device<device::Core<'_>>, this: Pin<&Self::Data<'bound>>) {
232         let _ = (dev, this);
233     }
234 }
235 
236 /// The auxiliary device representation.
237 ///
238 /// This structure represents the Rust abstraction for a C `struct auxiliary_device`. The
239 /// implementation abstracts the usage of an already existing C `struct auxiliary_device` within
240 /// Rust code that we get passed from the C side.
241 ///
242 /// # Invariants
243 ///
244 /// A [`Device`] instance represents a valid `struct auxiliary_device` created by the C portion of
245 /// the kernel.
246 #[repr(transparent)]
247 pub struct Device<Ctx: device::DeviceContext = device::Normal>(
248     Opaque<bindings::auxiliary_device>,
249     PhantomData<Ctx>,
250 );
251 
252 impl<Ctx: device::DeviceContext> Device<Ctx> {
253     fn as_raw(&self) -> *mut bindings::auxiliary_device {
254         self.0.get()
255     }
256 
257     /// Returns the auxiliary device' id.
258     pub fn id(&self) -> u32 {
259         // SAFETY: By the type invariant `self.as_raw()` is a valid pointer to a
260         // `struct auxiliary_device`.
261         unsafe { (*self.as_raw()).id }
262     }
263 }
264 
265 impl Device<device::Bound> {
266     /// Returns a bound reference to the parent [`device::Device`].
267     pub fn parent(&self) -> &device::Device<device::Bound> {
268         let parent = (**self).parent();
269 
270         // SAFETY: A bound auxiliary device always has a bound parent device.
271         unsafe { parent.as_bound() }
272     }
273 
274     /// Returns the stored registration data as a pinned reference.
275     ///
276     /// Performs null and [`TypeId`] checks, then borrows the stored [`KBox`].
277     ///
278     /// # Safety
279     ///
280     /// Callers must ensure that the lifetime shortening from the original `'static` storage to
281     /// `'_` is sound, e.g. via an HRTB closure or [`CovariantForLt`] guarantee.
282     unsafe fn registration_data_pinned<F: ForLt + 'static>(&self) -> Result<Pin<&F::Of<'_>>> {
283         // SAFETY: By the type invariant, `self.as_raw()` is a valid `struct auxiliary_device`.
284         let ptr = unsafe { (*self.as_raw()).registration_data_rust };
285         if ptr.is_null() {
286             dev_warn!(
287                 self.as_ref(),
288                 "No registration data set; parent is not a Rust driver.\n"
289             );
290             return Err(ENOENT);
291         }
292 
293         // SAFETY: `ptr` is non-null and was set via `into_foreign()` in `Registration::new()`;
294         // `RegistrationData` is `#[repr(C)]` with `type_id` at offset 0, so reading a `TypeId`
295         // at the start of the allocation is valid regardless of `F`.
296         let type_id = unsafe { ptr.cast::<TypeId>().read() };
297         if type_id != TypeId::of::<F>() {
298             return Err(EINVAL);
299         }
300 
301         // SAFETY: The `TypeId` check above confirms that the stored type matches `F`'s
302         // encoding; lifetimes are erased at runtime, so borrowing as `F::Of<'_>` is
303         // layout-compatible with the stored `F::Of<'static>`. `ptr` remains valid until
304         // `Registration::drop()` calls `from_foreign()`.
305         let wrapper = unsafe { Pin::<KBox<RegistrationData<F::Of<'_>>>>::borrow(ptr) };
306 
307         // SAFETY: `data` is a structurally pinned field of `RegistrationData`.
308         Ok(unsafe { wrapper.map_unchecked(|w| &w.data) })
309     }
310 
311     /// Access the registration data set by the registering (parent) driver through a closure.
312     ///
313     /// `F` is the [`ForLt`](trait@ForLt) encoding of the data type. The closure receives a pinned
314     /// reference to the registration data.
315     ///
316     /// The outer reference carries the `&self` lifetime while the inner type carries the HRTB
317     /// lifetime `'a`, implying `'a` outlives `&self`. This allows the closure to coerce covariant
318     /// sub-fields (e.g. `&'a T` to the caller's lifetime) and return them directly in `R`.
319     ///
320     /// For covariant types that implement [`trait@CovariantForLt`], prefer
321     /// [`registration_data`](Self::registration_data) which returns a direct reference.
322     ///
323     /// Returns [`EINVAL`] if `F` does not match the type used by the parent driver when calling
324     /// [`Registration::new()`].
325     ///
326     /// Returns [`ENOENT`] if no registration data has been set, e.g. when the device was
327     /// registered by a C driver.
328     #[inline]
329     pub fn registration_data_with<'this, F: ForLt + 'static, R>(
330         &'this self,
331         f: impl for<'a> FnOnce(Pin<&'this F::Of<'a>>) -> R,
332     ) -> Result<R> {
333         // SAFETY: The HRTB on the inner type prevents the caller from exploiting a specific
334         // choice of `'a`. Covariant sub-fields can be safely coerced to `'this`, while
335         // invariant fields cannot be coerced and thus cannot escape with an incorrect
336         // lifetime.
337         let pinned = unsafe { self.registration_data_pinned::<F>()? };
338 
339         Ok(f(pinned))
340     }
341 
342     /// Returns a pinned reference to the registration data set by the registering (parent) driver.
343     ///
344     /// This method is only available when `F` implements [`trait@CovariantForLt`], which guarantees
345     /// that the lifetime shortening is sound.
346     ///
347     /// For non-covariant types, use the closure-based [`Self::registration_data_with`].
348     ///
349     /// Returns [`EINVAL`] if `F` does not match the type used by the parent driver when calling
350     /// [`Registration::new()`].
351     ///
352     /// Returns [`ENOENT`] if no registration data has been set, e.g. when the device was
353     /// registered by a C driver.
354     #[inline]
355     pub fn registration_data<F: CovariantForLt + 'static>(&self) -> Result<Pin<&F::Of<'_>>> {
356         // SAFETY: `CovariantForLt` guarantees covariance, which makes the lifetime shortening
357         // from `'static` to `'_` performed by `registration_data_pinned` sound.
358         unsafe { self.registration_data_pinned::<F>() }
359     }
360 }
361 
362 impl Device {
363     /// Returns a reference to the parent [`device::Device`].
364     pub fn parent(&self) -> &device::Device {
365         // SAFETY: A `struct auxiliary_device` always has a parent.
366         unsafe { self.as_ref().parent().unwrap_unchecked() }
367     }
368 
369     extern "C" fn release(dev: *mut bindings::device) {
370         // SAFETY: By the type invariant `self.0.as_raw` is a pointer to the `struct device`
371         // embedded in `struct auxiliary_device`.
372         let adev = unsafe { container_of!(dev, bindings::auxiliary_device, dev) };
373 
374         // SAFETY: `adev` points to the memory that has been allocated in `Registration::new`, via
375         // `KBox::new(Opaque::<bindings::auxiliary_device>::zeroed(), GFP_KERNEL)`.
376         let _ = unsafe { KBox::<Opaque<bindings::auxiliary_device>>::from_raw(adev.cast()) };
377     }
378 }
379 
380 // SAFETY: `auxiliary::Device` is a transparent wrapper of `struct auxiliary_device`.
381 // The offset is guaranteed to point to a valid device field inside `auxiliary::Device`.
382 unsafe impl<Ctx: device::DeviceContext> device::AsBusDevice<Ctx> for Device<Ctx> {
383     const OFFSET: usize = offset_of!(bindings::auxiliary_device, dev);
384 }
385 
386 // SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic
387 // argument.
388 kernel::impl_device_context_deref!(unsafe { Device });
389 kernel::impl_device_context_into_aref!(Device);
390 
391 // SAFETY: Instances of `Device` are always reference-counted.
392 unsafe impl crate::sync::aref::AlwaysRefCounted for Device {
393     fn inc_ref(&self) {
394         // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
395         unsafe { bindings::get_device(self.as_ref().as_raw()) };
396     }
397 
398     unsafe fn dec_ref(obj: NonNull<Self>) {
399         // CAST: `Self` a transparent wrapper of `bindings::auxiliary_device`.
400         let adev: *mut bindings::auxiliary_device = obj.cast().as_ptr();
401 
402         // SAFETY: By the type invariant of `Self`, `adev` is a pointer to a valid
403         // `struct auxiliary_device`.
404         let dev = unsafe { addr_of_mut!((*adev).dev) };
405 
406         // SAFETY: The safety requirements guarantee that the refcount is non-zero.
407         unsafe { bindings::put_device(dev) }
408     }
409 }
410 
411 impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> {
412     fn as_ref(&self) -> &device::Device<Ctx> {
413         // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid
414         // `struct auxiliary_device`.
415         let dev = unsafe { addr_of_mut!((*self.as_raw()).dev) };
416 
417         // SAFETY: `dev` points to a valid `struct device`.
418         unsafe { device::Device::from_raw(dev) }
419     }
420 }
421 
422 // SAFETY: A `Device` is always reference-counted and can be released from any thread.
423 unsafe impl Send for Device {}
424 
425 // SAFETY: `Device` can be shared among threads because all methods of `Device`
426 // (i.e. `Device<Normal>) are thread safe.
427 unsafe impl Sync for Device {}
428 
429 // SAFETY: Same as `Device<Normal>` -- the underlying `struct auxiliary_device` is the same;
430 // `Bound` is a zero-sized type-state marker that does not affect thread safety.
431 unsafe impl Sync for Device<device::Bound> {}
432 
433 /// Wrapper that stores a [`TypeId`] alongside the registration data for runtime type checking.
434 #[repr(C)]
435 #[pin_data]
436 struct RegistrationData<T> {
437     type_id: TypeId,
438     #[pin]
439     data: T,
440 }
441 
442 /// The registration of an auxiliary device.
443 ///
444 /// This type represents the registration of a [`struct auxiliary_device`]. When its parent device
445 /// is unbound, the corresponding auxiliary device will be unregistered from the system.
446 ///
447 /// The type parameter `F` is a [`ForLt`](trait@ForLt) encoding of the registration
448 /// data type. For non-lifetime-parameterized types, use [`ForLt!(T)`](macro@ForLt).
449 ///
450 /// The data can be accessed by the auxiliary driver through [`Device::registration_data()`] and
451 /// [`Device::registration_data_with()`].
452 ///
453 /// # Invariants
454 ///
455 /// `self.adev` always holds a valid pointer to an initialized and registered
456 /// [`struct auxiliary_device`] whose `registration_data_rust` field points to a
457 /// valid `Pin<KBox<RegistrationData<F::Of<'static>>>>`.
458 pub struct Registration<'a, F: ForLt + 'static> {
459     adev: NonNull<bindings::auxiliary_device>,
460     _phantom: PhantomData<F::Of<'a>>,
461 }
462 
463 impl<'a, F: ForLt> Registration<'a, F>
464 where
465     for<'b> F::Of<'b>: Send + Sync,
466 {
467     /// Create and register a new auxiliary device with the given registration data.
468     ///
469     /// The `data` is owned by the registration and can be accessed through the auxiliary device
470     /// via [`Device::registration_data()`].
471     ///
472     /// # Safety
473     ///
474     /// The caller must not `mem::forget()` the returned [`Registration`] or otherwise prevent its
475     /// [`Drop`] implementation from running, since the registration data may contain borrowed
476     /// references that become invalid after `'a` ends.
477     ///
478     /// If the registration data is `'static`, use the safe [`Registration::new()`] instead.
479     pub unsafe fn new_with_lt<E>(
480         parent: &'a device::Device<device::Bound>,
481         name: &CStr,
482         id: u32,
483         modname: &CStr,
484         data: impl PinInit<F::Of<'a>, E>,
485     ) -> Result<Self>
486     where
487         Error: From<E>,
488     {
489         let data = KBox::pin_init::<Error>(
490             try_pin_init!(RegistrationData {
491                 type_id: TypeId::of::<F>(),
492                 data <- data,
493             }),
494             GFP_KERNEL,
495         )?;
496 
497         // SAFETY: `'a` is invariant (via `Registration`'s `PhantomData`). Lifetimes do not
498         // affect layout, so RegistrationData<F::Of<'a>> and RegistrationData<F::Of<'static>>
499         // have identical representation.
500         let data: Pin<KBox<RegistrationData<F::Of<'static>>>> =
501             unsafe { core::mem::transmute(data) };
502 
503         let boxed: KBox<Opaque<bindings::auxiliary_device>> = KBox::zeroed(GFP_KERNEL)?;
504         let adev = boxed.get();
505 
506         // SAFETY: It's safe to set the fields of `struct auxiliary_device` on initialization.
507         unsafe {
508             (*adev).dev.parent = parent.as_raw();
509             (*adev).dev.release = Some(Device::release);
510             (*adev).name = name.as_char_ptr();
511             (*adev).id = id;
512             (*adev).registration_data_rust = data.into_foreign();
513         }
514 
515         // SAFETY: `adev` is guaranteed to be a valid pointer to a `struct auxiliary_device`,
516         // which has not been initialized yet.
517         unsafe { bindings::auxiliary_device_init(adev) };
518 
519         // Now that `adev` is initialized, leak the `Box`; the corresponding memory will be
520         // freed by `Device::release` when the last reference to the `struct auxiliary_device`
521         // is dropped.
522         let _ = KBox::into_raw(boxed);
523 
524         // SAFETY:
525         // - `adev` is guaranteed to be a valid pointer to a `struct auxiliary_device`, which
526         //   has been initialized,
527         // - `modname.as_char_ptr()` is a NULL terminated string.
528         let ret = unsafe { bindings::__auxiliary_device_add(adev, modname.as_char_ptr()) };
529         if ret != 0 {
530             // SAFETY: `registration_data` was set above via `into_foreign()`.
531             drop(unsafe {
532                 Pin::<KBox<RegistrationData<F::Of<'static>>>>::from_foreign(
533                     (*adev).registration_data_rust,
534                 )
535             });
536 
537             // SAFETY: `adev` is guaranteed to be a valid pointer to a
538             // `struct auxiliary_device`, which has been initialized.
539             unsafe { bindings::auxiliary_device_uninit(adev) };
540 
541             return Err(Error::from_errno(ret));
542         }
543 
544         // INVARIANT: The device will remain registered until `auxiliary_device_delete()` is
545         // called, which happens in `Self::drop()`.
546         Ok(Self {
547             // SAFETY: `adev` is guaranteed to be non-null, since the `KBox` was allocated
548             // successfully.
549             adev: unsafe { NonNull::new_unchecked(adev) },
550             _phantom: PhantomData,
551         })
552     }
553 
554     /// Create and register a new auxiliary device with `'static` registration data.
555     ///
556     /// Safe variant of [`Registration::new_with_lt()`] for registration data that does not contain
557     /// borrowed references.
558     pub fn new<E>(
559         parent: &'a device::Device<device::Bound>,
560         name: &CStr,
561         id: u32,
562         modname: &CStr,
563         data: impl PinInit<F::Of<'a>, E>,
564     ) -> Result<Self>
565     where
566         F::Of<'a>: 'static,
567         Error: From<E>,
568     {
569         // SAFETY: `F::Of<'a>: 'static` guarantees the data contains no borrowed references,
570         // so forgetting the `Registration` cannot cause use-after-free.
571         unsafe { Self::new_with_lt(parent, name, id, modname, data) }
572     }
573 }
574 
575 impl<F: ForLt> Drop for Registration<'_, F> {
576     fn drop(&mut self) {
577         // SAFETY: By the type invariant of `Self`, `self.adev.as_ptr()` is a valid registered
578         // `struct auxiliary_device`.
579         unsafe { bindings::auxiliary_device_delete(self.adev.as_ptr()) };
580 
581         // SAFETY: `registration_data` was set in `new()` via `into_foreign()`.
582         drop(unsafe {
583             Pin::<KBox<RegistrationData<F::Of<'static>>>>::from_foreign(
584                 (*self.adev.as_ptr()).registration_data_rust,
585             )
586         });
587 
588         // This drops the reference we acquired through `auxiliary_device_init()`.
589         //
590         // SAFETY: By the type invariant of `Self`, `self.adev.as_ptr()` is a valid registered
591         // `struct auxiliary_device`.
592         unsafe { bindings::auxiliary_device_uninit(self.adev.as_ptr()) };
593     }
594 }
595 
596 // SAFETY: A `Registration` of a `struct auxiliary_device` can be released from any thread.
597 unsafe impl<F: ForLt> Send for Registration<'_, F> where for<'a> F::Of<'a>: Send {}
598 
599 // SAFETY: `Registration` does not expose any methods or fields that need synchronization.
600 unsafe impl<F: ForLt> Sync for Registration<'_, F> where for<'a> F::Of<'a>: Send {}
601