pub struct Devres<T>(/* 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.
§Example
// 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 _, SIZE as _) };
if addr.is_null() {
return Err(ENOMEM);
}
Ok(IoMem(IoRaw::new(addr as _, 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 _); };
}
}
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 = Devres::new(&dev, iomem, GFP_KERNEL)?;
let res = devres.try_access().ok_or(ENXIO)?;
res.write8(0x42, 0x0);Implementations§
Source§impl<T> Devres<T>
impl<T> Devres<T>
Sourcepub fn new(dev: &Device, data: T, flags: Flags) -> Result<Self>
pub fn new(dev: &Device, data: T, flags: Flags) -> Result<Self>
Creates a new Devres instance of the given data. The data encapsulated within the
returned Devres instance’ data will be revoked once the device is detached.
Sourcepub fn new_foreign_owned(dev: &Device, data: T, flags: Flags) -> Result
pub fn new_foreign_owned(dev: &Device, data: T, flags: Flags) -> Result
Same as Devres::new, but does not return a Devres instance. Instead the given data
is owned by devres and will be revoked / dropped, once the device is detached.
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_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.