On Thu, 2026-11-12 at 01:52 +0100, Danilo Krummrich wrote: > The driver model uses native Rust lifetimes to let driver data retain > device resources and a Device reference for the duration of the > binding. Both remain accessible from the destructor, so a separate > unbind() callback is no longer needed. > > Remove serdev::Driver::unbind() and the adapter's remove callback and > document that device teardown belongs in Drop or PinnedDrop. > > Signed-off-by: Danilo Krummrich > --- > rust/kernel/serdev.rs | 41 ++++------------------------------------- > 1 file changed, 4 insertions(+), 37 deletions(-) > > diff --git a/rust/kernel/serdev.rs b/rust/kernel/serdev.rs > index 17ca504b7f8d..fd998b68b74f 100644 > --- a/rust/kernel/serdev.rs > +++ b/rust/kernel/serdev.rs > @@ -81,7 +81,6 @@ unsafe fn register( > unsafe { > (*sdrv.get()).driver.name = name.as_char_ptr(); > (*sdrv.get()).probe = Some(Self::probe_callback); > - (*sdrv.get()).remove = Some(Self::remove_callback); > (*sdrv.get()).driver.of_match_table = of_table; > (*sdrv.get()).driver.acpi_match_table = acpi_table; > } > @@ -210,29 +209,6 @@ extern "C" fn probe_callback(sdev: *mut bindings::serdev_device) -> kernel::ffi: > }) > } > > - extern "C" fn remove_callback(sdev: *mut bindings::serdev_device) { > - // SAFETY: The serial device bus only ever calls the remove callback with a valid pointer > - // to a `struct serdev_device`. > - // > - // INVARIANT: `sdev` is valid for the duration of `remove_callback()`. > - let sdev = unsafe { &*sdev.cast::>>() }; > - > - // SAFETY: `remove_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>>`. > - let private_data = unsafe { sdev.as_ref().drvdata_borrow::>() }; > - > - // SAFETY: No one has exclusive access to `private_data.driver`. > - let data = unsafe { &*private_data.driver.get() }; > - // SAFETY: > - // - `private_data.driver` is pinned. > - // - `remove_callback` is only ever called after a successful call to `probe_callback`, > - // hence it's guaranteed that `private_data.driver` was initialized. > - let data_pinned = unsafe { Pin::new_unchecked(data.assume_init_ref()) }; > - > - T::unbind(sdev, data_pinned); > - } > - > extern "C" fn receive_buf_callback( > sdev: *mut bindings::serdev_device, > buf: *const u8, > @@ -365,6 +341,10 @@ pub trait Driver { > type IdInfo: 'static; > > /// The type of the driver's bus device private data. > + /// > + /// Device teardown should be performed in [`Drop`] or [`PinnedDrop`](pin_init::PinnedDrop) > + /// for this type. The `'bound` lifetime allows the data to retain device resources and a > + /// [`Device`] reference for use during teardown. > type Data<'bound>: Send + Sync + 'bound; > > /// The table of OF device ids supported by the driver. > @@ -382,19 +362,6 @@ fn probe<'bound>( > id_info: Option<&'bound Self::IdInfo>, > ) -> impl PinInit, Error> + 'bound; > > - /// Serial device bus device driver unbind. > - /// > - /// Called when a [`Device`] is unbound from its bound [`Driver`]. Implementing this callback > - /// is optional. > - /// > - /// This callback serves as a place for drivers to perform teardown operations that require a > - /// `&Device` or `&Device` reference. For instance. > - /// > - /// Otherwise, release operations for driver resources should be performed in `Drop`. > - fn unbind<'bound>(sdev: &'bound Device>, this: Pin<&Self::Data<'bound>>) { > - let _ = (sdev, this); > - } > - > /// Serial device bus device data receive callback. > /// > /// Called when data got received from device. Reviewed-by: Markus Probst Thanks - Markus Probst