diff options
| author | Danilo Krummrich <dakr@kernel.org> | 2026-06-26 20:36:13 +0200 |
|---|---|---|
| committer | Danilo Krummrich <dakr@kernel.org> | 2026-07-11 19:45:40 +0200 |
| commit | e7e6bf5af80e7454ebb92a998a2ab931cb27204f (patch) | |
| tree | 9603ca32dc85da9b0c18c79cfe531c461217f91c /rust/kernel | |
| parent | b85f672a3e68ed16e8c7fa96ec1f090a173930ad (diff) | |
rust: pci: return DevresLt from Bar::into_devres()
Implement ForLt and CovariantForLt for Bar<'static, SIZE> so that
DevresLt can shorten the stored 'static lifetime back to the caller's
borrow lifetime.
CovariantForLt is sound because Bar<'a, SIZE> only holds &'a
Device<Bound>, which is covariant over 'a.
Since DevresLt::new() handles the lifetime transmutation internally,
into_devres() no longer needs an explicit transmute to Bar<'static>.
Add a DevresBar<SIZE> type alias for convenience.
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Link: https://patch.msgid.link/20260626183630.2585057-7-dakr@kernel.org
[ Add default SIZE parameter to DevresBar. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Diffstat (limited to 'rust/kernel')
| -rw-r--r-- | rust/kernel/pci.rs | 1 | ||||
| -rw-r--r-- | rust/kernel/pci/io.rs | 37 |
2 files changed, 27 insertions, 11 deletions
diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 5071cae6543f..f783b9d9fa26 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -45,6 +45,7 @@ pub use self::io::{ ConfigSpace, ConfigSpaceKind, ConfigSpaceSize, + DevresBar, Extended, Normal, // }; diff --git a/rust/kernel/pci/io.rs b/rust/kernel/pci/io.rs index 0461e01aaa20..6ebfbf368cd3 100644 --- a/rust/kernel/pci/io.rs +++ b/rust/kernel/pci/io.rs @@ -6,7 +6,7 @@ use super::Device; use crate::{ bindings, device, - devres::Devres, + devres::DevresLt, io::{ Io, IoCapable, @@ -14,7 +14,11 @@ use crate::{ Mmio, MmioRaw, // }, - prelude::*, // + prelude::*, + types::{ + CovariantForLt, + ForLt, // + }, // }; use core::{ marker::PhantomData, @@ -151,6 +155,19 @@ pub struct Bar<'a, const SIZE: usize = 0> { num: i32, } +impl<const SIZE: usize> ForLt for Bar<'static, SIZE> { + type Of<'a> = Bar<'a, SIZE>; +} + +// SAFETY: `Bar<'a, SIZE>` is covariant over `'a`; it holds `&'a Device<Bound>`, +// which is covariant. +unsafe impl<const SIZE: usize> CovariantForLt for Bar<'static, SIZE> {} + +/// A device-managed PCI BAR mapping. +/// +/// See [`Bar::into_devres`]. +pub type DevresBar<const SIZE: usize = 0> = DevresLt<Bar<'static, SIZE>>; + impl<'a, const SIZE: usize> Bar<'a, SIZE> { pub(super) fn new( pdev: &'a Device<device::Bound>, @@ -223,15 +240,13 @@ impl<'a, const SIZE: usize> Bar<'a, SIZE> { /// Consume the `Bar` and register it as a device-managed resource. /// - /// The returned `Devres<Bar<'static, SIZE>>` can outlive the original lifetime `'a`. Access - /// to the BAR is revoked when the device is unbound. - pub fn into_devres(self) -> Result<Devres<Bar<'static, SIZE>>> { - // SAFETY: Casting to `'static` is sound because `Devres` guarantees the `Bar` does not - // actually outlive the device -- access is revoked and the resource is released when the - // device is unbound. - let bar: Bar<'static, SIZE> = unsafe { core::mem::transmute(self) }; - let pdev = bar.pdev; - Devres::new(pdev.as_ref(), bar) + /// The returned [`DevresBar`] can outlive the original borrow and be stored in driver data. + /// Access to the BAR is revoked automatically when the device is unbound. + pub fn into_devres(self) -> Result<DevresBar<SIZE>> { + let pdev = self.pdev; + // SAFETY: `Bar` only holds a reference to the device and an I/O mapping, both of which + // remain valid for the device's full bound scope, not just for `'a`. + unsafe { DevresLt::new(pdev.as_ref(), self) } } } |
