mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 07:03:28 -04:00
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>
This commit is contained in:
@@ -45,6 +45,7 @@
|
||||
ConfigSpace,
|
||||
ConfigSpaceKind,
|
||||
ConfigSpaceSize,
|
||||
DevresBar,
|
||||
Extended,
|
||||
Normal, //
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
use crate::{
|
||||
bindings,
|
||||
device,
|
||||
devres::Devres,
|
||||
devres::DevresLt,
|
||||
io::{
|
||||
Io,
|
||||
IoCapable,
|
||||
@@ -14,7 +14,11 @@
|
||||
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 @@ fn release(&self) {
|
||||
|
||||
/// 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) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user