On 06.05.2026 23:50, Danilo Krummrich wrote:
> Currently, Rust device drivers access device resources such as PCI BAR mappings
> and I/O memory regions through Devres<T>.
>
> Devres::access() provides zero-overhead access by taking a &Device<Bound>
> reference as proof that the device is still bound. Since a &Device<Bound> is
> available in almost all contexts by design, Devres is mostly a type-system level
> proof that the resource is valid, but it can also be used from scopes without
> this guarantee through its try_access() accessor.
>
> This works well in general, but has a few limitations:
>
> - Every access to a device resource goes through Devres::access(), which
> despite zero cost, adds boilerplate to every access site.
>
> - Destructors do not receive a &Device<Bound>, so they must use try_access(),
> which can fail. In practice the access succeeds if teardown ordering is
> correct, but the type system can't express this, forcing drivers to handle a
> failure path that should never be taken.
>
> - Sharing a resource across components (e.g. passing a BAR to a sub-component)
> requires Arc<Devres<T>>.
>
> - Device references must be stored as ARef<Device> rather than plain &Device
> borrows.
>
> These limitations stem from the driver's bus device private data being 'static
> -- the driver struct cannot borrow from the device reference it receives in
> probe(), even though it structurally cannot outlive the device binding.
>
> This series introduces Higher-Ranked Lifetime Types (HRT) for Rust device
> drivers. An HRT is a type that is generic over a lifetime -- it does not have a
> fixed lifetime, but can be instantiated with any lifetime chosen by the caller.
>
> Rust does not directly support types that are generic over a lifetime as type
> parameters; the ForLt trait (contributed by Gary Guo) encodes this internally.
>
> The module_*_driver! macros handle the wrapping, so driver authors just write
> struct MyDriver<'a> and impl Driver<'a>.
>
> With HRT, driver structs carry a lifetime parameter tied to the device binding
> scope -- the interval of a bus device being bound to a driver. Device resources
> like pci::Bar<'a> and IoMem<'a> are handed out with this lifetime, so the
> compiler enforces at build time that they do not escape the binding scope.
>
> Before:
>
> struct MyDriver {
> pdev: ARef<pci::Device>,
> bar: Devres<pci::Bar<BAR_SIZE>>,
> }
>
> let io = self.bar.access(dev)?;
> io.read32(OFFSET);
>
> After:
>
> struct MyDriver<'a> {
> pdev: &'a pci::Device,
> bar: pci::Bar<'a, BAR_SIZE>,
> }
>
> self.bar.read32(OFFSET);
>
> Lifetime-parameterized device resources can be put into a Devres at any point
> via Bar::into_devres() / IoMem::into_devres(), providing the exact same
> semantics as before. This is useful for resources shared across subsystem
> boundaries where revocation is needed.
>
> This also synergizes with the upcoming self-referential initialization support
> in pin-init, which allows one field of the driver struct to borrow another
> during initialization without unsafe code.
>
> The same pattern is applied to auxiliary device registration data as a first
> example beyond bus device private data. Registration<F: ForLt> can hold
> lifetime-parameterized data tied to the parent driver's binding scope. Since the
> auxiliary bus guarantees that the parent remains bound while the auxiliary
> device is registered, the registration data can safely borrow the parent's
> device resources.
>
> More generally, binding resource lifetimes to a registration scope applies to
> every registration that is scoped to a driver binding -- auxiliary devices,
> class devices, IRQ handlers, workqueues.
>
> A follow-up series extends this to class device registrations, starting with
> DRM, so that class device callbacks (IOCTLs, etc.) can safely access device
> resources through the separate registration data bound to the registration's
> lifetime without Devres indirection.
>
> The series contains a few driver patches for reference, indicated by the REF
> suffix.
>
> Thanks to Gary for coming up with the ForLt implementation; thanks to Alice for
> the early discussions around lifetime-parameterized private data that helped
> shape the direction of this work.
>
> This series depends on [1].
>
> [1] https://lore.kernel.org/driver-core/20260505152400.3905096-1-dakr@kernel.org/
I have applied this series together with [1] on top of 7.1.0-rc1. I made
some adaptions to local changes (e.g. my ARM64 TMU interrupt test) and
boot tested it. Several parts this patch series touches (e.g. PCI,
auxiliary, gpu) I might not use or even don't have it enabled. So I
don't know if this is worth mentioning
Tested-by: Dirk Behme <dirk.behme@de.bosch.com>
Please feel free to ignore this, then.
Thanks
Dirk
> Changes in v2:
> - Add 'a bound to ForLt::Of<'a> and WithLt::Of, making the lifetime bound
> inherent to the trait; remove all F::Of<'static>: 'static where clauses
> - Drop "rust: devres: add ForLt support to Devres"; Devres itself stays
> unchanged -- ForLt-aware access is introduced later through DevresLt in a
> separate series
> - Use 'bound instead of 'a; add patches to consistently use 'bound for
> pre-existing 'a
>
> Danilo Krummrich (24):
> rust: driver core: drop drvdata before devres release
> rust: device: generalize drvdata methods over ForLt
> rust: driver: make Adapter trait lifetime-parameterized
> rust: pci: implement Sync for Device<Bound>
> rust: platform: implement Sync for Device<Bound>
> rust: auxiliary: implement Sync for Device<Bound>
> rust: usb: implement Sync for Device<Bound>
> rust: device: implement Sync for Device<Bound>
> rust: pci: make Driver trait lifetime-parameterized
> rust: platform: make Driver trait lifetime-parameterized
> rust: auxiliary: make Driver trait lifetime-parameterized
> rust: auxiliary: generalize Registration over ForLt
> samples: rust: rust_driver_auxiliary: showcase lifetime-bound
> registration data
> rust: usb: make Driver trait lifetime-parameterized
> rust: i2c: make Driver trait lifetime-parameterized
> rust: pci: make Bar lifetime-parameterized
> rust: io: make IoMem and ExclusiveIoMem lifetime-parameterized
> samples: rust: rust_driver_pci: use HRT lifetime for Bar
> rust: driver-core: rename 'a lifetime to 'bound
> gpu: nova-core: rename 'a lifetime to 'bound
> gpu: nova-core: use HRT lifetime for Bar
> gpu: nova-core: unregister sysmem flush page from Drop
> gpu: nova-core: replace ARef<Device> with &'bound Device in
> SysmemFlush
> gpu: drm: tyr: use HRT lifetime for IoMem
>
> Gary Guo (1):
> rust: types: add `ForLt` trait for higher-ranked lifetime support
>
> drivers/base/dd.c | 2 +-
> drivers/cpufreq/rcpufreq_dt.rs | 10 +-
> drivers/gpu/drm/nova/driver.rs | 9 +-
> drivers/gpu/drm/tyr/driver.rs | 24 ++-
> drivers/gpu/drm/tyr/gpu.rs | 62 +++---
> drivers/gpu/drm/tyr/regs.rs | 21 +-
> drivers/gpu/nova-core/driver.rs | 48 ++---
> drivers/gpu/nova-core/fb.rs | 31 ++-
> drivers/gpu/nova-core/firmware/gsp.rs | 8 +-
> drivers/gpu/nova-core/gpu.rs | 38 ++--
> drivers/gpu/nova-core/gsp/commands.rs | 10 +-
> drivers/gpu/nova-core/gsp/fw/commands.rs | 4 +-
> drivers/gpu/nova-core/nova_core.rs | 4 +-
> drivers/pwm/pwm_th1520.rs | 14 +-
> include/linux/device/driver.h | 4 +-
> rust/Makefile | 1 +
> rust/kernel/auxiliary.rs | 132 +++++++++----
> rust/kernel/cpufreq.rs | 8 +-
> rust/kernel/device.rs | 79 +++++---
> rust/kernel/devres.rs | 16 +-
> rust/kernel/driver.rs | 44 +++--
> rust/kernel/i2c.rs | 130 +++++++-----
> rust/kernel/io/mem.rs | 131 ++++++------
> rust/kernel/pci.rs | 89 ++++++---
> rust/kernel/pci/io.rs | 68 ++++---
> rust/kernel/pci/irq.rs | 38 ++--
> rust/kernel/platform.rs | 120 +++++++----
> rust/kernel/types.rs | 4 +
> rust/kernel/types/for_lt.rs | 117 +++++++++++
> rust/kernel/usb.rs | 94 +++++----
> rust/macros/for_lt.rs | 242 +++++++++++++++++++++++
> rust/macros/lib.rs | 12 ++
> samples/rust/rust_debugfs.rs | 10 +-
> samples/rust/rust_dma.rs | 9 +-
> samples/rust/rust_driver_auxiliary.rs | 53 +++--
> samples/rust/rust_driver_i2c.rs | 18 +-
> samples/rust/rust_driver_pci.rs | 93 ++++-----
> samples/rust/rust_driver_platform.rs | 12 +-
> samples/rust/rust_driver_usb.rs | 14 +-
> samples/rust/rust_i2c_client.rs | 12 +-
> samples/rust/rust_soc.rs | 12 +-
> 41 files changed, 1220 insertions(+), 627 deletions(-)
> create mode 100644 rust/kernel/types/for_lt.rs
> create mode 100644 rust/macros/for_lt.rs
>