diff options
Diffstat (limited to 'queue-6.15/rust-devres-implement-devres-access.patch')
-rw-r--r-- | queue-6.15/rust-devres-implement-devres-access.patch | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/queue-6.15/rust-devres-implement-devres-access.patch b/queue-6.15/rust-devres-implement-devres-access.patch new file mode 100644 index 0000000000..3dd47d42b3 --- /dev/null +++ b/queue-6.15/rust-devres-implement-devres-access.patch @@ -0,0 +1,93 @@ +From e9ec190d9683bcc4b1fe276c640b18cebd1bba45 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sashal@kernel.org> +Date: Mon, 28 Apr 2025 16:00:28 +0200 +Subject: rust: devres: implement Devres::access() + +From: Danilo Krummrich <dakr@kernel.org> + +[ Upstream commit f301cb978c068faa8fcd630be2cb317a2d0ec063 ] + +Implement a direct accessor for the data stored within the Devres for +cases where we can prove that we own a reference to a Device<Bound> +(i.e. a bound device) of the same device that was used to create the +corresponding Devres container. + +Usually, when accessing the data stored within a Devres container, it is +not clear whether the data has been revoked already due to the device +being unbound and, hence, we have to try whether the access is possible +and subsequently keep holding the RCU read lock for the duration of the +access. + +However, when we can prove that we hold a reference to Device<Bound> +matching the device the Devres container has been created with, we can +guarantee that the device is not unbound for the duration of the +lifetime of the Device<Bound> reference and, hence, it is not possible +for the data within the Devres container to be revoked. + +Therefore, in this case, we can bypass the atomic check and the RCU read +lock, which is a great optimization and simplification for drivers. + +Reviewed-by: Christian Schrefl <chrisi.schrefl@gmail.com> +Reviewed-by: Alexandre Courbot <acourbot@nvidia.com> +Acked-by: Boqun Feng <boqun.feng@gmail.com> +Reviewed-by: Joel Fernandes <joelagnelf@nvidia.com> +Link: https://lore.kernel.org/r/20250428140137.468709-3-dakr@kernel.org +Signed-off-by: Danilo Krummrich <dakr@kernel.org> +Stable-dep-of: 20c96ed278e3 ("rust: devres: do not dereference to the internal Revocable") +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + rust/kernel/devres.rs | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs +index f3a4e3383b8d2..acb8e1d13ddd9 100644 +--- a/rust/kernel/devres.rs ++++ b/rust/kernel/devres.rs +@@ -196,6 +196,44 @@ pub fn new_foreign_owned(dev: &Device, data: T, flags: Flags) -> Result { + + Ok(()) + } ++ ++ /// 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. ++ /// ++ /// # Example ++ /// ++ /// ```no_run ++ /// # use kernel::{device::Core, devres::Devres, pci}; ++ /// ++ /// 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(()) ++ /// } ++ /// ``` ++ pub fn access<'a>(&'a self, dev: &'a Device<Bound>) -> Result<&'a T> { ++ if self.0.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.deref().access() }) ++ } + } + + impl<T> Deref for Devres<T> { +-- +2.39.5 + |