summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanilo Krummrich <dakr@kernel.org>2024-08-27 13:19:34 +0200
committerDanilo Krummrich <dakr@kernel.org>2024-08-27 13:22:07 +0200
commit9e4674f5e9b29b8a20012e1192ef11c208233c94 (patch)
tree9712da057fb5135233c1a65e7d1ab7f10971668c
parentc24e57ccf49ffb6bfe9074f0a1a8b689dd1aff14 (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.rs33
-rw-r--r--samples/rust/rust_pci_driver/mod.rs10
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),
})
}
}