summaryrefslogtreecommitdiff
path: root/rust/kernel
diff options
context:
space:
mode:
authorDanilo Krummrich <dakr@kernel.org>2026-06-26 20:36:13 +0200
committerDanilo Krummrich <dakr@kernel.org>2026-07-11 19:45:40 +0200
commite7e6bf5af80e7454ebb92a998a2ab931cb27204f (patch)
tree9603ca32dc85da9b0c18c79cfe531c461217f91c /rust/kernel
parentb85f672a3e68ed16e8c7fa96ec1f090a173930ad (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.rs1
-rw-r--r--rust/kernel/pci/io.rs37
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) }
}
}