Re: [PATCH v5 5/9] rust: pci: drop driver data before remove returns

From: Alexandre Courbot

Date: Mon Nov 09 2026 - 06:58:21 EST


On Sat Oct 31, 2026 at 2:12 AM JST, Simon Song wrote:
> From: Zhi Wang <zhiw@xxxxxxxxxx>
>
> Drop PCI private data before the remove callback returns, so its
> destructors run within PCI core's removal context.
>
> Call unbind while private data remains installed, then take and release
> the data. Taking it clears drvdata, so post_unbind does not release it
> again. All borrows must end before the data is removed.
>
> Suggested-by: Danilo Krummrich <dakr@xxxxxxxxxx>
> Signed-off-by: Zhi Wang <zhiw@xxxxxxxxxx>
> Signed-off-by: Simon Song <xinmengs@xxxxxxxxxx>
> ---
> rust/kernel/device.rs | 4 ++--
> rust/kernel/pci.rs | 6 ++++++
> 2 files changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
> index 2291d85b684..1f6bb58396e 100644
> --- a/rust/kernel/device.rs
> +++ b/rust/kernel/device.rs
> @@ -243,8 +243,8 @@ impl<Ctx: InternalBoundContext> Device<Ctx> {
> ///
> /// # Safety
> ///
> - /// - Must only be called after a preceding call to [`Device::set_drvdata`] and before the
> - /// device is fully unbound.
> + /// - The data stored by [`Device::set_drvdata`] must still be installed and remain valid
> + /// for the returned borrow.
> /// - The type `T` must match the type of the `ForeignOwnable` previously stored by
> /// [`Device::set_drvdata`].
> pub unsafe fn drvdata_borrow<T>(&self) -> Pin<&T> {
> diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
> index 9e1d02588af..8092f56ee2b 100644
> --- a/rust/kernel/pci.rs
> +++ b/rust/kernel/pci.rs
> @@ -150,6 +150,12 @@ extern "C" fn remove_callback(pdev: *mut bindings::pci_dev) {
> let data = unsafe { pdev.as_ref().drvdata_borrow::<T::Data<'_>>() };
>
> T::unbind(pdev, data);
> +
> + // SAFETY: The driver's unbind callback has returned, and no callbacks retain a borrow.
> + let data = unsafe { pdev.as_ref().drvdata_obtain::<T::Data<'_>>() };
> +
> + // Drop private data before returning to PCI core, while its removal context is valid.
> + drop(data);

So this is basically doing the job of
`driver::Registration::post_unbind_callback` a bit ahead-of-schedule
because some of the PCI capabilities need to be released before the
device is fully unbound. A short comment stating so would make the code
easier to understand imho.