From fd3b87ff0232f46e1ad53a48609a3853c8757c6c Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Tue, 5 May 2026 17:23:08 +0200 Subject: rust: auxiliary: add registration data to auxiliary devices Add a registration_data pointer to struct auxiliary_device, allowing the registering (parent) driver to attach private data to the device at registration time and retrieve it later when called back by the auxiliary (child) driver. By tying the data to the device's registration, Rust drivers can bind the lifetime of device resources to it, since the auxiliary bus guarantees that the parent driver remains bound while the auxiliary device is bound. On the Rust side, Registration takes ownership of the data via ForeignOwnable. A TypeId is stored alongside the data for runtime type checking, making Device::registration_data() a safe method. Reviewed-by: Alice Ryhl Link: https://patch.msgid.link/20260505152400.3905096-3-dakr@kernel.org Signed-off-by: Danilo Krummrich --- include/linux/auxiliary_bus.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux') diff --git a/include/linux/auxiliary_bus.h b/include/linux/auxiliary_bus.h index bc09b55e3682..4e1ad8ccbcdd 100644 --- a/include/linux/auxiliary_bus.h +++ b/include/linux/auxiliary_bus.h @@ -62,6 +62,9 @@ * @sysfs.irqs: irqs xarray contains irq indices which are used by the device, * @sysfs.lock: Synchronize irq sysfs creation, * @sysfs.irq_dir_exists: whether "irqs" directory exists, + * @registration_data_rust: private data owned by the registering (parent) + * driver; valid for as long as the device is + * registered with the driver core, * * An auxiliary_device represents a part of its parent device's functionality. * It is given a name that, combined with the registering drivers @@ -148,6 +151,7 @@ struct auxiliary_device { struct mutex lock; /* Synchronize irq sysfs creation */ bool irq_dir_exists; } sysfs; + void *registration_data_rust; }; /** -- cgit v1.2.3 From be31fcf5af751815457102575b816a2bd31b4562 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Mon, 25 May 2026 22:20:52 +0200 Subject: rust: driver core: drop drvdata before devres release Move the post_unbind_rust callback before devres_release_all() in device_unbind_cleanup(). With drvdata() removed, the driver's bus device private data is only accessible by the owning driver itself. It is hence safe to drop the driver's bus device private data before devres actions are released. This reordering is the key enabler for Higher-Ranked Lifetime Types (HRT) in Rust device drivers -- it allows driver structs to hold direct references to devres-managed resources, because the bus device private data (and with it all such references) is guaranteed to be dropped while the underlying devres resources are still alive. Without this change, devres resources would be freed first, leaving the driver's bus device private data with dangling references during its destructor. Reviewed-by: Alexandre Courbot Reviewed-by: Gary Guo Reviewed-by: Greg Kroah-Hartman Link: https://patch.msgid.link/20260525202921.124698-6-dakr@kernel.org Signed-off-by: Danilo Krummrich --- drivers/base/dd.c | 2 +- include/linux/device/driver.h | 4 ++-- rust/kernel/driver.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 1dc1e3528043..73801b40a416 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -595,9 +595,9 @@ static DEVICE_ATTR_RW(state_synced); static void device_unbind_cleanup(struct device *dev) { - devres_release_all(dev); if (dev->driver->p_cb.post_unbind_rust) dev->driver->p_cb.post_unbind_rust(dev); + devres_release_all(dev); arch_teardown_dma_ops(dev); kfree(dev->dma_range_map); dev->dma_range_map = NULL; diff --git a/include/linux/device/driver.h b/include/linux/device/driver.h index bbc67ec513ed..38e9a4679447 100644 --- a/include/linux/device/driver.h +++ b/include/linux/device/driver.h @@ -123,8 +123,8 @@ struct device_driver { struct driver_private *p; struct { /* - * Called after remove() and after all devres entries have been - * processed. This is a Rust only callback. + * Called after remove() but before devres entries are released. + * This is a Rust only callback. */ void (*post_unbind_rust)(struct device *dev); } p_cb; diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs index 5fd1cfd64e93..a95dafaa9d68 100644 --- a/rust/kernel/driver.rs +++ b/rust/kernel/driver.rs @@ -193,8 +193,8 @@ impl Registration { // INVARIANT: `dev` is valid for the duration of the `post_unbind_callback()`. let dev = unsafe { &*dev.cast::>() }; - // `remove()` and all devres callbacks have been completed at this point, hence drop the - // driver's device private data. + // `remove()` has been completed at this point; devres resources are still valid and will + // be released after the driver's bus device private data is dropped. // // SAFETY: By the safety requirements of the `Driver` trait, `T::DriverData` is the // driver's bus device private data type. -- cgit v1.2.3