mirror of
https://github.com/torvalds/linux.git
synced 2026-01-24 23:16:46 +00:00
rust: driver: introduce a DriverLayout trait
The DriverLayout trait describes the layout of a specific driver structure, such as `struct pci_driver` or `struct platform_driver`. In a first step, this replaces the associated type RegType of the RegistrationOps with the DriverLayout::DriverType associated type. Acked-by: Alice Ryhl <aliceryhl@google.com> Acked-by: Igor Korotin <igor.korotin.linux@gmail.com> Link: https://patch.msgid.link/20260107103511.570525-4-dakr@kernel.org [ Rename driver::Driver to driver::DriverLayout, as it represents the layout of a driver structure rather than the driver structure itself. - Danilo ] Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
@@ -23,13 +23,17 @@ use core::{
|
||||
/// An adapter for the registration of auxiliary drivers.
|
||||
pub struct Adapter<T: Driver>(T);
|
||||
|
||||
// SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if
|
||||
// SAFETY:
|
||||
// - `bindings::auxiliary_driver` is a C type declared as `repr(C)`.
|
||||
unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> {
|
||||
type DriverType = bindings::auxiliary_driver;
|
||||
}
|
||||
|
||||
// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
|
||||
// a preceding call to `register` has been successful.
|
||||
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
|
||||
type RegType = bindings::auxiliary_driver;
|
||||
|
||||
unsafe fn register(
|
||||
adrv: &Opaque<Self::RegType>,
|
||||
adrv: &Opaque<Self::DriverType>,
|
||||
name: &'static CStr,
|
||||
module: &'static ThisModule,
|
||||
) -> Result {
|
||||
@@ -41,14 +45,14 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
|
||||
(*adrv.get()).id_table = T::ID_TABLE.as_ptr();
|
||||
}
|
||||
|
||||
// SAFETY: `adrv` is guaranteed to be a valid `RegType`.
|
||||
// SAFETY: `adrv` is guaranteed to be a valid `DriverType`.
|
||||
to_result(unsafe {
|
||||
bindings::__auxiliary_driver_register(adrv.get(), module.0, name.as_char_ptr())
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn unregister(adrv: &Opaque<Self::RegType>) {
|
||||
// SAFETY: `adrv` is guaranteed to be a valid `RegType`.
|
||||
unsafe fn unregister(adrv: &Opaque<Self::DriverType>) {
|
||||
// SAFETY: `adrv` is guaranteed to be a valid `DriverType`.
|
||||
unsafe { bindings::auxiliary_driver_unregister(adrv.get()) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,23 +99,33 @@ use crate::{acpi, device, of, str::CStr, try_pin_init, types::Opaque, ThisModule
|
||||
use core::pin::Pin;
|
||||
use pin_init::{pin_data, pinned_drop, PinInit};
|
||||
|
||||
/// Trait describing the layout of a specific device driver.
|
||||
///
|
||||
/// This trait describes the layout of a specific driver structure, such as `struct pci_driver` or
|
||||
/// `struct platform_driver`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Implementors must guarantee that:
|
||||
/// - `DriverType` is `repr(C)`.
|
||||
pub unsafe trait DriverLayout {
|
||||
/// The specific driver type embedding a `struct device_driver`.
|
||||
type DriverType: Default;
|
||||
}
|
||||
|
||||
/// The [`RegistrationOps`] trait serves as generic interface for subsystems (e.g., PCI, Platform,
|
||||
/// Amba, etc.) to provide the corresponding subsystem specific implementation to register /
|
||||
/// unregister a driver of the particular type (`RegType`).
|
||||
/// unregister a driver of the particular type (`DriverType`).
|
||||
///
|
||||
/// For instance, the PCI subsystem would set `RegType` to `bindings::pci_driver` and call
|
||||
/// For instance, the PCI subsystem would set `DriverType` to `bindings::pci_driver` and call
|
||||
/// `bindings::__pci_register_driver` from `RegistrationOps::register` and
|
||||
/// `bindings::pci_unregister_driver` from `RegistrationOps::unregister`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// A call to [`RegistrationOps::unregister`] for a given instance of `RegType` is only valid if a
|
||||
/// preceding call to [`RegistrationOps::register`] has been successful.
|
||||
pub unsafe trait RegistrationOps {
|
||||
/// The type that holds information about the registration. This is typically a struct defined
|
||||
/// by the C portion of the kernel.
|
||||
type RegType: Default;
|
||||
|
||||
/// A call to [`RegistrationOps::unregister`] for a given instance of `DriverType` is only valid if
|
||||
/// a preceding call to [`RegistrationOps::register`] has been successful.
|
||||
pub unsafe trait RegistrationOps: DriverLayout {
|
||||
/// Registers a driver.
|
||||
///
|
||||
/// # Safety
|
||||
@@ -123,7 +133,7 @@ pub unsafe trait RegistrationOps {
|
||||
/// On success, `reg` must remain pinned and valid until the matching call to
|
||||
/// [`RegistrationOps::unregister`].
|
||||
unsafe fn register(
|
||||
reg: &Opaque<Self::RegType>,
|
||||
reg: &Opaque<Self::DriverType>,
|
||||
name: &'static CStr,
|
||||
module: &'static ThisModule,
|
||||
) -> Result;
|
||||
@@ -134,7 +144,7 @@ pub unsafe trait RegistrationOps {
|
||||
///
|
||||
/// Must only be called after a preceding successful call to [`RegistrationOps::register`] for
|
||||
/// the same `reg`.
|
||||
unsafe fn unregister(reg: &Opaque<Self::RegType>);
|
||||
unsafe fn unregister(reg: &Opaque<Self::DriverType>);
|
||||
}
|
||||
|
||||
/// A [`Registration`] is a generic type that represents the registration of some driver type (e.g.
|
||||
@@ -146,7 +156,7 @@ pub unsafe trait RegistrationOps {
|
||||
#[pin_data(PinnedDrop)]
|
||||
pub struct Registration<T: RegistrationOps> {
|
||||
#[pin]
|
||||
reg: Opaque<T::RegType>,
|
||||
reg: Opaque<T::DriverType>,
|
||||
}
|
||||
|
||||
// SAFETY: `Registration` has no fields or methods accessible via `&Registration`, so it is safe to
|
||||
@@ -161,13 +171,13 @@ impl<T: RegistrationOps> Registration<T> {
|
||||
/// Creates a new instance of the registration object.
|
||||
pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl PinInit<Self, Error> {
|
||||
try_pin_init!(Self {
|
||||
reg <- Opaque::try_ffi_init(|ptr: *mut T::RegType| {
|
||||
reg <- Opaque::try_ffi_init(|ptr: *mut T::DriverType| {
|
||||
// SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write.
|
||||
unsafe { ptr.write(T::RegType::default()) };
|
||||
unsafe { ptr.write(T::DriverType::default()) };
|
||||
|
||||
// SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write, and it has
|
||||
// just been initialised above, so it's also valid for read.
|
||||
let drv = unsafe { &*(ptr as *const Opaque<T::RegType>) };
|
||||
let drv = unsafe { &*(ptr as *const Opaque<T::DriverType>) };
|
||||
|
||||
// SAFETY: `drv` is guaranteed to be pinned until `T::unregister`.
|
||||
unsafe { T::register(drv, name, module) }
|
||||
|
||||
@@ -92,13 +92,17 @@ macro_rules! i2c_device_table {
|
||||
/// An adapter for the registration of I2C drivers.
|
||||
pub struct Adapter<T: Driver>(T);
|
||||
|
||||
// SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if
|
||||
// SAFETY:
|
||||
// - `bindings::i2c_driver` is a C type declared as `repr(C)`.
|
||||
unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> {
|
||||
type DriverType = bindings::i2c_driver;
|
||||
}
|
||||
|
||||
// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
|
||||
// a preceding call to `register` has been successful.
|
||||
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
|
||||
type RegType = bindings::i2c_driver;
|
||||
|
||||
unsafe fn register(
|
||||
idrv: &Opaque<Self::RegType>,
|
||||
idrv: &Opaque<Self::DriverType>,
|
||||
name: &'static CStr,
|
||||
module: &'static ThisModule,
|
||||
) -> Result {
|
||||
@@ -133,12 +137,12 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
|
||||
(*idrv.get()).driver.acpi_match_table = acpi_table;
|
||||
}
|
||||
|
||||
// SAFETY: `idrv` is guaranteed to be a valid `RegType`.
|
||||
// SAFETY: `idrv` is guaranteed to be a valid `DriverType`.
|
||||
to_result(unsafe { bindings::i2c_register_driver(module.0, idrv.get()) })
|
||||
}
|
||||
|
||||
unsafe fn unregister(idrv: &Opaque<Self::RegType>) {
|
||||
// SAFETY: `idrv` is guaranteed to be a valid `RegType`.
|
||||
unsafe fn unregister(idrv: &Opaque<Self::DriverType>) {
|
||||
// SAFETY: `idrv` is guaranteed to be a valid `DriverType`.
|
||||
unsafe { bindings::i2c_del_driver(idrv.get()) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,13 +50,17 @@ pub use self::irq::{
|
||||
/// An adapter for the registration of PCI drivers.
|
||||
pub struct Adapter<T: Driver>(T);
|
||||
|
||||
// SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if
|
||||
// SAFETY:
|
||||
// - `bindings::pci_driver` is a C type declared as `repr(C)`.
|
||||
unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> {
|
||||
type DriverType = bindings::pci_driver;
|
||||
}
|
||||
|
||||
// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
|
||||
// a preceding call to `register` has been successful.
|
||||
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
|
||||
type RegType = bindings::pci_driver;
|
||||
|
||||
unsafe fn register(
|
||||
pdrv: &Opaque<Self::RegType>,
|
||||
pdrv: &Opaque<Self::DriverType>,
|
||||
name: &'static CStr,
|
||||
module: &'static ThisModule,
|
||||
) -> Result {
|
||||
@@ -68,14 +72,14 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
|
||||
(*pdrv.get()).id_table = T::ID_TABLE.as_ptr();
|
||||
}
|
||||
|
||||
// SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
|
||||
// SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.
|
||||
to_result(unsafe {
|
||||
bindings::__pci_register_driver(pdrv.get(), module.0, name.as_char_ptr())
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn unregister(pdrv: &Opaque<Self::RegType>) {
|
||||
// SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
|
||||
unsafe fn unregister(pdrv: &Opaque<Self::DriverType>) {
|
||||
// SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.
|
||||
unsafe { bindings::pci_unregister_driver(pdrv.get()) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,13 +26,17 @@ use core::{
|
||||
/// An adapter for the registration of platform drivers.
|
||||
pub struct Adapter<T: Driver>(T);
|
||||
|
||||
// SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if
|
||||
// SAFETY:
|
||||
// - `bindings::platform_driver` is a C type declared as `repr(C)`.
|
||||
unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> {
|
||||
type DriverType = bindings::platform_driver;
|
||||
}
|
||||
|
||||
// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
|
||||
// a preceding call to `register` has been successful.
|
||||
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
|
||||
type RegType = bindings::platform_driver;
|
||||
|
||||
unsafe fn register(
|
||||
pdrv: &Opaque<Self::RegType>,
|
||||
pdrv: &Opaque<Self::DriverType>,
|
||||
name: &'static CStr,
|
||||
module: &'static ThisModule,
|
||||
) -> Result {
|
||||
@@ -55,12 +59,12 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
|
||||
(*pdrv.get()).driver.acpi_match_table = acpi_table;
|
||||
}
|
||||
|
||||
// SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
|
||||
// SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.
|
||||
to_result(unsafe { bindings::__platform_driver_register(pdrv.get(), module.0) })
|
||||
}
|
||||
|
||||
unsafe fn unregister(pdrv: &Opaque<Self::RegType>) {
|
||||
// SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
|
||||
unsafe fn unregister(pdrv: &Opaque<Self::DriverType>) {
|
||||
// SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.
|
||||
unsafe { bindings::platform_driver_unregister(pdrv.get()) };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,13 +27,17 @@ use core::{
|
||||
/// An adapter for the registration of USB drivers.
|
||||
pub struct Adapter<T: Driver>(T);
|
||||
|
||||
// SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if
|
||||
// SAFETY:
|
||||
// - `bindings::usb_driver` is a C type declared as `repr(C)`.
|
||||
unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> {
|
||||
type DriverType = bindings::usb_driver;
|
||||
}
|
||||
|
||||
// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
|
||||
// a preceding call to `register` has been successful.
|
||||
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
|
||||
type RegType = bindings::usb_driver;
|
||||
|
||||
unsafe fn register(
|
||||
udrv: &Opaque<Self::RegType>,
|
||||
udrv: &Opaque<Self::DriverType>,
|
||||
name: &'static CStr,
|
||||
module: &'static ThisModule,
|
||||
) -> Result {
|
||||
@@ -45,14 +49,14 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
|
||||
(*udrv.get()).id_table = T::ID_TABLE.as_ptr();
|
||||
}
|
||||
|
||||
// SAFETY: `udrv` is guaranteed to be a valid `RegType`.
|
||||
// SAFETY: `udrv` is guaranteed to be a valid `DriverType`.
|
||||
to_result(unsafe {
|
||||
bindings::usb_register_driver(udrv.get(), module.0, name.as_char_ptr())
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn unregister(udrv: &Opaque<Self::RegType>) {
|
||||
// SAFETY: `udrv` is guaranteed to be a valid `RegType`.
|
||||
unsafe fn unregister(udrv: &Opaque<Self::DriverType>) {
|
||||
// SAFETY: `udrv` is guaranteed to be a valid `DriverType`.
|
||||
unsafe { bindings::usb_deregister(udrv.get()) };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user