Skip to content

Commit 0af1a9e

Browse files
author
Danilo Krummrich
committed
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>
1 parent 5f4476e commit 0af1a9e

6 files changed

Lines changed: 80 additions & 50 deletions

File tree

rust/kernel/auxiliary.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,17 @@ use core::{
2323
/// An adapter for the registration of auxiliary drivers.
2424
pub struct Adapter<T: Driver>(T);
2525

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
2733
// a preceding call to `register` has been successful.
2834
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
29-
type RegType = bindings::auxiliary_driver;
30-
3135
unsafe fn register(
32-
adrv: &Opaque<Self::RegType>,
36+
adrv: &Opaque<Self::DriverType>,
3337
name: &'static CStr,
3438
module: &'static ThisModule,
3539
) -> Result {
@@ -41,14 +45,14 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
4145
(*adrv.get()).id_table = T::ID_TABLE.as_ptr();
4246
}
4347

44-
// SAFETY: `adrv` is guaranteed to be a valid `RegType`.
48+
// SAFETY: `adrv` is guaranteed to be a valid `DriverType`.
4549
to_result(unsafe {
4650
bindings::__auxiliary_driver_register(adrv.get(), module.0, name.as_char_ptr())
4751
})
4852
}
4953

50-
unsafe fn unregister(adrv: &Opaque<Self::RegType>) {
51-
// SAFETY: `adrv` is guaranteed to be a valid `RegType`.
54+
unsafe fn unregister(adrv: &Opaque<Self::DriverType>) {
55+
// SAFETY: `adrv` is guaranteed to be a valid `DriverType`.
5256
unsafe { bindings::auxiliary_driver_unregister(adrv.get()) }
5357
}
5458
}

rust/kernel/driver.rs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -99,31 +99,41 @@ use crate::{acpi, device, of, str::CStr, try_pin_init, types::Opaque, ThisModule
9999
use core::pin::Pin;
100100
use pin_init::{pin_data, pinned_drop, PinInit};
101101

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+
102116
/// The [`RegistrationOps`] trait serves as generic interface for subsystems (e.g., PCI, Platform,
103117
/// 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`).
105119
///
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
107121
/// `bindings::__pci_register_driver` from `RegistrationOps::register` and
108122
/// `bindings::pci_unregister_driver` from `RegistrationOps::unregister`.
109123
///
110124
/// # Safety
111125
///
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 {
119129
/// Registers a driver.
120130
///
121131
/// # Safety
122132
///
123133
/// On success, `reg` must remain pinned and valid until the matching call to
124134
/// [`RegistrationOps::unregister`].
125135
unsafe fn register(
126-
reg: &Opaque<Self::RegType>,
136+
reg: &Opaque<Self::DriverType>,
127137
name: &'static CStr,
128138
module: &'static ThisModule,
129139
) -> Result;
@@ -134,7 +144,7 @@ pub unsafe trait RegistrationOps {
134144
///
135145
/// Must only be called after a preceding successful call to [`RegistrationOps::register`] for
136146
/// the same `reg`.
137-
unsafe fn unregister(reg: &Opaque<Self::RegType>);
147+
unsafe fn unregister(reg: &Opaque<Self::DriverType>);
138148
}
139149

140150
/// A [`Registration`] is a generic type that represents the registration of some driver type (e.g.
@@ -146,7 +156,7 @@ pub unsafe trait RegistrationOps {
146156
#[pin_data(PinnedDrop)]
147157
pub struct Registration<T: RegistrationOps> {
148158
#[pin]
149-
reg: Opaque<T::RegType>,
159+
reg: Opaque<T::DriverType>,
150160
}
151161

152162
// SAFETY: `Registration` has no fields or methods accessible via `&Registration`, so it is safe to
@@ -161,13 +171,13 @@ impl<T: RegistrationOps> Registration<T> {
161171
/// Creates a new instance of the registration object.
162172
pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl PinInit<Self, Error> {
163173
try_pin_init!(Self {
164-
reg <- Opaque::try_ffi_init(|ptr: *mut T::RegType| {
174+
reg <- Opaque::try_ffi_init(|ptr: *mut T::DriverType| {
165175
// SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write.
166-
unsafe { ptr.write(T::RegType::default()) };
176+
unsafe { ptr.write(T::DriverType::default()) };
167177

168178
// SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write, and it has
169179
// just been initialised above, so it's also valid for read.
170-
let drv = unsafe { &*(ptr as *const Opaque<T::RegType>) };
180+
let drv = unsafe { &*(ptr as *const Opaque<T::DriverType>) };
171181

172182
// SAFETY: `drv` is guaranteed to be pinned until `T::unregister`.
173183
unsafe { T::register(drv, name, module) }

rust/kernel/i2c.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,17 @@ macro_rules! i2c_device_table {
9292
/// An adapter for the registration of I2C drivers.
9393
pub struct Adapter<T: Driver>(T);
9494

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
96102
// a preceding call to `register` has been successful.
97103
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
98-
type RegType = bindings::i2c_driver;
99-
100104
unsafe fn register(
101-
idrv: &Opaque<Self::RegType>,
105+
idrv: &Opaque<Self::DriverType>,
102106
name: &'static CStr,
103107
module: &'static ThisModule,
104108
) -> Result {
@@ -133,12 +137,12 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
133137
(*idrv.get()).driver.acpi_match_table = acpi_table;
134138
}
135139

136-
// SAFETY: `idrv` is guaranteed to be a valid `RegType`.
140+
// SAFETY: `idrv` is guaranteed to be a valid `DriverType`.
137141
to_result(unsafe { bindings::i2c_register_driver(module.0, idrv.get()) })
138142
}
139143

140-
unsafe fn unregister(idrv: &Opaque<Self::RegType>) {
141-
// SAFETY: `idrv` is guaranteed to be a valid `RegType`.
144+
unsafe fn unregister(idrv: &Opaque<Self::DriverType>) {
145+
// SAFETY: `idrv` is guaranteed to be a valid `DriverType`.
142146
unsafe { bindings::i2c_del_driver(idrv.get()) }
143147
}
144148
}

rust/kernel/pci.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,17 @@ pub use self::irq::{
5050
/// An adapter for the registration of PCI drivers.
5151
pub struct Adapter<T: Driver>(T);
5252

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
5460
// a preceding call to `register` has been successful.
5561
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
56-
type RegType = bindings::pci_driver;
57-
5862
unsafe fn register(
59-
pdrv: &Opaque<Self::RegType>,
63+
pdrv: &Opaque<Self::DriverType>,
6064
name: &'static CStr,
6165
module: &'static ThisModule,
6266
) -> Result {
@@ -68,14 +72,14 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
6872
(*pdrv.get()).id_table = T::ID_TABLE.as_ptr();
6973
}
7074

71-
// SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
75+
// SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.
7276
to_result(unsafe {
7377
bindings::__pci_register_driver(pdrv.get(), module.0, name.as_char_ptr())
7478
})
7579
}
7680

77-
unsafe fn unregister(pdrv: &Opaque<Self::RegType>) {
78-
// SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
81+
unsafe fn unregister(pdrv: &Opaque<Self::DriverType>) {
82+
// SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.
7983
unsafe { bindings::pci_unregister_driver(pdrv.get()) }
8084
}
8185
}

rust/kernel/platform.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,17 @@ use core::{
2626
/// An adapter for the registration of platform drivers.
2727
pub struct Adapter<T: Driver>(T);
2828

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
3036
// a preceding call to `register` has been successful.
3137
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
32-
type RegType = bindings::platform_driver;
33-
3438
unsafe fn register(
35-
pdrv: &Opaque<Self::RegType>,
39+
pdrv: &Opaque<Self::DriverType>,
3640
name: &'static CStr,
3741
module: &'static ThisModule,
3842
) -> Result {
@@ -55,12 +59,12 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
5559
(*pdrv.get()).driver.acpi_match_table = acpi_table;
5660
}
5761

58-
// SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
62+
// SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.
5963
to_result(unsafe { bindings::__platform_driver_register(pdrv.get(), module.0) })
6064
}
6165

62-
unsafe fn unregister(pdrv: &Opaque<Self::RegType>) {
63-
// SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
66+
unsafe fn unregister(pdrv: &Opaque<Self::DriverType>) {
67+
// SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.
6468
unsafe { bindings::platform_driver_unregister(pdrv.get()) };
6569
}
6670
}

rust/kernel/usb.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,17 @@ use core::{
2727
/// An adapter for the registration of USB drivers.
2828
pub struct Adapter<T: Driver>(T);
2929

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
3137
// a preceding call to `register` has been successful.
3238
unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
33-
type RegType = bindings::usb_driver;
34-
3539
unsafe fn register(
36-
udrv: &Opaque<Self::RegType>,
40+
udrv: &Opaque<Self::DriverType>,
3741
name: &'static CStr,
3842
module: &'static ThisModule,
3943
) -> Result {
@@ -45,14 +49,14 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
4549
(*udrv.get()).id_table = T::ID_TABLE.as_ptr();
4650
}
4751

48-
// SAFETY: `udrv` is guaranteed to be a valid `RegType`.
52+
// SAFETY: `udrv` is guaranteed to be a valid `DriverType`.
4953
to_result(unsafe {
5054
bindings::usb_register_driver(udrv.get(), module.0, name.as_char_ptr())
5155
})
5256
}
5357

54-
unsafe fn unregister(udrv: &Opaque<Self::RegType>) {
55-
// SAFETY: `udrv` is guaranteed to be a valid `RegType`.
58+
unsafe fn unregister(udrv: &Opaque<Self::DriverType>) {
59+
// SAFETY: `udrv` is guaranteed to be a valid `DriverType`.
5660
unsafe { bindings::usb_deregister(udrv.get()) };
5761
}
5862
}

0 commit comments

Comments
 (0)