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