diff options
Diffstat (limited to 'queue-6.15/rust-completion-implement-initial-abstraction.patch')
-rw-r--r-- | queue-6.15/rust-completion-implement-initial-abstraction.patch | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/queue-6.15/rust-completion-implement-initial-abstraction.patch b/queue-6.15/rust-completion-implement-initial-abstraction.patch new file mode 100644 index 0000000000..4fb2ee391a --- /dev/null +++ b/queue-6.15/rust-completion-implement-initial-abstraction.patch @@ -0,0 +1,206 @@ +From 1b56e765bf8990f1f60e124926c11fc4ac63d752 Mon Sep 17 00:00:00 2001 +From: Danilo Krummrich <dakr@kernel.org> +Date: Thu, 12 Jun 2025 14:17:13 +0200 +Subject: rust: completion: implement initial abstraction + +From: Danilo Krummrich <dakr@kernel.org> + +commit 1b56e765bf8990f1f60e124926c11fc4ac63d752 upstream. + +Implement a minimal abstraction for the completion synchronization +primitive. + +This initial abstraction only adds complete_all() and +wait_for_completion(), since that is what is required for the subsequent +Devres patch. + +Cc: Ingo Molnar <mingo@redhat.com> +Cc: Peter Zijlstra <peterz@infradead.org> +Cc: Juri Lelli <juri.lelli@redhat.com> +Cc: Vincent Guittot <vincent.guittot@linaro.org> +Cc: Dietmar Eggemann <dietmar.eggemann@arm.com> +Cc: Steven Rostedt <rostedt@goodmis.org> +Cc: Ben Segall <bsegall@google.com> +Cc: Mel Gorman <mgorman@suse.de> +Cc: Valentin Schneider <vschneid@redhat.com> +Reviewed-by: Alice Ryhl <aliceryhl@google.com> +Reviewed-by: Boqun Feng <boqun.feng@gmail.com> +Reviewed-by: Benno Lossin <lossin@kernel.org> +Acked-by: Miguel Ojeda <ojeda@kernel.org> +Link: https://lore.kernel.org/r/20250612121817.1621-2-dakr@kernel.org +Signed-off-by: Danilo Krummrich <dakr@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + rust/bindings/bindings_helper.h | 1 + rust/helpers/completion.c | 8 ++ + rust/helpers/helpers.c | 1 + rust/kernel/sync.rs | 2 + rust/kernel/sync/completion.rs | 112 ++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 124 insertions(+) + create mode 100644 rust/helpers/completion.c + create mode 100644 rust/kernel/sync/completion.rs + +--- a/rust/bindings/bindings_helper.h ++++ b/rust/bindings/bindings_helper.h +@@ -10,6 +10,7 @@ + #include <linux/blk-mq.h> + #include <linux/blk_types.h> + #include <linux/blkdev.h> ++#include <linux/completion.h> + #include <linux/cpumask.h> + #include <linux/cred.h> + #include <linux/device/faux.h> +--- /dev/null ++++ b/rust/helpers/completion.c +@@ -0,0 +1,8 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include <linux/completion.h> ++ ++void rust_helper_init_completion(struct completion *x) ++{ ++ init_completion(x); ++} +--- a/rust/helpers/helpers.c ++++ b/rust/helpers/helpers.c +@@ -11,6 +11,7 @@ + #include "bug.c" + #include "build_assert.c" + #include "build_bug.c" ++#include "completion.c" + #include "cpumask.c" + #include "cred.c" + #include "device.c" +--- a/rust/kernel/sync.rs ++++ b/rust/kernel/sync.rs +@@ -10,6 +10,7 @@ use crate::types::Opaque; + use pin_init; + + mod arc; ++pub mod completion; + mod condvar; + pub mod lock; + mod locked_by; +@@ -17,6 +18,7 @@ pub mod poll; + pub mod rcu; + + pub use arc::{Arc, ArcBorrow, UniqueArc}; ++pub use completion::Completion; + pub use condvar::{new_condvar, CondVar, CondVarTimeoutResult}; + pub use lock::global::{global_lock, GlobalGuard, GlobalLock, GlobalLockBackend, GlobalLockedBy}; + pub use lock::mutex::{new_mutex, Mutex, MutexGuard}; +--- /dev/null ++++ b/rust/kernel/sync/completion.rs +@@ -0,0 +1,112 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++//! Completion support. ++//! ++//! Reference: <https://docs.kernel.org/scheduler/completion.html> ++//! ++//! C header: [`include/linux/completion.h`](srctree/include/linux/completion.h) ++ ++use crate::{bindings, prelude::*, types::Opaque}; ++ ++/// Synchronization primitive to signal when a certain task has been completed. ++/// ++/// The [`Completion`] synchronization primitive signals when a certain task has been completed by ++/// waking up other tasks that have been queued up to wait for the [`Completion`] to be completed. ++/// ++/// # Examples ++/// ++/// ``` ++/// use kernel::sync::{Arc, Completion}; ++/// use kernel::workqueue::{self, impl_has_work, new_work, Work, WorkItem}; ++/// ++/// #[pin_data] ++/// struct MyTask { ++/// #[pin] ++/// work: Work<MyTask>, ++/// #[pin] ++/// done: Completion, ++/// } ++/// ++/// impl_has_work! { ++/// impl HasWork<Self> for MyTask { self.work } ++/// } ++/// ++/// impl MyTask { ++/// fn new() -> Result<Arc<Self>> { ++/// let this = Arc::pin_init(pin_init!(MyTask { ++/// work <- new_work!("MyTask::work"), ++/// done <- Completion::new(), ++/// }), GFP_KERNEL)?; ++/// ++/// let _ = workqueue::system().enqueue(this.clone()); ++/// ++/// Ok(this) ++/// } ++/// ++/// fn wait_for_completion(&self) { ++/// self.done.wait_for_completion(); ++/// ++/// pr_info!("Completion: task complete\n"); ++/// } ++/// } ++/// ++/// impl WorkItem for MyTask { ++/// type Pointer = Arc<MyTask>; ++/// ++/// fn run(this: Arc<MyTask>) { ++/// // process this task ++/// this.done.complete_all(); ++/// } ++/// } ++/// ++/// let task = MyTask::new()?; ++/// task.wait_for_completion(); ++/// # Ok::<(), Error>(()) ++/// ``` ++#[pin_data] ++pub struct Completion { ++ #[pin] ++ inner: Opaque<bindings::completion>, ++} ++ ++// SAFETY: `Completion` is safe to be send to any task. ++unsafe impl Send for Completion {} ++ ++// SAFETY: `Completion` is safe to be accessed concurrently. ++unsafe impl Sync for Completion {} ++ ++impl Completion { ++ /// Create an initializer for a new [`Completion`]. ++ pub fn new() -> impl PinInit<Self> { ++ pin_init!(Self { ++ inner <- Opaque::ffi_init(|slot: *mut bindings::completion| { ++ // SAFETY: `slot` is a valid pointer to an uninitialized `struct completion`. ++ unsafe { bindings::init_completion(slot) }; ++ }), ++ }) ++ } ++ ++ fn as_raw(&self) -> *mut bindings::completion { ++ self.inner.get() ++ } ++ ++ /// Signal all tasks waiting on this completion. ++ /// ++ /// This method wakes up all tasks waiting on this completion; after this operation the ++ /// completion is permanently done, i.e. signals all current and future waiters. ++ pub fn complete_all(&self) { ++ // SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`. ++ unsafe { bindings::complete_all(self.as_raw()) }; ++ } ++ ++ /// Wait for completion of a task. ++ /// ++ /// This method waits for the completion of a task; it is not interruptible and there is no ++ /// timeout. ++ /// ++ /// See also [`Completion::complete_all`]. ++ pub fn wait_for_completion(&self) { ++ // SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`. ++ unsafe { bindings::wait_for_completion(self.as_raw()) }; ++ } ++} |