diff options
| author | Danilo Krummrich <dakr@kernel.org> | 2026-05-25 22:20:51 +0200 |
|---|---|---|
| committer | Danilo Krummrich <dakr@kernel.org> | 2026-05-27 16:22:41 +0200 |
| commit | 7fdffdda630ee61ae0e09ef8f1ace52bbf70e2b0 (patch) | |
| tree | 82bdea83290b72b76d053411b4f571a830172b30 /rust/kernel/i2c.rs | |
| parent | c8a43666bade4683640dc835f92cd456d29cee55 (diff) | |
rust: driver: decouple driver private data from driver type
Add a type Data<'bound> associated type to all bus driver traits,
decoupling the driver's bus device private data type from the driver
struct itself.
In the context of adding a 'bound lifetime, making this an associated
type has the advantage that it allows us to avoid a driver trait global
lifetime and it avoids the need for ForLt for bus device private data;
both of which make the subsequent implementation by buses much simpler.
All existing drivers and doc examples set type Data = Self to preserve
the current behavior.
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Reviewed-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://patch.msgid.link/20260525202921.124698-5-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Diffstat (limited to 'rust/kernel/i2c.rs')
| -rw-r--r-- | rust/kernel/i2c.rs | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index 4ccee4ba4f23..bfd081518615 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -93,12 +93,12 @@ pub struct Adapter<T: Driver>(T); // SAFETY: // - `bindings::i2c_driver` is a C type declared as `repr(C)`. -// - `T` is the type of the driver's device private data. +// - `T::Data` is the type of the driver's device private data. // - `struct i2c_driver` embeds a `struct device_driver`. // - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`. unsafe impl<T: Driver> driver::DriverLayout for Adapter<T> { type DriverType = bindings::i2c_driver; - type DriverData = T; + type DriverData<'bound> = T::Data; const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver); } @@ -176,8 +176,8 @@ impl<T: Driver> Adapter<T> { // SAFETY: `remove_callback` is only ever called after a successful call to // `probe_callback`, hence it's guaranteed that `I2cClient::set_drvdata()` has been called - // and stored a `Pin<KBox<T>>`. - let data = unsafe { idev.as_ref().drvdata_borrow::<T>() }; + // and stored a `Pin<KBox<T::Data>>`. + let data = unsafe { idev.as_ref().drvdata_borrow::<T::Data>() }; T::unbind(idev, data); } @@ -188,8 +188,8 @@ impl<T: Driver> Adapter<T> { // SAFETY: `shutdown_callback` is only ever called after a successful call to // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called - // and stored a `Pin<KBox<T>>`. - let data = unsafe { idev.as_ref().drvdata_borrow::<T>() }; + // and stored a `Pin<KBox<T::Data>>`. + let data = unsafe { idev.as_ref().drvdata_borrow::<T::Data>() }; T::shutdown(idev, data); } @@ -294,6 +294,7 @@ macro_rules! module_i2c_driver { /// /// impl i2c::Driver for MyDriver { /// type IdInfo = (); +/// type Data = Self; /// const I2C_ID_TABLE: Option<i2c::IdTable<Self::IdInfo>> = Some(&I2C_TABLE); /// const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE); /// const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE); @@ -301,15 +302,15 @@ macro_rules! module_i2c_driver { /// fn probe( /// _idev: &i2c::I2cClient<Core>, /// _id_info: Option<&Self::IdInfo>, -/// ) -> impl PinInit<Self, Error> { +/// ) -> impl PinInit<Self::Data, Error> { /// Err(ENODEV) /// } /// -/// fn shutdown(_idev: &i2c::I2cClient<Core>, this: Pin<&Self>) { +/// fn shutdown(_idev: &i2c::I2cClient<Core>, this: Pin<&Self::Data>) { /// } /// } ///``` -pub trait Driver: Send { +pub trait Driver { /// The type holding information about each device id supported by the driver. // TODO: Use `associated_type_defaults` once stabilized: // @@ -318,6 +319,9 @@ pub trait Driver: Send { // ``` type IdInfo: 'static; + /// The type of the driver's bus device private data. + type Data: Send; + /// The table of device ids supported by the driver. const I2C_ID_TABLE: Option<IdTable<Self::IdInfo>> = None; @@ -334,7 +338,7 @@ pub trait Driver: Send { fn probe( dev: &I2cClient<device::Core>, id_info: Option<&Self::IdInfo>, - ) -> impl PinInit<Self, Error>; + ) -> impl PinInit<Self::Data, Error>; /// I2C driver shutdown. /// @@ -346,8 +350,8 @@ pub trait Driver: Send { /// /// This callback is distinct from final resource cleanup, as the driver instance remains valid /// after it returns. Any deallocation or teardown of driver-owned resources should instead be - /// handled in `Self::drop`. - fn shutdown(dev: &I2cClient<device::Core>, this: Pin<&Self>) { + /// handled in `Drop`. + fn shutdown(dev: &I2cClient<device::Core>, this: Pin<&Self::Data>) { let _ = (dev, this); } @@ -360,8 +364,8 @@ pub trait Driver: Send { /// `&Device<Core>` or `&Device<Bound>` reference. For instance, drivers may try to perform I/O /// operations to gracefully tear down the device. /// - /// Otherwise, release operations for driver resources should be performed in `Self::drop`. - fn unbind(dev: &I2cClient<device::Core>, this: Pin<&Self>) { + /// Otherwise, release operations for driver resources should be performed in `Drop`. + fn unbind(dev: &I2cClient<device::Core>, this: Pin<&Self::Data>) { let _ = (dev, this); } } |
