pub struct Devres<T: Send> { /* private fields */ }
Expand description
This abstraction is meant to be used by subsystems to containerize Device
bound resources to
manage their lifetime.
Device
bound resources should be freed when either the resource goes out of scope or the
Device
is unbound respectively, depending on what happens first. In any case, it is always
guaranteed that revoking the device resource is completed before the corresponding Device
is unbound.
To achieve that Devres
registers a devres callback on creation, which is called once the
Device
is unbound, revoking access to the encapsulated resource (see also Revocable
).
After the Devres
has been unbound it is not possible to access the encapsulated resource
anymore.
Devres
users should make sure to simply free the corresponding backing resource in T
’s
Drop
implementation.
§Examples
// See also [`pci::Bar`] for a real example.
struct IoMem<const SIZE: usize>(IoRaw<SIZE>);
impl<const SIZE: usize> IoMem<SIZE> {
/// # Safety
///
/// [`paddr`, `paddr` + `SIZE`) must be a valid MMIO region that is mappable into the CPUs
/// virtual address space.
unsafe fn new(paddr: usize) -> Result<Self>{
// SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is
// valid for `ioremap`.
let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) };
if addr.is_null() {
return Err(ENOMEM);
}
Ok(IoMem(IoRaw::new(addr as usize, SIZE)?))
}
}
impl<const SIZE: usize> Drop for IoMem<SIZE> {
fn drop(&mut self) {
// SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.
unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };
}
}
impl<const SIZE: usize> Deref for IoMem<SIZE> {
type Target = Io<SIZE>;
fn deref(&self) -> &Self::Target {
// SAFETY: The memory range stored in `self` has been properly mapped in `Self::new`.
unsafe { Io::from_raw(&self.0) }
}
}
// SAFETY: Invalid usage for example purposes.
let iomem = unsafe { IoMem::<{ core::mem::size_of::<u32>() }>::new(0xBAAAAAAD)? };
let devres = KBox::pin_init(Devres::new(dev, iomem), GFP_KERNEL)?;
let res = devres.try_access().ok_or(ENXIO)?;
res.write8(0x42, 0x0);
§Invariants
Self::inner
is guaranteed to be initialized and is always accessed read-only.
Implementations§
Source§impl<T: Send> Devres<T>
impl<T: Send> Devres<T>
Sourcepub fn new<'a, E>(
dev: &'a Device<Bound>,
data: impl PinInit<T, E> + 'a,
) -> impl PinInit<Self, Error> + 'a
pub fn new<'a, E>( dev: &'a Device<Bound>, data: impl PinInit<T, E> + 'a, ) -> impl PinInit<Self, Error> + 'a
Sourcepub fn access<'a>(&'a self, dev: &'a Device<Bound>) -> Result<&'a T>
pub fn access<'a>(&'a self, dev: &'a Device<Bound>) -> Result<&'a T>
Obtain &'a T
, bypassing the Revocable
.
This method allows to directly obtain a &'a T
, bypassing the Revocable
, by presenting
a &'a Device<Bound>
of the same Device
this Devres
instance has been created with.
§Errors
An error is returned if dev
does not match the same Device
this Devres
instance
has been created with.
§Examples
fn from_core(dev: &pci::Device<Core>, devres: Devres<pci::Bar<0x4>>) -> Result {
let bar = devres.access(dev.as_ref())?;
let _ = bar.read32(0x0);
// might_sleep()
bar.write32(0x42, 0x0);
Ok(())
}
Sourcepub fn try_access(&self) -> Option<RevocableGuard<'_, T>>
pub fn try_access(&self) -> Option<RevocableGuard<'_, T>>
Devres
accessor for Revocable::try_access
.
Sourcepub fn try_access_with<R, F: FnOnce(&T) -> R>(&self, f: F) -> Option<R>
pub fn try_access_with<R, F: FnOnce(&T) -> R>(&self, f: F) -> Option<R>
Devres
accessor for Revocable::try_access_with
.
Sourcepub fn try_access_with_guard<'a>(&'a self, guard: &'a Guard) -> Option<&'a T>
pub fn try_access_with_guard<'a>(&'a self, guard: &'a Guard) -> Option<&'a T>
Devres
accessor for Revocable::try_access_with_guard
.
Trait Implementations§
Source§impl<T: Send> PinnedDrop for Devres<T>
impl<T: Send> PinnedDrop for Devres<T>
impl<T: Send> Send for Devres<T>
impl<T: Send + Sync> Sync for Devres<T>
Auto Trait Implementations§
impl<T> !Freeze for Devres<T>
impl<T> !RefUnwindSafe for Devres<T>
impl<T> !UnwindSafe for Devres<T>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> PinInit<T> for T
impl<T> PinInit<T> for T
Source§unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible>
unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible>
slot
. Read more