* [PATCH v4 0/2] Add read_poll_timeout_atomic support
@ 2025-11-03 11:29 FUJITA Tomonori
2025-11-03 11:29 ` [PATCH v4 1/2] rust: add udelay() function FUJITA Tomonori
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: FUJITA Tomonori @ 2025-11-03 11:29 UTC (permalink / raw)
To: a.hindborg, alex.gaynor, aliceryhl, dakr, daniel.almeida, ojeda
Cc: anna-maria, bjorn3_gh, boqun.feng, frederic, gary, jstultz,
linux-kernel, lossin, lyude, rust-for-linux, sboyd, tglx, tmgross
Add read_poll_timeout_atomic function which polls periodically until a
condition is met, an error occurs, or the attempt limit is reached.
This helper is used to wait for a condition in atomic context,
mirroring the C's read_poll_timeout_atomic().
In atomic context, the timekeeping infrastructure is unavailable, so
reliable time-based timeouts cannot be implemented. So instead, the
helper accepts a maximum number of attempts and busy-waits (udelay +
cpu_relax) between tries.
v4:
- update the comment on udelay
- add Alice and Andreas' Reviewed-by
v3: https://lore.kernel.org/lkml/20251026125458.2772103-1-fujita.tomonori@gmail.com/
- revert the function name
- simplify the example code
- add debug_assert to check the range for udelay
v2: https://lore.kernel.org/lkml/20251021071146.2357069-1-fujita.tomonori@gmail.com/
- use the attempt limit instead of timeout
- rename the function to read_poll_count_atomic
- add the comment about C's udelay behavior.
v1: https://lore.kernel.org/lkml/20250821035710.3692455-1-fujita.tomonori@gmail.com/
FUJITA Tomonori (2):
rust: add udelay() function
rust: Add read_poll_timeout_atomic function
rust/helpers/time.c | 5 +++
rust/kernel/io/poll.rs | 72 ++++++++++++++++++++++++++++++++++++++-
rust/kernel/time/delay.rs | 37 ++++++++++++++++++++
3 files changed, 113 insertions(+), 1 deletion(-)
base-commit: b0b7301b004301afe920b3d08caa6171dd3f4011
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v4 1/2] rust: add udelay() function
2025-11-03 11:29 [PATCH v4 0/2] Add read_poll_timeout_atomic support FUJITA Tomonori
@ 2025-11-03 11:29 ` FUJITA Tomonori
2025-11-03 11:29 ` [PATCH v4 2/2] rust: Add read_poll_timeout_atomic function FUJITA Tomonori
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: FUJITA Tomonori @ 2025-11-03 11:29 UTC (permalink / raw)
To: a.hindborg, alex.gaynor, aliceryhl, dakr, daniel.almeida, ojeda
Cc: anna-maria, bjorn3_gh, boqun.feng, frederic, gary, jstultz,
linux-kernel, lossin, lyude, rust-for-linux, sboyd, tglx, tmgross
Add udelay() function, inserts a delay based on microseconds with busy
waiting, in preparation for supporting read_poll_timeout_atomic().
Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
rust/helpers/time.c | 5 +++++
rust/kernel/time/delay.rs | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/rust/helpers/time.c b/rust/helpers/time.c
index a318e9fa4408..67a36ccc3ec4 100644
--- a/rust/helpers/time.c
+++ b/rust/helpers/time.c
@@ -33,3 +33,8 @@ s64 rust_helper_ktime_to_ms(const ktime_t kt)
{
return ktime_to_ms(kt);
}
+
+void rust_helper_udelay(unsigned long usec)
+{
+ udelay(usec);
+}
diff --git a/rust/kernel/time/delay.rs b/rust/kernel/time/delay.rs
index eb8838da62bc..b5b1b42797a0 100644
--- a/rust/kernel/time/delay.rs
+++ b/rust/kernel/time/delay.rs
@@ -47,3 +47,40 @@ pub fn fsleep(delta: Delta) {
bindings::fsleep(delta.as_micros_ceil() as c_ulong)
}
}
+
+/// Inserts a delay based on microseconds with busy waiting.
+///
+/// Equivalent to the C side [`udelay()`], which delays in microseconds.
+///
+/// `delta` must be within `[0, MAX_UDELAY_MS]` in milliseconds;
+/// otherwise, it is erroneous behavior. That is, it is considered a bug to
+/// call this function with an out-of-range value.
+///
+/// The behavior above differs from the C side [`udelay()`] for which out-of-range
+/// values could lead to an overflow and unexpected behavior.
+///
+/// [`udelay()`]: https://docs.kernel.org/timers/delay_sleep_functions.html#c.udelay
+pub fn udelay(delta: Delta) {
+ const MAX_UDELAY_DELTA: Delta = Delta::from_millis(bindings::MAX_UDELAY_MS as i64);
+
+ debug_assert!(delta.as_nanos() >= 0);
+ debug_assert!(delta <= MAX_UDELAY_DELTA);
+
+ let delta = if (Delta::ZERO..=MAX_UDELAY_DELTA).contains(&delta) {
+ delta
+ } else {
+ MAX_UDELAY_DELTA
+ };
+
+ // SAFETY: It is always safe to call `udelay()` with any duration.
+ // Note that the kernel is compiled with `-fno-strict-overflow`
+ // so any out-of-range value could lead to unexpected behavior
+ // but won't lead to undefined behavior.
+ unsafe {
+ // Convert the duration to microseconds and round up to preserve
+ // the guarantee; `udelay()` inserts a delay for at least
+ // the provided duration, but that it may delay for longer
+ // under some circumstances.
+ bindings::udelay(delta.as_micros_ceil() as c_ulong)
+ }
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v4 2/2] rust: Add read_poll_timeout_atomic function
2025-11-03 11:29 [PATCH v4 0/2] Add read_poll_timeout_atomic support FUJITA Tomonori
2025-11-03 11:29 ` [PATCH v4 1/2] rust: add udelay() function FUJITA Tomonori
@ 2025-11-03 11:29 ` FUJITA Tomonori
2025-11-03 11:34 ` [PATCH v4 0/2] Add read_poll_timeout_atomic support Danilo Krummrich
2025-11-04 13:09 ` Danilo Krummrich
3 siblings, 0 replies; 6+ messages in thread
From: FUJITA Tomonori @ 2025-11-03 11:29 UTC (permalink / raw)
To: a.hindborg, alex.gaynor, aliceryhl, dakr, daniel.almeida, ojeda
Cc: anna-maria, bjorn3_gh, boqun.feng, frederic, gary, jstultz,
linux-kernel, lossin, lyude, rust-for-linux, sboyd, tglx, tmgross
Add read_poll_timeout_atomic function which polls periodically until a
condition is met, an error occurs, or the attempt limit is reached.
The C's read_poll_timeout_atomic() is used for the similar purpose.
In atomic context the timekeeping infrastructure is unavailable, so
reliable time-based timeouts cannot be implemented. So instead, the
helper accepts a maximum number of attempts and busy-waits (udelay +
cpu_relax) between tries.
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
rust/kernel/io/poll.rs | 72 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 71 insertions(+), 1 deletion(-)
diff --git a/rust/kernel/io/poll.rs b/rust/kernel/io/poll.rs
index 8f8886543f34..18bed3e78ef7 100644
--- a/rust/kernel/io/poll.rs
+++ b/rust/kernel/io/poll.rs
@@ -8,7 +8,10 @@
error::{code::*, Result},
processor::cpu_relax,
task::might_sleep,
- time::{delay::fsleep, Delta, Instant, Monotonic},
+ time::{
+ delay::{fsleep, udelay},
+ Delta, Instant, Monotonic,
+ },
};
/// Polls periodically until a condition is met, an error occurs,
@@ -96,3 +99,70 @@ pub fn read_poll_timeout<Op, Cond, T>(
cpu_relax();
}
}
+
+/// Polls periodically until a condition is met, an error occurs,
+/// or the attempt limit is reached.
+///
+/// The function repeatedly executes the given operation `op` closure and
+/// checks its result using the condition closure `cond`.
+///
+/// If `cond` returns `true`, the function returns successfully with the result of `op`.
+/// Otherwise, it performs a busy wait for a duration specified by `delay_delta`
+/// before executing `op` again.
+///
+/// This process continues until either `op` returns an error, `cond`
+/// returns `true`, or the attempt limit specified by `retry` is reached.
+///
+/// # Errors
+///
+/// If `op` returns an error, then that error is returned directly.
+///
+/// If the attempt limit specified by `retry` is reached, then
+/// `Err(ETIMEDOUT)` is returned.
+///
+/// # Examples
+///
+/// ```no_run
+/// use kernel::io::{poll::read_poll_timeout_atomic, Io};
+/// use kernel::time::Delta;
+///
+/// const HW_READY: u16 = 0x01;
+///
+/// fn wait_for_hardware<const SIZE: usize>(io: &Io<SIZE>) -> Result {
+/// read_poll_timeout_atomic(
+/// // The `op` closure reads the value of a specific status register.
+/// || io.try_read16(0x1000),
+/// // The `cond` closure takes a reference to the value returned by `op`
+/// // and checks whether the hardware is ready.
+/// |val: &u16| *val == HW_READY,
+/// Delta::from_micros(50),
+/// 1000,
+/// )?;
+/// Ok(())
+/// }
+/// ```
+pub fn read_poll_timeout_atomic<Op, Cond, T>(
+ mut op: Op,
+ mut cond: Cond,
+ delay_delta: Delta,
+ retry: usize,
+) -> Result<T>
+where
+ Op: FnMut() -> Result<T>,
+ Cond: FnMut(&T) -> bool,
+{
+ for _ in 0..retry {
+ let val = op()?;
+ if cond(&val) {
+ return Ok(val);
+ }
+
+ if !delay_delta.is_zero() {
+ udelay(delay_delta);
+ }
+
+ cpu_relax();
+ }
+
+ Err(ETIMEDOUT)
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v4 0/2] Add read_poll_timeout_atomic support
2025-11-03 11:29 [PATCH v4 0/2] Add read_poll_timeout_atomic support FUJITA Tomonori
2025-11-03 11:29 ` [PATCH v4 1/2] rust: add udelay() function FUJITA Tomonori
2025-11-03 11:29 ` [PATCH v4 2/2] rust: Add read_poll_timeout_atomic function FUJITA Tomonori
@ 2025-11-03 11:34 ` Danilo Krummrich
2025-11-04 11:26 ` Andreas Hindborg
2025-11-04 13:09 ` Danilo Krummrich
3 siblings, 1 reply; 6+ messages in thread
From: Danilo Krummrich @ 2025-11-03 11:34 UTC (permalink / raw)
To: a.hindborg
Cc: FUJITA Tomonori, alex.gaynor, aliceryhl, daniel.almeida, ojeda,
anna-maria, bjorn3_gh, boqun.feng, frederic, gary, jstultz,
linux-kernel, lossin, lyude, rust-for-linux, sboyd, tglx, tmgross
On 11/3/25 12:29 PM, FUJITA Tomonori wrote:
> rust: add udelay() function
> rust: Add read_poll_timeout_atomic function
@Andreas: Mind providing an ACK so I can pick this one up including the udelay()
patch?
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v4 0/2] Add read_poll_timeout_atomic support
2025-11-03 11:34 ` [PATCH v4 0/2] Add read_poll_timeout_atomic support Danilo Krummrich
@ 2025-11-04 11:26 ` Andreas Hindborg
0 siblings, 0 replies; 6+ messages in thread
From: Andreas Hindborg @ 2025-11-04 11:26 UTC (permalink / raw)
To: Danilo Krummrich
Cc: FUJITA Tomonori, alex.gaynor, aliceryhl, daniel.almeida, ojeda,
anna-maria, bjorn3_gh, boqun.feng, frederic, gary, jstultz,
linux-kernel, lossin, lyude, rust-for-linux, sboyd, tglx, tmgross
Danilo Krummrich <dakr@kernel.org> writes:
> On 11/3/25 12:29 PM, FUJITA Tomonori wrote:
>> rust: add udelay() function
>> rust: Add read_poll_timeout_atomic function
>
> @Andreas: Mind providing an ACK so I can pick this one up including the udelay()
> patch?
Acked-by: Andreas Hindborg <a.hindborg@kernel.org>
Best regards,
Andreas Hindborg
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v4 0/2] Add read_poll_timeout_atomic support
2025-11-03 11:29 [PATCH v4 0/2] Add read_poll_timeout_atomic support FUJITA Tomonori
` (2 preceding siblings ...)
2025-11-03 11:34 ` [PATCH v4 0/2] Add read_poll_timeout_atomic support Danilo Krummrich
@ 2025-11-04 13:09 ` Danilo Krummrich
3 siblings, 0 replies; 6+ messages in thread
From: Danilo Krummrich @ 2025-11-04 13:09 UTC (permalink / raw)
To: FUJITA Tomonori
Cc: a.hindborg, alex.gaynor, aliceryhl, daniel.almeida, ojeda,
anna-maria, bjorn3_gh, boqun.feng, frederic, gary, jstultz,
linux-kernel, lossin, lyude, rust-for-linux, sboyd, tglx, tmgross
On Mon Nov 3, 2025 at 12:29 PM CET, FUJITA Tomonori wrote:
Applied to driver-core-testing, thanks!
> FUJITA Tomonori (2):
> rust: add udelay() function
> rust: Add read_poll_timeout_atomic function
[ Adjust imports to use "kernel vertical" style. - Danilo ]
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-11-04 13:09 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-03 11:29 [PATCH v4 0/2] Add read_poll_timeout_atomic support FUJITA Tomonori
2025-11-03 11:29 ` [PATCH v4 1/2] rust: add udelay() function FUJITA Tomonori
2025-11-03 11:29 ` [PATCH v4 2/2] rust: Add read_poll_timeout_atomic function FUJITA Tomonori
2025-11-03 11:34 ` [PATCH v4 0/2] Add read_poll_timeout_atomic support Danilo Krummrich
2025-11-04 11:26 ` Andreas Hindborg
2025-11-04 13:09 ` Danilo Krummrich
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox