On Thu Jun 26, 2025 at 10:00 PM CEST, Danilo Krummrich wrote: > diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs > index 60b86f370284..47653c14838b 100644 > --- a/drivers/gpu/nova-core/gpu.rs > +++ b/drivers/gpu/nova-core/gpu.rs > @@ -161,14 +161,14 @@ fn new(bar: &Bar0) -> Result<Spec> { > pub(crate) struct Gpu { > spec: Spec, > /// MMIO mapping of PCI BAR 0 > - bar: Devres<Bar0>, > + bar: Arc<Devres<Bar0>>, Can't you store it inline, given that you return an `impl PinInit<Self>` below? > fw: Firmware, > } > > impl Gpu { > pub(crate) fn new( > pdev: &pci::Device<device::Bound>, > - devres_bar: Devres<Bar0>, > + devres_bar: Arc<Devres<Bar0>>, > ) -> Result<impl PinInit<Self>> { While I see this code, is it really necessary to return `Result` wrapping the initializer here? I think it's probably better to return `impl PinInit<Self, Error>` instead. (of course in a different patch/an issue) > let bar = devres_bar.access(pdev.as_ref())?; > let spec = Spec::new(bar)?; > @@ -44,6 +49,10 @@ struct DevresInner<T: Send> { > /// [`Devres`] users should make sure to simply free the corresponding backing resource in `T`'s > /// [`Drop`] implementation. > /// > +/// # Invariants > +/// > +/// [`Self::inner`] is guaranteed to be initialized and is always accessed read-only. > +/// Let's put this section below the examples, I really ought to write the safety docs one day and let everyone vote on this kind of stuff... > /// # Example > /// > /// ```no_run > @@ -213,44 +233,63 @@ pub fn new(dev: &Device<Bound>, data: T, flags: Flags) -> Result<Self> { > /// } > /// ``` > pub fn access<'a>(&'a self, dev: &'a Device<Bound>) -> Result<&'a T> { > - if self.0.dev.as_raw() != dev.as_raw() { > + if self.dev.as_raw() != dev.as_raw() { > return Err(EINVAL); > } > > // SAFETY: `dev` being the same device as the device this `Devres` has been created for > - // proves that `self.0.data` hasn't been revoked and is guaranteed to not be revoked as > - // long as `dev` lives; `dev` lives at least as long as `self`. > - Ok(unsafe { self.0.data.access() }) > + // proves that `self.data` hasn't been revoked and is guaranteed to not be revoked as long > + // as `dev` lives; `dev` lives at least as long as `self`. What if the device has been unbound and a new device has been allocated in the exact same memory? --- Cheers, Benno > + Ok(unsafe { self.data().access() }) > }