summaryrefslogtreecommitdiff
path: root/rust/kernel/i2c.rs
diff options
context:
space:
mode:
authorDanilo Krummrich <dakr@kernel.org>2026-05-25 22:20:51 +0200
committerDanilo Krummrich <dakr@kernel.org>2026-05-27 16:22:41 +0200
commit7fdffdda630ee61ae0e09ef8f1ace52bbf70e2b0 (patch)
tree82bdea83290b72b76d053411b4f571a830172b30 /rust/kernel/i2c.rs
parentc8a43666bade4683640dc835f92cd456d29cee55 (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.rs32
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);
}
}