diff options
author | Danilo Krummrich <dakr@kernel.org> | 2024-08-27 13:19:34 +0200 |
---|---|---|
committer | Danilo Krummrich <dakr@kernel.org> | 2024-08-27 13:22:07 +0200 |
commit | 9e4674f5e9b29b8a20012e1192ef11c208233c94 (patch) | |
tree | 9712da057fb5135233c1a65e7d1ab7f10971668c | |
parent | c24e57ccf49ffb6bfe9074f0a1a8b689dd1aff14 (diff) |
rust: driver: use in-place init for `Registration`kangrejos
Use in-place init to avoid dynamic allocation of driver structures.
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
-rw-r--r-- | rust/kernel/driver.rs | 33 | ||||
-rw-r--r-- | samples/rust/rust_pci_driver/mod.rs | 10 |
2 files changed, 23 insertions, 20 deletions
diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs index 4fec6ee1a90d..40244f540853 100644 --- a/rust/kernel/driver.rs +++ b/rust/kernel/driver.rs @@ -2,9 +2,8 @@ //! Generic driver support -use core::cell::UnsafeCell; -use core::marker::PhantomData; -use kernel::{alloc::flags::*, prelude::*}; +use crate::types::Opaque; +use kernel::prelude::*; /// The [`RegistrationOps`] trait serves as generic interface for subsystems (e.g., PCI, Platform, /// Amba, etc.) to privide the corresponding subsystem specific implementation to register / @@ -46,9 +45,10 @@ pub trait RegistrationOps { /// /// The existance of an instance of this structure implies that the corresponding driver is /// currently registered. +#[pin_data(PinnedDrop)] pub struct Registration<T: RegistrationOps> { - driver: Pin<KBox<UnsafeCell<T::RegType>>>, - _p: PhantomData<T>, + #[pin] + driver: Opaque<T::RegType>, } impl<T> Registration<T> @@ -56,25 +56,26 @@ where T: RegistrationOps, { /// Register a new driver from `T::RegType`. - pub fn new(name: &'static CStr, module: &'static ThisModule) -> Result<Self> { - let driver = KBox::pin(UnsafeCell::new(T::RegType::default()), GFP_KERNEL)?; + pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl PinInit<Self, Error> { + try_pin_init!(Self { + driver <- Opaque::try_ffi_init(|ptr: *mut T::RegType| { + // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write. + unsafe { ptr.write(T::RegType::default()) }; - // SAFETY: `driver` has just been initialized; it's only freed after `Self::drop`, which - // calls `T::unregister` first. - unsafe { T::register(driver.get(), name, module) }?; - - Ok(Self { - driver, - _p: PhantomData::<T>, + // SAFETY: `driver` has just been initialized; `T::unregister` is called on + // `Self::drop`. + unsafe { T::register(ptr, name, module) } + }), }) } } -impl<T> Drop for Registration<T> +#[pinned_drop] +impl<T> PinnedDrop for Registration<T> where T: RegistrationOps, { - fn drop(&mut self) { + fn drop(self: Pin<&mut Self>) { // SAFETY: Only ever called if the `Registration` was created successfully. unsafe { T::unregister(self.driver.get()) }; } diff --git a/samples/rust/rust_pci_driver/mod.rs b/samples/rust/rust_pci_driver/mod.rs index e4e848d7c59d..9685bd6d2cde 100644 --- a/samples/rust/rust_pci_driver/mod.rs +++ b/samples/rust/rust_pci_driver/mod.rs @@ -14,14 +14,16 @@ module! { license: "GPL", } +#[pin_data] struct Module { + #[pin] _reg: kernel::driver::Registration<pci::Adapter<driver::Driver>>, } -impl kernel::Module for Module { - fn init(name: &'static CStr, module: &'static ThisModule) -> Result<Self> { - Ok(Module { - _reg: kernel::driver::Registration::new(name, module)?, +impl kernel::InPlaceModule for Module { + fn init(name: &'static CStr, module: &'static ThisModule) -> impl PinInit<Self, Error> { + try_pin_init!(Module { + _reg <- kernel::driver::Registration::new(name, module), }) } } |