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>

+80 -50
+11 -7
rust/kernel/auxiliary.rs
··· 23 /// An adapter for the registration of auxiliary drivers. 24 pub struct Adapter<T: Driver>(T); 25 26 - // SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if 27 // a preceding call to `register` has been successful. 28 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 29 - type RegType = bindings::auxiliary_driver; 30 - 31 unsafe fn register( 32 - adrv: &Opaque<Self::RegType>, 33 name: &'static CStr, 34 module: &'static ThisModule, 35 ) -> Result { ··· 45 (*adrv.get()).id_table = T::ID_TABLE.as_ptr(); 46 } 47 48 - // SAFETY: `adrv` is guaranteed to be a valid `RegType`. 49 to_result(unsafe { 50 bindings::__auxiliary_driver_register(adrv.get(), module.0, name.as_char_ptr()) 51 }) 52 } 53 54 - unsafe fn unregister(adrv: &Opaque<Self::RegType>) { 55 - // SAFETY: `adrv` is guaranteed to be a valid `RegType`. 56 unsafe { bindings::auxiliary_driver_unregister(adrv.get()) } 57 } 58 }
··· 23 /// An adapter for the registration of auxiliary drivers. 24 pub struct Adapter<T: Driver>(T); 25 26 + // SAFETY: 27 + // - `bindings::auxiliary_driver` is a C type declared as `repr(C)`. 28 + unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> { 29 + type DriverType = bindings::auxiliary_driver; 30 + } 31 + 32 + // SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if 33 // a preceding call to `register` has been successful. 34 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 35 unsafe fn register( 36 + adrv: &Opaque<Self::DriverType>, 37 name: &'static CStr, 38 module: &'static ThisModule, 39 ) -> Result { ··· 41 (*adrv.get()).id_table = T::ID_TABLE.as_ptr(); 42 } 43 44 + // SAFETY: `adrv` is guaranteed to be a valid `DriverType`. 45 to_result(unsafe { 46 bindings::__auxiliary_driver_register(adrv.get(), module.0, name.as_char_ptr()) 47 }) 48 } 49 50 + unsafe fn unregister(adrv: &Opaque<Self::DriverType>) { 51 + // SAFETY: `adrv` is guaranteed to be a valid `DriverType`. 52 unsafe { bindings::auxiliary_driver_unregister(adrv.get()) } 53 } 54 }
+25 -15
rust/kernel/driver.rs
··· 99 use core::pin::Pin; 100 use pin_init::{pin_data, pinned_drop, PinInit}; 101 102 /// The [`RegistrationOps`] trait serves as generic interface for subsystems (e.g., PCI, Platform, 103 /// Amba, etc.) to provide the corresponding subsystem specific implementation to register / 104 - /// unregister a driver of the particular type (`RegType`). 105 /// 106 - /// For instance, the PCI subsystem would set `RegType` to `bindings::pci_driver` and call 107 /// `bindings::__pci_register_driver` from `RegistrationOps::register` and 108 /// `bindings::pci_unregister_driver` from `RegistrationOps::unregister`. 109 /// 110 /// # Safety 111 /// 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 - 119 /// Registers a driver. 120 /// 121 /// # Safety ··· 133 /// On success, `reg` must remain pinned and valid until the matching call to 134 /// [`RegistrationOps::unregister`]. 135 unsafe fn register( 136 - reg: &Opaque<Self::RegType>, 137 name: &'static CStr, 138 module: &'static ThisModule, 139 ) -> Result; ··· 144 /// 145 /// Must only be called after a preceding successful call to [`RegistrationOps::register`] for 146 /// the same `reg`. 147 - unsafe fn unregister(reg: &Opaque<Self::RegType>); 148 } 149 150 /// A [`Registration`] is a generic type that represents the registration of some driver type (e.g. ··· 156 #[pin_data(PinnedDrop)] 157 pub struct Registration<T: RegistrationOps> { 158 #[pin] 159 - reg: Opaque<T::RegType>, 160 } 161 162 // SAFETY: `Registration` has no fields or methods accessible via `&Registration`, so it is safe to ··· 171 /// Creates a new instance of the registration object. 172 pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl PinInit<Self, Error> { 173 try_pin_init!(Self { 174 - reg <- Opaque::try_ffi_init(|ptr: *mut T::RegType| { 175 // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write. 176 - unsafe { ptr.write(T::RegType::default()) }; 177 178 // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write, and it has 179 // just been initialised above, so it's also valid for read. 180 - let drv = unsafe { &*(ptr as *const Opaque<T::RegType>) }; 181 182 // SAFETY: `drv` is guaranteed to be pinned until `T::unregister`. 183 unsafe { T::register(drv, name, module) }
··· 99 use core::pin::Pin; 100 use pin_init::{pin_data, pinned_drop, PinInit}; 101 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 + pub unsafe trait DriverLayout { 112 + /// The specific driver type embedding a `struct device_driver`. 113 + type DriverType: Default; 114 + } 115 + 116 /// The [`RegistrationOps`] trait serves as generic interface for subsystems (e.g., PCI, Platform, 117 /// Amba, etc.) to provide the corresponding subsystem specific implementation to register / 118 + /// unregister a driver of the particular type (`DriverType`). 119 /// 120 + /// For instance, the PCI subsystem would set `DriverType` to `bindings::pci_driver` and call 121 /// `bindings::__pci_register_driver` from `RegistrationOps::register` and 122 /// `bindings::pci_unregister_driver` from `RegistrationOps::unregister`. 123 /// 124 /// # Safety 125 /// 126 + /// A call to [`RegistrationOps::unregister`] for a given instance of `DriverType` is only valid if 127 + /// a preceding call to [`RegistrationOps::register`] has been successful. 128 + pub unsafe trait RegistrationOps: DriverLayout { 129 /// Registers a driver. 130 /// 131 /// # Safety ··· 123 /// On success, `reg` must remain pinned and valid until the matching call to 124 /// [`RegistrationOps::unregister`]. 125 unsafe fn register( 126 + reg: &Opaque<Self::DriverType>, 127 name: &'static CStr, 128 module: &'static ThisModule, 129 ) -> Result; ··· 134 /// 135 /// Must only be called after a preceding successful call to [`RegistrationOps::register`] for 136 /// the same `reg`. 137 + unsafe fn unregister(reg: &Opaque<Self::DriverType>); 138 } 139 140 /// A [`Registration`] is a generic type that represents the registration of some driver type (e.g. ··· 146 #[pin_data(PinnedDrop)] 147 pub struct Registration<T: RegistrationOps> { 148 #[pin] 149 + reg: Opaque<T::DriverType>, 150 } 151 152 // SAFETY: `Registration` has no fields or methods accessible via `&Registration`, so it is safe to ··· 161 /// Creates a new instance of the registration object. 162 pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl PinInit<Self, Error> { 163 try_pin_init!(Self { 164 + reg <- Opaque::try_ffi_init(|ptr: *mut T::DriverType| { 165 // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write. 166 + unsafe { ptr.write(T::DriverType::default()) }; 167 168 // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write, and it has 169 // just been initialised above, so it's also valid for read. 170 + let drv = unsafe { &*(ptr as *const Opaque<T::DriverType>) }; 171 172 // SAFETY: `drv` is guaranteed to be pinned until `T::unregister`. 173 unsafe { T::register(drv, name, module) }
+11 -7
rust/kernel/i2c.rs
··· 92 /// An adapter for the registration of I2C drivers. 93 pub struct Adapter<T: Driver>(T); 94 95 - // SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if 96 // a preceding call to `register` has been successful. 97 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 98 - type RegType = bindings::i2c_driver; 99 - 100 unsafe fn register( 101 - idrv: &Opaque<Self::RegType>, 102 name: &'static CStr, 103 module: &'static ThisModule, 104 ) -> Result { ··· 137 (*idrv.get()).driver.acpi_match_table = acpi_table; 138 } 139 140 - // SAFETY: `idrv` is guaranteed to be a valid `RegType`. 141 to_result(unsafe { bindings::i2c_register_driver(module.0, idrv.get()) }) 142 } 143 144 - unsafe fn unregister(idrv: &Opaque<Self::RegType>) { 145 - // SAFETY: `idrv` is guaranteed to be a valid `RegType`. 146 unsafe { bindings::i2c_del_driver(idrv.get()) } 147 } 148 }
··· 92 /// An adapter for the registration of I2C drivers. 93 pub struct Adapter<T: Driver>(T); 94 95 + // SAFETY: 96 + // - `bindings::i2c_driver` is a C type declared as `repr(C)`. 97 + unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> { 98 + type DriverType = bindings::i2c_driver; 99 + } 100 + 101 + // SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if 102 // a preceding call to `register` has been successful. 103 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 104 unsafe fn register( 105 + idrv: &Opaque<Self::DriverType>, 106 name: &'static CStr, 107 module: &'static ThisModule, 108 ) -> Result { ··· 133 (*idrv.get()).driver.acpi_match_table = acpi_table; 134 } 135 136 + // SAFETY: `idrv` is guaranteed to be a valid `DriverType`. 137 to_result(unsafe { bindings::i2c_register_driver(module.0, idrv.get()) }) 138 } 139 140 + unsafe fn unregister(idrv: &Opaque<Self::DriverType>) { 141 + // SAFETY: `idrv` is guaranteed to be a valid `DriverType`. 142 unsafe { bindings::i2c_del_driver(idrv.get()) } 143 } 144 }
+11 -7
rust/kernel/pci.rs
··· 50 /// An adapter for the registration of PCI drivers. 51 pub struct Adapter<T: Driver>(T); 52 53 - // SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if 54 // a preceding call to `register` has been successful. 55 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 56 - type RegType = bindings::pci_driver; 57 - 58 unsafe fn register( 59 - pdrv: &Opaque<Self::RegType>, 60 name: &'static CStr, 61 module: &'static ThisModule, 62 ) -> Result { ··· 72 (*pdrv.get()).id_table = T::ID_TABLE.as_ptr(); 73 } 74 75 - // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. 76 to_result(unsafe { 77 bindings::__pci_register_driver(pdrv.get(), module.0, name.as_char_ptr()) 78 }) 79 } 80 81 - unsafe fn unregister(pdrv: &Opaque<Self::RegType>) { 82 - // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. 83 unsafe { bindings::pci_unregister_driver(pdrv.get()) } 84 } 85 }
··· 50 /// An adapter for the registration of PCI drivers. 51 pub struct Adapter<T: Driver>(T); 52 53 + // SAFETY: 54 + // - `bindings::pci_driver` is a C type declared as `repr(C)`. 55 + unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> { 56 + type DriverType = bindings::pci_driver; 57 + } 58 + 59 + // SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if 60 // a preceding call to `register` has been successful. 61 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 62 unsafe fn register( 63 + pdrv: &Opaque<Self::DriverType>, 64 name: &'static CStr, 65 module: &'static ThisModule, 66 ) -> Result { ··· 68 (*pdrv.get()).id_table = T::ID_TABLE.as_ptr(); 69 } 70 71 + // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`. 72 to_result(unsafe { 73 bindings::__pci_register_driver(pdrv.get(), module.0, name.as_char_ptr()) 74 }) 75 } 76 77 + unsafe fn unregister(pdrv: &Opaque<Self::DriverType>) { 78 + // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`. 79 unsafe { bindings::pci_unregister_driver(pdrv.get()) } 80 } 81 }
+11 -7
rust/kernel/platform.rs
··· 26 /// An adapter for the registration of platform drivers. 27 pub struct Adapter<T: Driver>(T); 28 29 - // SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if 30 // a preceding call to `register` has been successful. 31 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 32 - type RegType = bindings::platform_driver; 33 - 34 unsafe fn register( 35 - pdrv: &Opaque<Self::RegType>, 36 name: &'static CStr, 37 module: &'static ThisModule, 38 ) -> Result { ··· 59 (*pdrv.get()).driver.acpi_match_table = acpi_table; 60 } 61 62 - // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. 63 to_result(unsafe { bindings::__platform_driver_register(pdrv.get(), module.0) }) 64 } 65 66 - unsafe fn unregister(pdrv: &Opaque<Self::RegType>) { 67 - // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. 68 unsafe { bindings::platform_driver_unregister(pdrv.get()) }; 69 } 70 }
··· 26 /// An adapter for the registration of platform drivers. 27 pub struct Adapter<T: Driver>(T); 28 29 + // SAFETY: 30 + // - `bindings::platform_driver` is a C type declared as `repr(C)`. 31 + unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> { 32 + type DriverType = bindings::platform_driver; 33 + } 34 + 35 + // SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if 36 // a preceding call to `register` has been successful. 37 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 38 unsafe fn register( 39 + pdrv: &Opaque<Self::DriverType>, 40 name: &'static CStr, 41 module: &'static ThisModule, 42 ) -> Result { ··· 55 (*pdrv.get()).driver.acpi_match_table = acpi_table; 56 } 57 58 + // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`. 59 to_result(unsafe { bindings::__platform_driver_register(pdrv.get(), module.0) }) 60 } 61 62 + unsafe fn unregister(pdrv: &Opaque<Self::DriverType>) { 63 + // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`. 64 unsafe { bindings::platform_driver_unregister(pdrv.get()) }; 65 } 66 }
+11 -7
rust/kernel/usb.rs
··· 27 /// An adapter for the registration of USB drivers. 28 pub struct Adapter<T: Driver>(T); 29 30 - // SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if 31 // a preceding call to `register` has been successful. 32 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 33 - type RegType = bindings::usb_driver; 34 - 35 unsafe fn register( 36 - udrv: &Opaque<Self::RegType>, 37 name: &'static CStr, 38 module: &'static ThisModule, 39 ) -> Result { ··· 49 (*udrv.get()).id_table = T::ID_TABLE.as_ptr(); 50 } 51 52 - // SAFETY: `udrv` is guaranteed to be a valid `RegType`. 53 to_result(unsafe { 54 bindings::usb_register_driver(udrv.get(), module.0, name.as_char_ptr()) 55 }) 56 } 57 58 - unsafe fn unregister(udrv: &Opaque<Self::RegType>) { 59 - // SAFETY: `udrv` is guaranteed to be a valid `RegType`. 60 unsafe { bindings::usb_deregister(udrv.get()) }; 61 } 62 }
··· 27 /// An adapter for the registration of USB drivers. 28 pub struct Adapter<T: Driver>(T); 29 30 + // SAFETY: 31 + // - `bindings::usb_driver` is a C type declared as `repr(C)`. 32 + unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> { 33 + type DriverType = bindings::usb_driver; 34 + } 35 + 36 + // SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if 37 // a preceding call to `register` has been successful. 38 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 39 unsafe fn register( 40 + udrv: &Opaque<Self::DriverType>, 41 name: &'static CStr, 42 module: &'static ThisModule, 43 ) -> Result { ··· 45 (*udrv.get()).id_table = T::ID_TABLE.as_ptr(); 46 } 47 48 + // SAFETY: `udrv` is guaranteed to be a valid `DriverType`. 49 to_result(unsafe { 50 bindings::usb_register_driver(udrv.get(), module.0, name.as_char_ptr()) 51 }) 52 } 53 54 + unsafe fn unregister(udrv: &Opaque<Self::DriverType>) { 55 + // SAFETY: `udrv` is guaranteed to be a valid `DriverType`. 56 unsafe { bindings::usb_deregister(udrv.get()) }; 57 } 58 }