rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v1 0/2] add delay abstraction (sleep functions)
@ 2024-10-01 11:25 FUJITA Tomonori
  2024-10-01 11:25 ` [PATCH net-next v1 1/2] rust: add delay abstraction FUJITA Tomonori
                   ` (2 more replies)
  0 siblings, 3 replies; 40+ messages in thread
From: FUJITA Tomonori @ 2024-10-01 11:25 UTC (permalink / raw)
  To: netdev
  Cc: rust-for-linux, andrew, hkallweit1, tmgross, ojeda, alex.gaynor,
	gary, bjorn3_gh, benno.lossin, a.hindborg, aliceryhl

Add an abstraction for sleep functions in `include/linux/delay.h` for
dealing with hardware delays. `delay.h` supports sleep and delay (busy
wait). This adds support for sleep functions used by QT2025 PHY driver
to sleep until a PHY becomes ready.

The old rust branch has the delay abstraction which supports msleep()
with a helper function which rounds a `Duration` up to the nearest
milliseconds.

This adds fsleep() support instead of msleep(). fsleep() can handle
various lengths of delay by internally calling an appropriate sleep
function including msleep().


FUJITA Tomonori (2):
  rust: add delay abstraction
  net: phy: qt2025: wait until PHY becomes ready

 drivers/net/phy/qt2025.rs       | 11 +++++++++--
 rust/bindings/bindings_helper.h |  1 +
 rust/helpers/delay.c            |  8 ++++++++
 rust/helpers/helpers.c          |  1 +
 rust/kernel/delay.rs            | 18 ++++++++++++++++++
 rust/kernel/lib.rs              |  1 +
 6 files changed, 38 insertions(+), 2 deletions(-)
 create mode 100644 rust/helpers/delay.c
 create mode 100644 rust/kernel/delay.rs


base-commit: c824deb1a89755f70156b5cdaf569fca80698719
-- 
2.34.1


^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-01 11:25 [PATCH net-next v1 0/2] add delay abstraction (sleep functions) FUJITA Tomonori
@ 2024-10-01 11:25 ` FUJITA Tomonori
  2024-10-01 11:33   ` Alice Ryhl
  2024-10-01 12:31   ` Andrew Lunn
  2024-10-01 11:25 ` [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready FUJITA Tomonori
  2024-10-01 11:39 ` [PATCH net-next v1 0/2] add delay abstraction (sleep functions) Alice Ryhl
  2 siblings, 2 replies; 40+ messages in thread
From: FUJITA Tomonori @ 2024-10-01 11:25 UTC (permalink / raw)
  To: netdev
  Cc: rust-for-linux, andrew, hkallweit1, tmgross, ojeda, alex.gaynor,
	gary, bjorn3_gh, benno.lossin, a.hindborg, aliceryhl

Add an abstraction for sleep functions in `include/linux/delay.h` for
dealing with hardware delays.

The kernel supports several `sleep` functions for handles various
lengths of delay. This adds fsleep helper function, internally calls
an appropriate sleep function.

This is used by QT2025 PHY driver to wait until a PHY becomes ready.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
 rust/bindings/bindings_helper.h |  1 +
 rust/helpers/delay.c            |  8 ++++++++
 rust/helpers/helpers.c          |  1 +
 rust/kernel/delay.rs            | 18 ++++++++++++++++++
 rust/kernel/lib.rs              |  1 +
 5 files changed, 29 insertions(+)
 create mode 100644 rust/helpers/delay.c
 create mode 100644 rust/kernel/delay.rs

diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index ae82e9c941af..29a2f59294ba 100644
--- 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/delay.h>
 #include <linux/errname.h>
 #include <linux/ethtool.h>
 #include <linux/firmware.h>
diff --git a/rust/helpers/delay.c b/rust/helpers/delay.c
new file mode 100644
index 000000000000..7ae64ad8141d
--- /dev/null
+++ b/rust/helpers/delay.c
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/delay.h>
+
+void rust_helper_fsleep(unsigned long usecs)
+{
+	fsleep(usecs);
+}
diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
index 30f40149f3a9..279ea662ee3b 100644
--- a/rust/helpers/helpers.c
+++ b/rust/helpers/helpers.c
@@ -12,6 +12,7 @@
 #include "build_assert.c"
 #include "build_bug.c"
 #include "err.c"
+#include "delay.c"
 #include "kunit.c"
 #include "mutex.c"
 #include "page.c"
diff --git a/rust/kernel/delay.rs b/rust/kernel/delay.rs
new file mode 100644
index 000000000000..79f51a9608b5
--- /dev/null
+++ b/rust/kernel/delay.rs
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Delay and sleep routines.
+//!
+//! C headers: [`include/linux/delay.h`](srctree/include/linux/delay.h).
+
+use core::{ffi::c_ulong, time::Duration};
+
+/// Sleeps for a given duration.
+///
+/// Equivalent to the kernel's [`fsleep`] function, internally calls `udelay`,
+/// `usleep_range`, or `msleep`.
+///
+/// This function can only be used in a nonatomic context.
+pub fn sleep(duration: Duration) {
+    // SAFETY: FFI call.
+    unsafe { bindings::fsleep(duration.as_micros() as c_ulong) }
+}
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 22a3bfa5a9e9..c08cb5509c82 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -30,6 +30,7 @@
 #[cfg(CONFIG_BLOCK)]
 pub mod block;
 mod build_assert;
+pub mod delay;
 pub mod device;
 pub mod error;
 #[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready
  2024-10-01 11:25 [PATCH net-next v1 0/2] add delay abstraction (sleep functions) FUJITA Tomonori
  2024-10-01 11:25 ` [PATCH net-next v1 1/2] rust: add delay abstraction FUJITA Tomonori
@ 2024-10-01 11:25 ` FUJITA Tomonori
  2024-10-01 11:36   ` Alice Ryhl
  2024-10-01 11:39 ` [PATCH net-next v1 0/2] add delay abstraction (sleep functions) Alice Ryhl
  2 siblings, 1 reply; 40+ messages in thread
From: FUJITA Tomonori @ 2024-10-01 11:25 UTC (permalink / raw)
  To: netdev
  Cc: rust-for-linux, andrew, hkallweit1, tmgross, ojeda, alex.gaynor,
	gary, bjorn3_gh, benno.lossin, a.hindborg, aliceryhl

Wait until a PHY becomes ready in the probe callback by using a sleep
function.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
 drivers/net/phy/qt2025.rs | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/qt2025.rs b/drivers/net/phy/qt2025.rs
index 28d8981f410b..3a8ef9f73642 100644
--- a/drivers/net/phy/qt2025.rs
+++ b/drivers/net/phy/qt2025.rs
@@ -93,8 +93,15 @@ fn probe(dev: &mut phy::Device) -> Result<()> {
         // The micro-controller will start running from SRAM.
         dev.write(C45::new(Mmd::PCS, 0xe854), 0x0040)?;
 
-        // TODO: sleep here until the hw becomes ready.
-        Ok(())
+        // sleep here until the hw becomes ready.
+        for _ in 0..60 {
+            kernel::delay::sleep(core::time::Duration::from_millis(50));
+            let val = dev.read(C45::new(Mmd::PCS, 0xd7fd))?;
+            if val != 0x00 && val != 0x10 {
+                return Ok(());
+            }
+        }
+        Err(code::ENODEV)
     }
 
     fn read_status(dev: &mut phy::Device) -> Result<u16> {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-01 11:25 ` [PATCH net-next v1 1/2] rust: add delay abstraction FUJITA Tomonori
@ 2024-10-01 11:33   ` Alice Ryhl
  2024-10-01 12:31   ` Andrew Lunn
  1 sibling, 0 replies; 40+ messages in thread
From: Alice Ryhl @ 2024-10-01 11:33 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: netdev, rust-for-linux, andrew, hkallweit1, tmgross, ojeda,
	alex.gaynor, gary, bjorn3_gh, benno.lossin, a.hindborg

On Tue, Oct 1, 2024 at 1:27 PM FUJITA Tomonori
<fujita.tomonori@gmail.com> wrote:
>
> Add an abstraction for sleep functions in `include/linux/delay.h` for
> dealing with hardware delays.
>
> The kernel supports several `sleep` functions for handles various
> lengths of delay. This adds fsleep helper function, internally calls
> an appropriate sleep function.
>
> This is used by QT2025 PHY driver to wait until a PHY becomes ready.
>
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
> ---
>  rust/bindings/bindings_helper.h |  1 +
>  rust/helpers/delay.c            |  8 ++++++++
>  rust/helpers/helpers.c          |  1 +
>  rust/kernel/delay.rs            | 18 ++++++++++++++++++
>  rust/kernel/lib.rs              |  1 +

There is already a rust/kernel/time.rs file that this can go in.

> +/// Sleeps for a given duration.
> +///
> +/// Equivalent to the kernel's [`fsleep`] function, internally calls `udelay`,
> +/// `usleep_range`, or `msleep`.
> +///
> +/// This function can only be used in a nonatomic context.
> +pub fn sleep(duration: Duration) {
> +    // SAFETY: FFI call.
> +    unsafe { bindings::fsleep(duration.as_micros() as c_ulong) }
> +}

We should probably call this `fsleep` to match the C side.

Alice

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready
  2024-10-01 11:25 ` [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready FUJITA Tomonori
@ 2024-10-01 11:36   ` Alice Ryhl
  2024-10-01 12:48     ` Andrew Lunn
  2024-10-02 11:17     ` FUJITA Tomonori
  0 siblings, 2 replies; 40+ messages in thread
From: Alice Ryhl @ 2024-10-01 11:36 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: netdev, rust-for-linux, andrew, hkallweit1, tmgross, ojeda,
	alex.gaynor, gary, bjorn3_gh, benno.lossin, a.hindborg

On Tue, Oct 1, 2024 at 1:27 PM FUJITA Tomonori
<fujita.tomonori@gmail.com> wrote:
>
> Wait until a PHY becomes ready in the probe callback by using a sleep
> function.
>
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
> ---
>  drivers/net/phy/qt2025.rs | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/phy/qt2025.rs b/drivers/net/phy/qt2025.rs
> index 28d8981f410b..3a8ef9f73642 100644
> --- a/drivers/net/phy/qt2025.rs
> +++ b/drivers/net/phy/qt2025.rs
> @@ -93,8 +93,15 @@ fn probe(dev: &mut phy::Device) -> Result<()> {
>          // The micro-controller will start running from SRAM.
>          dev.write(C45::new(Mmd::PCS, 0xe854), 0x0040)?;
>
> -        // TODO: sleep here until the hw becomes ready.
> -        Ok(())
> +        // sleep here until the hw becomes ready.
> +        for _ in 0..60 {
> +            kernel::delay::sleep(core::time::Duration::from_millis(50));
> +            let val = dev.read(C45::new(Mmd::PCS, 0xd7fd))?;
> +            if val != 0x00 && val != 0x10 {
> +                return Ok(());
> +            }

Why not place the sleep after this check? That way, we don't need to
sleep if the check succeeds immediately.

> +        }
> +        Err(code::ENODEV)

This sleeps for up to 3 seconds. Is that the right amount to sleep?

Alice

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 0/2] add delay abstraction (sleep functions)
  2024-10-01 11:25 [PATCH net-next v1 0/2] add delay abstraction (sleep functions) FUJITA Tomonori
  2024-10-01 11:25 ` [PATCH net-next v1 1/2] rust: add delay abstraction FUJITA Tomonori
  2024-10-01 11:25 ` [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready FUJITA Tomonori
@ 2024-10-01 11:39 ` Alice Ryhl
  2 siblings, 0 replies; 40+ messages in thread
From: Alice Ryhl @ 2024-10-01 11:39 UTC (permalink / raw)
  To: FUJITA Tomonori, Anna-Maria Behnsen, Frederic Weisbecker,
	Thomas Gleixner
  Cc: netdev, rust-for-linux, andrew, hkallweit1, tmgross, ojeda,
	alex.gaynor, gary, bjorn3_gh, benno.lossin, a.hindborg

On Tue, Oct 1, 2024 at 1:27 PM FUJITA Tomonori
<fujita.tomonori@gmail.com> wrote:
>
> Add an abstraction for sleep functions in `include/linux/delay.h` for
> dealing with hardware delays. `delay.h` supports sleep and delay (busy
> wait). This adds support for sleep functions used by QT2025 PHY driver
> to sleep until a PHY becomes ready.
>
> The old rust branch has the delay abstraction which supports msleep()
> with a helper function which rounds a `Duration` up to the nearest
> milliseconds.
>
> This adds fsleep() support instead of msleep(). fsleep() can handle
> various lengths of delay by internally calling an appropriate sleep
> function including msleep().

Add time keeping maintainers to CC.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-01 11:25 ` [PATCH net-next v1 1/2] rust: add delay abstraction FUJITA Tomonori
  2024-10-01 11:33   ` Alice Ryhl
@ 2024-10-01 12:31   ` Andrew Lunn
  2024-10-01 15:08     ` Miguel Ojeda
                       ` (2 more replies)
  1 sibling, 3 replies; 40+ messages in thread
From: Andrew Lunn @ 2024-10-01 12:31 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: netdev, rust-for-linux, hkallweit1, tmgross, ojeda, alex.gaynor,
	gary, bjorn3_gh, benno.lossin, a.hindborg, aliceryhl

On Tue, Oct 01, 2024 at 11:25:11AM +0000, FUJITA Tomonori wrote:
> Add an abstraction for sleep functions in `include/linux/delay.h` for
> dealing with hardware delays.
> 
> The kernel supports several `sleep` functions for handles various

s/for/which

> lengths of delay. This adds fsleep helper function, internally calls
> an appropriate sleep function.
> 
> This is used by QT2025 PHY driver to wait until a PHY becomes ready.
> 
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
> ---
>  rust/bindings/bindings_helper.h |  1 +
>  rust/helpers/delay.c            |  8 ++++++++
>  rust/helpers/helpers.c          |  1 +
>  rust/kernel/delay.rs            | 18 ++++++++++++++++++
>  rust/kernel/lib.rs              |  1 +
>  5 files changed, 29 insertions(+)
>  create mode 100644 rust/helpers/delay.c
>  create mode 100644 rust/kernel/delay.rs
> 
> diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
> index ae82e9c941af..29a2f59294ba 100644
> --- 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/delay.h>
>  #include <linux/errname.h>
>  #include <linux/ethtool.h>
>  #include <linux/firmware.h>
> diff --git a/rust/helpers/delay.c b/rust/helpers/delay.c
> new file mode 100644
> index 000000000000..7ae64ad8141d
> --- /dev/null
> +++ b/rust/helpers/delay.c
> @@ -0,0 +1,8 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/delay.h>
> +
> +void rust_helper_fsleep(unsigned long usecs)
> +{
> +	fsleep(usecs);
> +}
> diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
> index 30f40149f3a9..279ea662ee3b 100644
> --- a/rust/helpers/helpers.c
> +++ b/rust/helpers/helpers.c
> @@ -12,6 +12,7 @@
>  #include "build_assert.c"
>  #include "build_bug.c"
>  #include "err.c"
> +#include "delay.c"
>  #include "kunit.c"
>  #include "mutex.c"
>  #include "page.c"
> diff --git a/rust/kernel/delay.rs b/rust/kernel/delay.rs
> new file mode 100644
> index 000000000000..79f51a9608b5
> --- /dev/null
> +++ b/rust/kernel/delay.rs
> @@ -0,0 +1,18 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! Delay and sleep routines.
> +//!
> +//! C headers: [`include/linux/delay.h`](srctree/include/linux/delay.h).
> +
> +use core::{ffi::c_ulong, time::Duration};
> +
> +/// Sleeps for a given duration.
> +///
> +/// Equivalent to the kernel's [`fsleep`] function, internally calls `udelay`,
> +/// `usleep_range`, or `msleep`.

Is it possible to cross reference
Documentation/timers/timers-howto.rst ?  fsleep() points to it, so it
would e good if the Rust version also did.

I would also document the units for the parameter. Is it picoseconds
or centuries?

	Andrew

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready
  2024-10-01 11:36   ` Alice Ryhl
@ 2024-10-01 12:48     ` Andrew Lunn
  2024-10-02  4:39       ` iopoll abstraction (was: Re: [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready) Dirk Behme
  2024-10-02 10:13       ` [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready FUJITA Tomonori
  2024-10-02 11:17     ` FUJITA Tomonori
  1 sibling, 2 replies; 40+ messages in thread
From: Andrew Lunn @ 2024-10-01 12:48 UTC (permalink / raw)
  To: Alice Ryhl
  Cc: FUJITA Tomonori, netdev, rust-for-linux, hkallweit1, tmgross,
	ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin, a.hindborg

On Tue, Oct 01, 2024 at 01:36:41PM +0200, Alice Ryhl wrote:
> On Tue, Oct 1, 2024 at 1:27 PM FUJITA Tomonori
> <fujita.tomonori@gmail.com> wrote:
> >
> > Wait until a PHY becomes ready in the probe callback by using a sleep
> > function.
> >
> > Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
> > ---
> >  drivers/net/phy/qt2025.rs | 11 +++++++++--
> >  1 file changed, 9 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/phy/qt2025.rs b/drivers/net/phy/qt2025.rs
> > index 28d8981f410b..3a8ef9f73642 100644
> > --- a/drivers/net/phy/qt2025.rs
> > +++ b/drivers/net/phy/qt2025.rs
> > @@ -93,8 +93,15 @@ fn probe(dev: &mut phy::Device) -> Result<()> {
> >          // The micro-controller will start running from SRAM.
> >          dev.write(C45::new(Mmd::PCS, 0xe854), 0x0040)?;
> >
> > -        // TODO: sleep here until the hw becomes ready.
> > -        Ok(())
> > +        // sleep here until the hw becomes ready.
> > +        for _ in 0..60 {
> > +            kernel::delay::sleep(core::time::Duration::from_millis(50));
> > +            let val = dev.read(C45::new(Mmd::PCS, 0xd7fd))?;
> > +            if val != 0x00 && val != 0x10 {
> > +                return Ok(());
> > +            }
> 
> Why not place the sleep after this check? That way, we don't need to
> sleep if the check succeeds immediately.

Nice, you just made my point :-)

I generally point developers at iopoll.h, because developers nearly
always get this sort of polling for something to happen wrong. 

The kernel sleep functions guarantee the minimum sleep time. They say
nothing about the maximum sleep time. You can ask it to sleep for 1ms,
and in reality, due to something stealing the CPU and not being RT
friendly, it actually sleeps for 10ms. This extra long sleep time
blows straight past your timeout, if you have a time based timeout.
What most developers do is after the sleep() returns they check to see
if the timeout has been reached and then exit with -ETIMEDOUT. They
don't check the state of the hardware, which given its had a long time
to do its thing, probably is now in a good state. But the function
returns -ETIMEDOUT.

There should always be a check of the hardware state after the sleep,
in order to determine ETIMEDOUT vs 0.

As i said, most C developers get this wrong. So i don't really see why
Rust developers also will not get this wrong. So i like to discourage
this sort of code, and have Rust implementations of iopoll.h.

	Andrew

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-01 12:31   ` Andrew Lunn
@ 2024-10-01 15:08     ` Miguel Ojeda
  2024-10-02 11:34     ` FUJITA Tomonori
  2024-10-04 12:08     ` FUJITA Tomonori
  2 siblings, 0 replies; 40+ messages in thread
From: Miguel Ojeda @ 2024-10-01 15:08 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: FUJITA Tomonori, netdev, rust-for-linux, hkallweit1, tmgross,
	ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin, a.hindborg,
	aliceryhl

On Tue, Oct 1, 2024 at 2:31 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> Is it possible to cross reference
> Documentation/timers/timers-howto.rst ?  fsleep() points to it, so it
> would e good if the Rust version also did.

We currently use links like:

    //! Reference: <https://docs.kernel.org/core-api/rbtree.html>

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 40+ messages in thread

* iopoll abstraction (was: Re: [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready)
  2024-10-01 12:48     ` Andrew Lunn
@ 2024-10-02  4:39       ` Dirk Behme
  2024-10-02  9:56         ` iopoll abstraction FUJITA Tomonori
  2024-10-02 10:13       ` [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready FUJITA Tomonori
  1 sibling, 1 reply; 40+ messages in thread
From: Dirk Behme @ 2024-10-02  4:39 UTC (permalink / raw)
  To: Andrew Lunn, Alice Ryhl
  Cc: FUJITA Tomonori, netdev, rust-for-linux, hkallweit1, tmgross,
	ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin, a.hindborg

On 01.10.2024 14:48, Andrew Lunn wrote:
> On Tue, Oct 01, 2024 at 01:36:41PM +0200, Alice Ryhl wrote:
>> On Tue, Oct 1, 2024 at 1:27 PM FUJITA Tomonori
>> <fujita.tomonori@gmail.com> wrote:
>>>
>>> Wait until a PHY becomes ready in the probe callback by using a sleep
>>> function.
>>>
>>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
>>> ---
>>>   drivers/net/phy/qt2025.rs | 11 +++++++++--
>>>   1 file changed, 9 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/net/phy/qt2025.rs b/drivers/net/phy/qt2025.rs
>>> index 28d8981f410b..3a8ef9f73642 100644
>>> --- a/drivers/net/phy/qt2025.rs
>>> +++ b/drivers/net/phy/qt2025.rs
>>> @@ -93,8 +93,15 @@ fn probe(dev: &mut phy::Device) -> Result<()> {
>>>           // The micro-controller will start running from SRAM.
>>>           dev.write(C45::new(Mmd::PCS, 0xe854), 0x0040)?;
>>>
>>> -        // TODO: sleep here until the hw becomes ready.
>>> -        Ok(())
>>> +        // sleep here until the hw becomes ready.
>>> +        for _ in 0..60 {
>>> +            kernel::delay::sleep(core::time::Duration::from_millis(50));
>>> +            let val = dev.read(C45::new(Mmd::PCS, 0xd7fd))?;
>>> +            if val != 0x00 && val != 0x10 {
>>> +                return Ok(());
>>> +            }
>>
>> Why not place the sleep after this check? That way, we don't need to
>> sleep if the check succeeds immediately.
> 
> Nice, you just made my point :-)
> 
> I generally point developers at iopoll.h, because developers nearly
> always get this sort of polling for something to happen wrong.
> 
> The kernel sleep functions guarantee the minimum sleep time. They say
> nothing about the maximum sleep time. You can ask it to sleep for 1ms,
> and in reality, due to something stealing the CPU and not being RT
> friendly, it actually sleeps for 10ms. This extra long sleep time
> blows straight past your timeout, if you have a time based timeout.
> What most developers do is after the sleep() returns they check to see
> if the timeout has been reached and then exit with -ETIMEDOUT. They
> don't check the state of the hardware, which given its had a long time
> to do its thing, probably is now in a good state. But the function
> returns -ETIMEDOUT.
> 
> There should always be a check of the hardware state after the sleep,
> in order to determine ETIMEDOUT vs 0.
> 
> As i said, most C developers get this wrong. So i don't really see why
> Rust developers also will not get this wrong. So i like to discourage
> this sort of code, and have Rust implementations of iopoll.h.


Do we talk about some simple Rust wrappers for the macros in iopoll.h? 
E.g. something like [1]?

Or are we talking about some more complex (safety) dependencies which 
need some more complex abstraction handling?

Best regards

Dirk

[1]

int rust_helper_readb_poll_timeout(const volatile void * addr,
                                   u64 val, u64 cond, u64 delay_us,
                                   u64 timeout_us)
{
        return readb_poll_timeout(addr, val, cond, delay_us, timeout_us);
}




^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: iopoll abstraction
  2024-10-02  4:39       ` iopoll abstraction (was: Re: [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready) Dirk Behme
@ 2024-10-02  9:56         ` FUJITA Tomonori
  2024-10-03 11:52           ` Boqun Feng
  0 siblings, 1 reply; 40+ messages in thread
From: FUJITA Tomonori @ 2024-10-02  9:56 UTC (permalink / raw)
  To: dirk.behme
  Cc: andrew, aliceryhl, fujita.tomonori, netdev, rust-for-linux,
	hkallweit1, tmgross, ojeda, alex.gaynor, gary, bjorn3_gh,
	benno.lossin, a.hindborg

On Wed, 2 Oct 2024 06:39:48 +0200
Dirk Behme <dirk.behme@de.bosch.com> wrote:

>> I generally point developers at iopoll.h, because developers nearly
>> always get this sort of polling for something to happen wrong.
>> The kernel sleep functions guarantee the minimum sleep time. They say
>> nothing about the maximum sleep time. You can ask it to sleep for 1ms,
>> and in reality, due to something stealing the CPU and not being RT
>> friendly, it actually sleeps for 10ms. This extra long sleep time
>> blows straight past your timeout, if you have a time based timeout.
>> What most developers do is after the sleep() returns they check to see
>> if the timeout has been reached and then exit with -ETIMEDOUT. They
>> don't check the state of the hardware, which given its had a long time
>> to do its thing, probably is now in a good state. But the function
>> returns -ETIMEDOUT.
>> There should always be a check of the hardware state after the sleep,
>> in order to determine ETIMEDOUT vs 0.
>> As i said, most C developers get this wrong. So i don't really see why
>> Rust developers also will not get this wrong. So i like to discourage
>> this sort of code, and have Rust implementations of iopoll.h.
> 
> 
> Do we talk about some simple Rust wrappers for the macros in iopoll.h?
> E.g. something like [1]?
> 
> Or are we talking about some more complex (safety) dependencies which
> need some more complex abstraction handling?

(snip)

> int rust_helper_readb_poll_timeout(const volatile void * addr,
>                                   u64 val, u64 cond, u64 delay_us,
>                                   u64 timeout_us)
> {
>        return readb_poll_timeout(addr, val, cond, delay_us, timeout_us);
> }

I'm not sure a simple wrapper for iopoll.h works. We need to pass a
function. I'm testing a macro like the following (not added ktime
timeout yet):

macro_rules! read_poll_timeout {
    ($op:expr, $val:expr, $cond:expr, $sleep:expr, $timeout:expr, $($args:expr),*) => {{
        let _ = $val;
        loop {
            $val = $op($($args),*);
            if $cond {
                break;
            }
            kernel::delay::sleep($sleep);
        }
        if $cond {
            Ok(())
        } else {
            Err(kernel::error::code::ETIMEDOUT)
        }
    }};
}

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready
  2024-10-01 12:48     ` Andrew Lunn
  2024-10-02  4:39       ` iopoll abstraction (was: Re: [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready) Dirk Behme
@ 2024-10-02 10:13       ` FUJITA Tomonori
  2024-10-02 12:31         ` Andrew Lunn
  1 sibling, 1 reply; 40+ messages in thread
From: FUJITA Tomonori @ 2024-10-02 10:13 UTC (permalink / raw)
  To: andrew
  Cc: aliceryhl, fujita.tomonori, netdev, rust-for-linux, hkallweit1,
	tmgross, ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin,
	a.hindborg

On Tue, 1 Oct 2024 14:48:06 +0200
Andrew Lunn <andrew@lunn.ch> wrote:

> I generally point developers at iopoll.h, because developers nearly
> always get this sort of polling for something to happen wrong. 

Ah, I had forgotten about iopoll.h. Make senses. I'll try implement an
equivalent in Rust.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready
  2024-10-01 11:36   ` Alice Ryhl
  2024-10-01 12:48     ` Andrew Lunn
@ 2024-10-02 11:17     ` FUJITA Tomonori
  1 sibling, 0 replies; 40+ messages in thread
From: FUJITA Tomonori @ 2024-10-02 11:17 UTC (permalink / raw)
  To: aliceryhl
  Cc: fujita.tomonori, netdev, rust-for-linux, andrew, hkallweit1,
	tmgross, ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin,
	a.hindborg

On Tue, 1 Oct 2024 13:36:41 +0200
Alice Ryhl <aliceryhl@google.com> wrote:

>> diff --git a/drivers/net/phy/qt2025.rs b/drivers/net/phy/qt2025.rs
>> index 28d8981f410b..3a8ef9f73642 100644
>> --- a/drivers/net/phy/qt2025.rs
>> +++ b/drivers/net/phy/qt2025.rs
>> @@ -93,8 +93,15 @@ fn probe(dev: &mut phy::Device) -> Result<()> {
>>          // The micro-controller will start running from SRAM.
>>          dev.write(C45::new(Mmd::PCS, 0xe854), 0x0040)?;
>>
>> -        // TODO: sleep here until the hw becomes ready.
>> -        Ok(())
>> +        // sleep here until the hw becomes ready.
>> +        for _ in 0..60 {
>> +            kernel::delay::sleep(core::time::Duration::from_millis(50));
>> +            let val = dev.read(C45::new(Mmd::PCS, 0xd7fd))?;
>> +            if val != 0x00 && val != 0x10 {
>> +                return Ok(());
>> +            }
> 
> Why not place the sleep after this check? That way, we don't need to
> sleep if the check succeeds immediately.

Yeah, that's better. I copied the logic in the vendor driver without
thinking.

As Andrew pointed out, the code like this in C drivers isn't
recommended; iopoll.h should be used. So I'll try to implement such.


>> +        }
>> +        Err(code::ENODEV)
> 
> This sleeps for up to 3 seconds. Is that the right amount to sleep?

That's what the vendor driver does.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-01 12:31   ` Andrew Lunn
  2024-10-01 15:08     ` Miguel Ojeda
@ 2024-10-02 11:34     ` FUJITA Tomonori
  2024-10-02 12:18       ` Andrew Lunn
  2024-10-04 12:08     ` FUJITA Tomonori
  2 siblings, 1 reply; 40+ messages in thread
From: FUJITA Tomonori @ 2024-10-02 11:34 UTC (permalink / raw)
  To: andrew
  Cc: fujita.tomonori, netdev, rust-for-linux, hkallweit1, tmgross,
	ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin, a.hindborg,
	aliceryhl

On Tue, 1 Oct 2024 14:31:39 +0200
Andrew Lunn <andrew@lunn.ch> wrote:

> On Tue, Oct 01, 2024 at 11:25:11AM +0000, FUJITA Tomonori wrote:
>> Add an abstraction for sleep functions in `include/linux/delay.h` for
>> dealing with hardware delays.
>> 
>> The kernel supports several `sleep` functions for handles various
> 
> s/for/which

Oops, thanks.

>> +/// Sleeps for a given duration.
>> +///
>> +/// Equivalent to the kernel's [`fsleep`] function, internally calls `udelay`,
>> +/// `usleep_range`, or `msleep`.
> 
> Is it possible to cross reference
> Documentation/timers/timers-howto.rst ?  fsleep() points to it, so it
> would e good if the Rust version also did.
> 
> I would also document the units for the parameter. Is it picoseconds
> or centuries?

Rust's Duration is created from seconds and nanoseconds.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-02 11:34     ` FUJITA Tomonori
@ 2024-10-02 12:18       ` Andrew Lunn
  2024-10-02 12:35         ` Miguel Ojeda
  2024-10-02 12:37         ` Alice Ryhl
  0 siblings, 2 replies; 40+ messages in thread
From: Andrew Lunn @ 2024-10-02 12:18 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: netdev, rust-for-linux, hkallweit1, tmgross, ojeda, alex.gaynor,
	gary, bjorn3_gh, benno.lossin, a.hindborg, aliceryhl

> > I would also document the units for the parameter. Is it picoseconds
> > or centuries?
> 
> Rust's Duration is created from seconds and nanoseconds.

How well know is that? And is there a rust-for-linux wide preference
to use Duration for time? Are we going to get into a situation that
some abstractions use Duration, others seconds, some milliseconds,
etc, just like C code?

Anyway, i would still document the parameter is a Duration, since it
is different to how C fsleep() works.

	Andrew

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready
  2024-10-02 10:13       ` [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready FUJITA Tomonori
@ 2024-10-02 12:31         ` Andrew Lunn
  2024-10-03  5:07           ` FUJITA Tomonori
  0 siblings, 1 reply; 40+ messages in thread
From: Andrew Lunn @ 2024-10-02 12:31 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: aliceryhl, netdev, rust-for-linux, hkallweit1, tmgross, ojeda,
	alex.gaynor, gary, bjorn3_gh, benno.lossin, a.hindborg

On Wed, Oct 02, 2024 at 10:13:39AM +0000, FUJITA Tomonori wrote:
> On Tue, 1 Oct 2024 14:48:06 +0200
> Andrew Lunn <andrew@lunn.ch> wrote:
> 
> > I generally point developers at iopoll.h, because developers nearly
> > always get this sort of polling for something to happen wrong. 
> 
> Ah, I had forgotten about iopoll.h. Make senses. I'll try implement an
> equivalent in Rust.

There are some subtleties involved with PHYs, which is why we have our
own wrapper around the macros in iopoll.h:

https://elixir.bootlin.com/linux/v6.11.1/source/include/linux/phy.h#L1288

Normally an IO operation cannot fail. But PHYs are different, a read
could return -EOPNOTSUPP, -EIO, -ETIMEDOUT etc. That needs to be take
into account and checked before evaluating the condition.

So you might need to think about something similar for Rust. A generic
read_poll_timeout() and a phy_read_poll_timeout() built on top of it.

This is a worthwhile set of helpers to have, since the bugs in this
are nothing to do with memory safety, but plain simple logic bugs,
which Rust itself is unlikely to help with.

	Andrew

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-02 12:18       ` Andrew Lunn
@ 2024-10-02 12:35         ` Miguel Ojeda
  2024-10-02 12:51           ` Andrew Lunn
  2024-10-02 12:37         ` Alice Ryhl
  1 sibling, 1 reply; 40+ messages in thread
From: Miguel Ojeda @ 2024-10-02 12:35 UTC (permalink / raw)
  To: Andrew Lunn, Thomas Gleixner
  Cc: FUJITA Tomonori, netdev, rust-for-linux, hkallweit1, tmgross,
	ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin, a.hindborg,
	aliceryhl

On Wed, Oct 2, 2024 at 2:19 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> How well know is that? And is there a rust-for-linux wide preference
> to use Duration for time? Are we going to get into a situation that
> some abstractions use Duration, others seconds, some milliseconds,
> etc, just like C code?

We have `Ktime` that wraps `ktime_t`.

However, note that something like `Ktime` or `Duration` are types, not
a typedef, i.e. it is not an integer where you may confuse the unit.

So, for instance, the implementation here calls `as_micros()` to get
the actual integer. And whoever constructs e.g. a `Duration` has
several constructors to do so, not just the one that takes seconds and
nanoseconds, e.g. there is also `from_millis()`.

Perhaps we may end up needing different abstractions depending on what
we need (Cc'ing Thomas), but we will almost certainly want to still
use types like this, rather than plain integers or typedefs where
units can be confused.

> Anyway, i would still document the parameter is a Duration, since it
> is different to how C fsleep() works.

That is in the signature itself -- so taking into account what I
mentioned above, does it make sense that seeing the type in the
signature would be enough?

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-02 12:18       ` Andrew Lunn
  2024-10-02 12:35         ` Miguel Ojeda
@ 2024-10-02 12:37         ` Alice Ryhl
  2024-10-02 13:58           ` FUJITA Tomonori
  1 sibling, 1 reply; 40+ messages in thread
From: Alice Ryhl @ 2024-10-02 12:37 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: FUJITA Tomonori, netdev, rust-for-linux, hkallweit1, tmgross,
	ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin, a.hindborg

On Wed, Oct 2, 2024 at 2:19 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> > > I would also document the units for the parameter. Is it picoseconds
> > > or centuries?
> >
> > Rust's Duration is created from seconds and nanoseconds.
>
> How well know is that? And is there a rust-for-linux wide preference
> to use Duration for time? Are we going to get into a situation that
> some abstractions use Duration, others seconds, some milliseconds,
> etc, just like C code?
>
> Anyway, i would still document the parameter is a Duration, since it
> is different to how C fsleep() works.

I'm not necessarily convinced we want to use the Rust Duration type.
Similar questions came up when I added the Ktime type. The Rust
Duration type is rather large.

Alice

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-02 12:35         ` Miguel Ojeda
@ 2024-10-02 12:51           ` Andrew Lunn
  2024-10-02 13:21             ` Miguel Ojeda
  0 siblings, 1 reply; 40+ messages in thread
From: Andrew Lunn @ 2024-10-02 12:51 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Thomas Gleixner, FUJITA Tomonori, netdev, rust-for-linux,
	hkallweit1, tmgross, ojeda, alex.gaynor, gary, bjorn3_gh,
	benno.lossin, a.hindborg, aliceryhl

On Wed, Oct 02, 2024 at 02:35:57PM +0200, Miguel Ojeda wrote:
> On Wed, Oct 2, 2024 at 2:19 PM Andrew Lunn <andrew@lunn.ch> wrote:
> >
> > How well know is that? And is there a rust-for-linux wide preference
> > to use Duration for time? Are we going to get into a situation that
> > some abstractions use Duration, others seconds, some milliseconds,
> > etc, just like C code?
> 
> We have `Ktime` that wraps `ktime_t`.
> 
> However, note that something like `Ktime` or `Duration` are types, not
> a typedef, i.e. it is not an integer where you may confuse the unit.
> 
> So, for instance, the implementation here calls `as_micros()` to get
> the actual integer. And whoever constructs e.g. a `Duration` has
> several constructors to do so, not just the one that takes seconds and
> nanoseconds, e.g. there is also `from_millis()`.
> 
> Perhaps we may end up needing different abstractions depending on what
> we need (Cc'ing Thomas), but we will almost certainly want to still
> use types like this, rather than plain integers or typedefs where
> units can be confused.
> 
> > Anyway, i would still document the parameter is a Duration, since it
> > is different to how C fsleep() works.
> 
> That is in the signature itself -- so taking into account what I
> mentioned above, does it make sense that seeing the type in the
> signature would be enough?

Which is better, the Rust type system catching the error, or not
making the error in the first place because you read the documentation
and it pointed you in the right direction?

Maybe this is my background as a C programmer, with its sloppy type
system, but i prefer to have this very clear, maybe redundantly
stating it in words in addition to the signature.

	Andrew

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-02 12:51           ` Andrew Lunn
@ 2024-10-02 13:21             ` Miguel Ojeda
  2024-10-02 20:04               ` Thomas Gleixner
  0 siblings, 1 reply; 40+ messages in thread
From: Miguel Ojeda @ 2024-10-02 13:21 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Thomas Gleixner, FUJITA Tomonori, netdev, rust-for-linux,
	hkallweit1, tmgross, ojeda, alex.gaynor, gary, bjorn3_gh,
	benno.lossin, a.hindborg, aliceryhl

On Wed, Oct 2, 2024 at 2:51 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> Which is better, the Rust type system catching the error, or not
> making the error in the first place because you read the documentation
> and it pointed you in the right direction?

The former, because we don't want to duplicate documentation of every
type in every function that uses a type. It does not scale, and it
would be worse for the reader of the docs as soon as you become
familiar with a given type.

Of course, there may be exceptions, but just using a type normally
should not require explaining the type itself in every function.

Also note that in e.g. the rendered docs you can jump to another type
with a single click on top of the name. In some editors, you may be
able to e.g. hover it perhaps.

> Maybe this is my background as a C programmer, with its sloppy type
> system, but i prefer to have this very clear, maybe redundantly
> stating it in words in addition to the signature.

The second part of my message was about the signature point you made,
i.e. not about the units. So I am not sure if you are asking here to
re-state the types of parameters in every function's docs -- what do
you gain from that in common cases?

We also don't repeat every parameter in a bullet list inside the
documentation to explain each parameter, unless a parameter needs it
for a particular reason. In general, the stronger/stricter your
types/signatures are, and the better documented your types are, the
less "extra notes" in every function you need.

For instance, if you see `int` in a signature, then you very likely
need documentation to understand how the argument works because `int`
is way too general (e.g. it is likely it admits cases you are not
supposed to use). However, if you see `Duration`, then you already
know the answer to the units question.

Thus, in a way, we are factoring out documentation to a single place,
thus making them simpler/easier/lighter -- so you can see it as a way
to scale writing docs! :)

That is also why carrying as much information in the signature also
helps with docs, and not just with having the compiler catch mistakes
for us.

I hope this gives some context on why we are approaching it like this.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-02 12:37         ` Alice Ryhl
@ 2024-10-02 13:58           ` FUJITA Tomonori
  2024-10-02 14:27             ` Alice Ryhl
  0 siblings, 1 reply; 40+ messages in thread
From: FUJITA Tomonori @ 2024-10-02 13:58 UTC (permalink / raw)
  To: aliceryhl
  Cc: andrew, fujita.tomonori, netdev, rust-for-linux, hkallweit1,
	tmgross, ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin,
	a.hindborg

On Wed, 2 Oct 2024 14:37:55 +0200
Alice Ryhl <aliceryhl@google.com> wrote:

> On Wed, Oct 2, 2024 at 2:19 PM Andrew Lunn <andrew@lunn.ch> wrote:
>>
>> > > I would also document the units for the parameter. Is it picoseconds
>> > > or centuries?
>> >
>> > Rust's Duration is created from seconds and nanoseconds.
>>
>> How well know is that? And is there a rust-for-linux wide preference
>> to use Duration for time? Are we going to get into a situation that
>> some abstractions use Duration, others seconds, some milliseconds,
>> etc, just like C code?
>>
>> Anyway, i would still document the parameter is a Duration, since it
>> is different to how C fsleep() works.
> 
> I'm not necessarily convinced we want to use the Rust Duration type.
> Similar questions came up when I added the Ktime type. The Rust
> Duration type is rather large.

core::mem::size_of::<core::time::Duration>() says 16 bytes.

You prefer to add a simpler Duration structure to kernel/time.rs?
Something like:

struct Duration {
    nanos: u64,
}

u64 in nanoseconds is enough for delay in the kernel, I think.


btw, core::time::Duration::new() could panic if a driver does
something stupid; for example,

let d = core::time::Duration::new(u64::MAX, 1_000_000_000);

Is this acceptable?


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-02 13:58           ` FUJITA Tomonori
@ 2024-10-02 14:27             ` Alice Ryhl
  2024-10-02 14:40               ` FUJITA Tomonori
  0 siblings, 1 reply; 40+ messages in thread
From: Alice Ryhl @ 2024-10-02 14:27 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: andrew, netdev, rust-for-linux, hkallweit1, tmgross, ojeda,
	alex.gaynor, gary, bjorn3_gh, benno.lossin, a.hindborg

On Wed, Oct 2, 2024 at 3:58 PM FUJITA Tomonori
<fujita.tomonori@gmail.com> wrote:
>
> On Wed, 2 Oct 2024 14:37:55 +0200
> Alice Ryhl <aliceryhl@google.com> wrote:
>
> > On Wed, Oct 2, 2024 at 2:19 PM Andrew Lunn <andrew@lunn.ch> wrote:
> >>
> >> > > I would also document the units for the parameter. Is it picoseconds
> >> > > or centuries?
> >> >
> >> > Rust's Duration is created from seconds and nanoseconds.
> >>
> >> How well know is that? And is there a rust-for-linux wide preference
> >> to use Duration for time? Are we going to get into a situation that
> >> some abstractions use Duration, others seconds, some milliseconds,
> >> etc, just like C code?
> >>
> >> Anyway, i would still document the parameter is a Duration, since it
> >> is different to how C fsleep() works.
> >
> > I'm not necessarily convinced we want to use the Rust Duration type.
> > Similar questions came up when I added the Ktime type. The Rust
> > Duration type is rather large.
>
> core::mem::size_of::<core::time::Duration>() says 16 bytes.
>
> You prefer to add a simpler Duration structure to kernel/time.rs?
> Something like:
>
> struct Duration {
>     nanos: u64,
> }
>
> u64 in nanoseconds is enough for delay in the kernel, I think.

That type already exists. It's called kernel::time::Ktime.

Alice

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-02 14:27             ` Alice Ryhl
@ 2024-10-02 14:40               ` FUJITA Tomonori
  2024-10-02 14:52                 ` Miguel Ojeda
  0 siblings, 1 reply; 40+ messages in thread
From: FUJITA Tomonori @ 2024-10-02 14:40 UTC (permalink / raw)
  To: aliceryhl
  Cc: fujita.tomonori, andrew, netdev, rust-for-linux, hkallweit1,
	tmgross, ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin,
	a.hindborg

On Wed, 2 Oct 2024 16:27:17 +0200
Alice Ryhl <aliceryhl@google.com> wrote:

>> You prefer to add a simpler Duration structure to kernel/time.rs?
>> Something like:
>>
>> struct Duration {
>>     nanos: u64,
>> }
>>
>> u64 in nanoseconds is enough for delay in the kernel, I think.
> 
> That type already exists. It's called kernel::time::Ktime.

Sure. Some code use ktime_t to represent duration so using Ktime for
the delay functions makes sense. I'll add some methods to Ktime and
use it.

Thanks!

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-02 14:40               ` FUJITA Tomonori
@ 2024-10-02 14:52                 ` Miguel Ojeda
  2024-10-02 19:40                   ` Thomas Gleixner
  0 siblings, 1 reply; 40+ messages in thread
From: Miguel Ojeda @ 2024-10-02 14:52 UTC (permalink / raw)
  To: FUJITA Tomonori, Thomas Gleixner
  Cc: aliceryhl, andrew, netdev, rust-for-linux, hkallweit1, tmgross,
	ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin, a.hindborg

On Wed, Oct 2, 2024 at 4:40 PM FUJITA Tomonori
<fujita.tomonori@gmail.com> wrote:
>
> Sure. Some code use ktime_t to represent duration so using Ktime for
> the delay functions makes sense. I'll add some methods to Ktime and
> use it.

We really should still use different types to represent points and
deltas, even if internally they happen to end up using/being the
"same" thing.

If we start mixing those two up, then it will be harder to unravel later.

I think Thomas also wanted to have two types, please see this thread:
https://lore.kernel.org/rust-for-linux/87h6vfnh0f.ffs@tglx/ (we also
discussed clocks).

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-02 14:52                 ` Miguel Ojeda
@ 2024-10-02 19:40                   ` Thomas Gleixner
  2024-10-03  1:24                     ` FUJITA Tomonori
  0 siblings, 1 reply; 40+ messages in thread
From: Thomas Gleixner @ 2024-10-02 19:40 UTC (permalink / raw)
  To: Miguel Ojeda, FUJITA Tomonori
  Cc: aliceryhl, andrew, netdev, rust-for-linux, hkallweit1, tmgross,
	ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin, a.hindborg

On Wed, Oct 02 2024 at 16:52, Miguel Ojeda wrote:
> On Wed, Oct 2, 2024 at 4:40 PM FUJITA Tomonori
> <fujita.tomonori@gmail.com> wrote:
>>
>> Sure. Some code use ktime_t to represent duration so using Ktime for
>> the delay functions makes sense. I'll add some methods to Ktime and
>> use it.
>
> We really should still use different types to represent points and
> deltas, even if internally they happen to end up using/being the
> "same" thing.
>
> If we start mixing those two up, then it will be harder to unravel later.
>
> I think Thomas also wanted to have two types, please see this thread:
> https://lore.kernel.org/rust-for-linux/87h6vfnh0f.ffs@tglx/ (we also
> discussed clocks).

Correct. They are distinct.

Btw, why is this sent to netdev and not to LKML? delay is generic code
and has nothing to do with networking.

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-02 13:21             ` Miguel Ojeda
@ 2024-10-02 20:04               ` Thomas Gleixner
  0 siblings, 0 replies; 40+ messages in thread
From: Thomas Gleixner @ 2024-10-02 20:04 UTC (permalink / raw)
  To: Miguel Ojeda, Andrew Lunn
  Cc: FUJITA Tomonori, netdev, rust-for-linux, hkallweit1, tmgross,
	ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin, a.hindborg,
	aliceryhl, Anna-Maria Behnsen

On Wed, Oct 02 2024 at 15:21, Miguel Ojeda wrote:
> On Wed, Oct 2, 2024 at 2:51 PM Andrew Lunn <andrew@lunn.ch> wrote:
>> Maybe this is my background as a C programmer, with its sloppy type
>> system, but i prefer to have this very clear, maybe redundantly
>> stating it in words in addition to the signature.
>
> The second part of my message was about the signature point you made,
> i.e. not about the units. So I am not sure if you are asking here to
> re-state the types of parameters in every function's docs -- what do
> you gain from that in common cases?
>
> We also don't repeat every parameter in a bullet list inside the
> documentation to explain each parameter, unless a parameter needs it
> for a particular reason. In general, the stronger/stricter your
> types/signatures are, and the better documented your types are, the
> less "extra notes" in every function you need.
>
> For instance, if you see `int` in a signature, then you very likely
> need documentation to understand how the argument works because `int`
> is way too general (e.g. it is likely it admits cases you are not
> supposed to use). However, if you see `Duration`, then you already
> know the answer to the units question.
>
> Thus, in a way, we are factoring out documentation to a single place,
> thus making them simpler/easier/lighter -- so you can see it as a way
> to scale writing docs! :)
>
> That is also why carrying as much information in the signature also
> helps with docs, and not just with having the compiler catch mistakes
> for us.

I completely agree.

'delay(Duration d)' does not need explanation for @d unless there is a
restriction for the valid range of @d. @d is explained in the
documentation of Duration.

That's not any different in C, when the function argument is a pointer
to a complex struct. Nobody would even think about explaining the struct
members in the documentation of the function which has that struct
pointer argument. No, you need to go to the struct declaration to figure
it out.

Redundant documentation is actually bad, because any changes to the type
will inevitably lead to stale documentation at the usage site. The
kernel is full of this.

I havent's seen the actual patches as they were sent to netdev for
whatever reason. There is a larger rework of delay.h going on:

  https://lore.kernel.org/all/20240911-devel-anna-maria-b4-timers-flseep-v2-0-b0d3f33ccfe0@linutronix.de/

V3 will be coming early next week. So please look at V2 if you have any
constraints vs. the rust implementation.

Thanks,

        tglx



^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-02 19:40                   ` Thomas Gleixner
@ 2024-10-03  1:24                     ` FUJITA Tomonori
  2024-10-03 10:50                       ` Miguel Ojeda
  0 siblings, 1 reply; 40+ messages in thread
From: FUJITA Tomonori @ 2024-10-03  1:24 UTC (permalink / raw)
  To: tglx
  Cc: miguel.ojeda.sandonis, fujita.tomonori, aliceryhl, andrew, netdev,
	rust-for-linux, hkallweit1, tmgross, ojeda, alex.gaynor, gary,
	bjorn3_gh, benno.lossin, a.hindborg

On Wed, 02 Oct 2024 21:40:45 +0200
Thomas Gleixner <tglx@linutronix.de> wrote:

> On Wed, Oct 02 2024 at 16:52, Miguel Ojeda wrote:
>> On Wed, Oct 2, 2024 at 4:40 PM FUJITA Tomonori
>> <fujita.tomonori@gmail.com> wrote:
>>>
>>> Sure. Some code use ktime_t to represent duration so using Ktime for
>>> the delay functions makes sense. I'll add some methods to Ktime and
>>> use it.
>>
>> We really should still use different types to represent points and
>> deltas, even if internally they happen to end up using/being the
>> "same" thing.
>>
>> If we start mixing those two up, then it will be harder to unravel later.
>>
>> I think Thomas also wanted to have two types, please see this thread:
>> https://lore.kernel.org/rust-for-linux/87h6vfnh0f.ffs@tglx/ (we also
>> discussed clocks).
> 
> Correct. They are distinct.

Understood. I'll add a new type, time::Delta. Any alternative name
suggestions?

> Btw, why is this sent to netdev and not to LKML? delay is generic code
> and has nothing to do with networking.

Rust abstractions are typically merged with their users. I'm trying to
push the delay abstractions with a fix for QT2025 PHY driver
(drivers/net/phy/qt2025.rs), which uses delay.

Sorry, I'll send v2 to timers maintainers too.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready
  2024-10-02 12:31         ` Andrew Lunn
@ 2024-10-03  5:07           ` FUJITA Tomonori
  0 siblings, 0 replies; 40+ messages in thread
From: FUJITA Tomonori @ 2024-10-03  5:07 UTC (permalink / raw)
  To: andrew
  Cc: fujita.tomonori, aliceryhl, netdev, rust-for-linux, hkallweit1,
	tmgross, ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin,
	a.hindborg

On Wed, 2 Oct 2024 14:31:07 +0200
Andrew Lunn <andrew@lunn.ch> wrote:

> There are some subtleties involved with PHYs, which is why we have our
> own wrapper around the macros in iopoll.h:
> 
> https://elixir.bootlin.com/linux/v6.11.1/source/include/linux/phy.h#L1288
> 
> Normally an IO operation cannot fail. But PHYs are different, a read
> could return -EOPNOTSUPP, -EIO, -ETIMEDOUT etc. That needs to be take
> into account and checked before evaluating the condition.

Thanks, I didn't know this function. I think that a generic
read_poll_timeout in Rust can handle such case.

#define read_poll_timeout(op, val, cond, sleep_us, timeout_us, \
				sleep_before_read, args...) \
({ \
	u64 __timeout_us = (timeout_us); \
	unsigned long __sleep_us = (sleep_us); \
	ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
	might_sleep_if((__sleep_us) != 0); \
	if (sleep_before_read && __sleep_us) \
		usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
	for (;;) { \
		(val) = op(args); \
		if (cond) \
			break; \

The reason why the C version cannot handle such case is that after
call `op` function, read_poll_timeout macro can't know whether `val`
is an error or not.

In Rust version, 'op' function can return Result type, explicitly
tells success or an error. It can return an error before evaluating
the condition.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-03  1:24                     ` FUJITA Tomonori
@ 2024-10-03 10:50                       ` Miguel Ojeda
  2024-10-03 12:33                         ` Andrew Lunn
  0 siblings, 1 reply; 40+ messages in thread
From: Miguel Ojeda @ 2024-10-03 10:50 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: tglx, aliceryhl, andrew, netdev, rust-for-linux, hkallweit1,
	tmgross, ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin,
	a.hindborg

On Thu, Oct 3, 2024 at 3:24 AM FUJITA Tomonori
<fujita.tomonori@gmail.com> wrote:
>
> Rust abstractions are typically merged with their users. I'm trying to
> push the delay abstractions with a fix for QT2025 PHY driver
> (drivers/net/phy/qt2025.rs), which uses delay.

To clarify, in case it helps: users indeed drive the need for
abstractions (i.e. we don't merge abstractions without an expected
user), and it can happen that they go together in the same patch
series for convenience, that is true.

However, I don't think I would say "typically", since most
abstractions went in on their own so far, and each patch still needs
to Cc the relevant maintainers/lists and the respective maintainers
should say they are OK moving it through another tree.

In other words, the "default" is that the abstractions go through
their tree, i.e. delay wouldn't go through netdev, unless the
maintainers are OK with that (e.g. perhaps because it is simpler in a
given case).

I have some more notes at
https://rust-for-linux.com/contributing#the-rust-subsystem.

Of course, in most cases to review abstractions it helps seeing the
expected user, so sometimes it may help to show the users in the same
patch series, and sometimes it may make more sense to just add a link
to Lore to the user, or to a branch; and sometimes examples in the
commit message or in the abstractions' docs themselves are enough.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: iopoll abstraction
  2024-10-02  9:56         ` iopoll abstraction FUJITA Tomonori
@ 2024-10-03 11:52           ` Boqun Feng
  2024-10-03 13:45             ` FUJITA Tomonori
  0 siblings, 1 reply; 40+ messages in thread
From: Boqun Feng @ 2024-10-03 11:52 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: dirk.behme, andrew, aliceryhl, netdev, rust-for-linux, hkallweit1,
	tmgross, ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin,
	a.hindborg

On Wed, Oct 02, 2024 at 09:56:36AM +0000, FUJITA Tomonori wrote:
> On Wed, 2 Oct 2024 06:39:48 +0200
> Dirk Behme <dirk.behme@de.bosch.com> wrote:
> 
> >> I generally point developers at iopoll.h, because developers nearly
> >> always get this sort of polling for something to happen wrong.
> >> The kernel sleep functions guarantee the minimum sleep time. They say
> >> nothing about the maximum sleep time. You can ask it to sleep for 1ms,
> >> and in reality, due to something stealing the CPU and not being RT
> >> friendly, it actually sleeps for 10ms. This extra long sleep time
> >> blows straight past your timeout, if you have a time based timeout.
> >> What most developers do is after the sleep() returns they check to see
> >> if the timeout has been reached and then exit with -ETIMEDOUT. They
> >> don't check the state of the hardware, which given its had a long time
> >> to do its thing, probably is now in a good state. But the function
> >> returns -ETIMEDOUT.
> >> There should always be a check of the hardware state after the sleep,
> >> in order to determine ETIMEDOUT vs 0.
> >> As i said, most C developers get this wrong. So i don't really see why
> >> Rust developers also will not get this wrong. So i like to discourage
> >> this sort of code, and have Rust implementations of iopoll.h.
> > 
> > 
> > Do we talk about some simple Rust wrappers for the macros in iopoll.h?
> > E.g. something like [1]?
> > 
> > Or are we talking about some more complex (safety) dependencies which
> > need some more complex abstraction handling?
> 
> (snip)
> 
> > int rust_helper_readb_poll_timeout(const volatile void * addr,
> >                                   u64 val, u64 cond, u64 delay_us,
> >                                   u64 timeout_us)
> > {
> >        return readb_poll_timeout(addr, val, cond, delay_us, timeout_us);
> > }
> 
> I'm not sure a simple wrapper for iopoll.h works. We need to pass a
> function. I'm testing a macro like the following (not added ktime
> timeout yet):

You could use closure as a parameter to avoid macro interface, something
like:

	fn read_poll_timeout<Op, Cond, T>(
	    op: Op,
	    cond: Cond,
	    sleep: Delta,
	    timeout: Delta,
	) -> Result<T> where
	    Op: Fn() -> T,
	    cond: Fn() -> bool {

	    let __timeout = kernel::Ktime::ktime_get() + timeout;

	    let val = loop {
		let val = op();
		if cond() {
		    break Some(val);
		}
		kernel::delay::sleep(sleep);

		if __timeout.after(kernel::Ktime::ktime_get()) {
		    break None;
		}
	    };

	    if cond() {
		val
	    } else {
		Err(kernel::error::code::ETIMEDOUT)
	    }
	}

note that you don't need the args part, because `op` is a closure that
can capature value, so for example, if in C code you need to call foo(a,
b), with closure, you can do:

	<a and b are defined in the caller>
	read_poll_timeout(|| { foo(a, b) }, ...);

with above API.

Regards,
Boqun

> 
> macro_rules! read_poll_timeout {
>     ($op:expr, $val:expr, $cond:expr, $sleep:expr, $timeout:expr, $($args:expr),*) => {{
>         let _ = $val;
>         loop {
>             $val = $op($($args),*);
>             if $cond {
>                 break;
>             }
>             kernel::delay::sleep($sleep);
>         }
>         if $cond {
>             Ok(())
>         } else {
>             Err(kernel::error::code::ETIMEDOUT)
>         }
>     }};
> }
> 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-03 10:50                       ` Miguel Ojeda
@ 2024-10-03 12:33                         ` Andrew Lunn
  0 siblings, 0 replies; 40+ messages in thread
From: Andrew Lunn @ 2024-10-03 12:33 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: FUJITA Tomonori, tglx, aliceryhl, netdev, rust-for-linux,
	hkallweit1, tmgross, ojeda, alex.gaynor, gary, bjorn3_gh,
	benno.lossin, a.hindborg

On Thu, Oct 03, 2024 at 12:50:51PM +0200, Miguel Ojeda wrote:
> On Thu, Oct 3, 2024 at 3:24 AM FUJITA Tomonori
> <fujita.tomonori@gmail.com> wrote:
> >
> > Rust abstractions are typically merged with their users. I'm trying to
> > push the delay abstractions with a fix for QT2025 PHY driver
> > (drivers/net/phy/qt2025.rs), which uses delay.
> 
> To clarify, in case it helps: users indeed drive the need for
> abstractions (i.e. we don't merge abstractions without an expected
> user), and it can happen that they go together in the same patch
> series for convenience, that is true.
> 
> However, I don't think I would say "typically", since most
> abstractions went in on their own so far

Looking at the kernel as a whole, i would say that is actually
atypical. Rust is being somewhat special here. But it also seems to be
agreed on that this is O.K.

> In other words, the "default" is that the abstractions go through
> their tree, i.e. delay wouldn't go through netdev, unless the
> maintainers are OK with that (e.g. perhaps because it is simpler in a
> given case).

In this case, the fdelay() binding should be simple enough that i
think we can use the normal mechanism of merging it via netdev, so
long as the other subsystem Maintainer gives an Acked-by: But we can
also pull a stable branch into netdev if we need to.

A Rust equivalent of iopoll.h is going to be a bit more interesting.

./scripts/get_maintainer.pl -f include/linux/iopoll.h 
linux-kernel@vger.kernel.org (open list)

i.e. it does not have a Maintainer!

Looking at the Acked-by:s i would keep Arnd Bergmann <arnd@arndb.de>
in the loop.

	Andrew

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: iopoll abstraction
  2024-10-03 11:52           ` Boqun Feng
@ 2024-10-03 13:45             ` FUJITA Tomonori
  2024-10-03 14:25               ` Boqun Feng
  0 siblings, 1 reply; 40+ messages in thread
From: FUJITA Tomonori @ 2024-10-03 13:45 UTC (permalink / raw)
  To: boqun.feng
  Cc: fujita.tomonori, dirk.behme, andrew, aliceryhl, netdev,
	rust-for-linux, hkallweit1, tmgross, ojeda, alex.gaynor, gary,
	bjorn3_gh, benno.lossin, a.hindborg

On Thu, 3 Oct 2024 04:52:48 -0700
Boqun Feng <boqun.feng@gmail.com> wrote:

> You could use closure as a parameter to avoid macro interface, something
> like:
> 
> 	fn read_poll_timeout<Op, Cond, T>(
> 	    op: Op,
> 	    cond: Cond,
> 	    sleep: Delta,
> 	    timeout: Delta,
> 	) -> Result<T> where
> 	    Op: Fn() -> T,
> 	    cond: Fn() -> bool {
> 
> 	    let __timeout = kernel::Ktime::ktime_get() + timeout;
> 
> 	    let val = loop {
> 		let val = op();
> 		if cond() {
> 		    break Some(val);
> 		}
> 		kernel::delay::sleep(sleep);
> 
> 		if __timeout.after(kernel::Ktime::ktime_get()) {
> 		    break None;
> 		}
> 	    };
> 
> 	    if cond() {
> 		val
> 	    } else {
> 		Err(kernel::error::code::ETIMEDOUT)
> 	    }
> 	}

Great! I changed couple of things.

1. Op typically reads a value from a register and could need mut objects. So I use FnMut.
2. reading from hardware could fail so Op had better to return an error [1].
3. Cond needs val; typically check the value from a register.

[1] https://lore.kernel.org/netdev/ec7267b5-ae77-4c4a-94f8-aa933c87a9a2@lunn.ch

Seems that the following works QT2025 driver. How does it look?

fn read_poll_timeout<Op, Cond, T: Copy>(
    mut op: Op,
    cond: Cond,
    sleep: Delta,
    timeout: Delta,
) -> Result<T>
where
    Op: FnMut() -> Result<T>,
    Cond: Fn(T) -> bool,
{
    let timeout = Ktime::ktime_get() + timeout;
    let ret = loop {
        let val = op()?;
        if cond(val) {
            break Ok(val);
        }
        kernel::delay::sleep(sleep);

        if Ktime::ktime_get() > timeout {
            break Err(code::ETIMEDOUT);
        }
    };

    ret
}

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: iopoll abstraction
  2024-10-03 13:45             ` FUJITA Tomonori
@ 2024-10-03 14:25               ` Boqun Feng
  2024-10-03 16:00                 ` Andrew Lunn
  2024-10-03 16:09                 ` Andrew Lunn
  0 siblings, 2 replies; 40+ messages in thread
From: Boqun Feng @ 2024-10-03 14:25 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: dirk.behme, andrew, aliceryhl, netdev, rust-for-linux, hkallweit1,
	tmgross, ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin,
	a.hindborg

On Thu, Oct 03, 2024 at 01:45:18PM +0000, FUJITA Tomonori wrote:
> On Thu, 3 Oct 2024 04:52:48 -0700
> Boqun Feng <boqun.feng@gmail.com> wrote:
> 
> > You could use closure as a parameter to avoid macro interface, something
> > like:
> > 
> > 	fn read_poll_timeout<Op, Cond, T>(
> > 	    op: Op,
> > 	    cond: Cond,
> > 	    sleep: Delta,
> > 	    timeout: Delta,
> > 	) -> Result<T> where
> > 	    Op: Fn() -> T,
> > 	    cond: Fn() -> bool {
> > 
> > 	    let __timeout = kernel::Ktime::ktime_get() + timeout;
> > 
> > 	    let val = loop {
> > 		let val = op();
> > 		if cond() {
> > 		    break Some(val);
> > 		}
> > 		kernel::delay::sleep(sleep);
> > 
> > 		if __timeout.after(kernel::Ktime::ktime_get()) {
> > 		    break None;
> > 		}
> > 	    };
> > 
> > 	    if cond() {
> > 		val
> > 	    } else {
> > 		Err(kernel::error::code::ETIMEDOUT)
> > 	    }
> > 	}
> 
> Great! I changed couple of things.
> 
> 1. Op typically reads a value from a register and could need mut objects. So I use FnMut.
> 2. reading from hardware could fail so Op had better to return an error [1].
> 3. Cond needs val; typically check the value from a register.
> 
> [1] https://lore.kernel.org/netdev/ec7267b5-ae77-4c4a-94f8-aa933c87a9a2@lunn.ch
> 
> Seems that the following works QT2025 driver. How does it look?
> 

Makes sense to me. Of course, more users will probably tell us whether
we cover all the cases, but this is a good starting point. I would put
the function at kernel::io::poll, but that's my personal preference ;-)

Regards,
Boqun

> fn read_poll_timeout<Op, Cond, T: Copy>(
>     mut op: Op,
>     cond: Cond,
>     sleep: Delta,
>     timeout: Delta,
> ) -> Result<T>
> where
>     Op: FnMut() -> Result<T>,
>     Cond: Fn(T) -> bool,
> {
>     let timeout = Ktime::ktime_get() + timeout;
>     let ret = loop {
>         let val = op()?;
>         if cond(val) {
>             break Ok(val);
>         }
>         kernel::delay::sleep(sleep);
> 
>         if Ktime::ktime_get() > timeout {
>             break Err(code::ETIMEDOUT);
>         }
>     };
> 
>     ret
> }

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: iopoll abstraction
  2024-10-03 14:25               ` Boqun Feng
@ 2024-10-03 16:00                 ` Andrew Lunn
  2024-10-04 11:54                   ` FUJITA Tomonori
  2024-10-03 16:09                 ` Andrew Lunn
  1 sibling, 1 reply; 40+ messages in thread
From: Andrew Lunn @ 2024-10-03 16:00 UTC (permalink / raw)
  To: Boqun Feng
  Cc: FUJITA Tomonori, dirk.behme, aliceryhl, netdev, rust-for-linux,
	hkallweit1, tmgross, ojeda, alex.gaynor, gary, bjorn3_gh,
	benno.lossin, a.hindborg

> > fn read_poll_timeout<Op, Cond, T: Copy>(
> >     mut op: Op,
> >     cond: Cond,
> >     sleep: Delta,
> >     timeout: Delta,
> > ) -> Result<T>
> > where
> >     Op: FnMut() -> Result<T>,
> >     Cond: Fn(T) -> bool,
> > {
> >     let timeout = Ktime::ktime_get() + timeout;
> >     let ret = loop {
> >         let val = op()?;
> >         if cond(val) {
> >             break Ok(val);
> >         }
> >         kernel::delay::sleep(sleep);
> > 
> >         if Ktime::ktime_get() > timeout {
> >             break Err(code::ETIMEDOUT);
> >         }
> >     };
> > 
> >     ret
> > }

This appears to have the usual bug when people implement it themselves
and i then point them at iopoll.h, which so far as been bug free.

kernel::delay::sleep(sleep) can sleep for an arbitrary amount of time
greater than sleep, if the system is busy doing other things. You
might only get around this loop once, and exit with ETIMEOUT, but
while you have been sleeping a long time the hardware has completed
its operation, but you never check.

There must be a call to cond() after the timeout to handle this
condition.

And this is not theoretical. I had a very reproducible case of this
during the boot of a device. It is less likely today, with SMP
systems, and all the RT patches, but if it does happen, it will be
very hard to track down.

	Andrew

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: iopoll abstraction
  2024-10-03 14:25               ` Boqun Feng
  2024-10-03 16:00                 ` Andrew Lunn
@ 2024-10-03 16:09                 ` Andrew Lunn
  2024-10-04 11:48                   ` FUJITA Tomonori
  1 sibling, 1 reply; 40+ messages in thread
From: Andrew Lunn @ 2024-10-03 16:09 UTC (permalink / raw)
  To: Boqun Feng
  Cc: FUJITA Tomonori, dirk.behme, aliceryhl, netdev, rust-for-linux,
	hkallweit1, tmgross, ojeda, alex.gaynor, gary, bjorn3_gh,
	benno.lossin, a.hindborg

> we cover all the cases, but this is a good starting point. I would put
> the function at kernel::io::poll, but that's my personal preference ;-)

iopoll.h has a few variants. The variant being implemented here can
only be used in thread context where it can sleep. There is also
read_poll_timeout_atomic() which can be used in atomic context, which
uses udelay() rather than sleeping, since you are not allowed to sleep
in atomic context.

So we should keep the naming open to allow for the atomic variant
sometime in the future.

We probably also want a comment that this helper cannot be used in
atomic context.

Do we have a Rust equivalent of might_sleep()?

https://elixir.bootlin.com/linux/v6.12-rc1/source/include/linux/kernel.h#L93

	Andrew

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: iopoll abstraction
  2024-10-03 16:09                 ` Andrew Lunn
@ 2024-10-04 11:48                   ` FUJITA Tomonori
  2024-10-04 13:37                     ` Andrew Lunn
  0 siblings, 1 reply; 40+ messages in thread
From: FUJITA Tomonori @ 2024-10-04 11:48 UTC (permalink / raw)
  To: andrew
  Cc: boqun.feng, fujita.tomonori, dirk.behme, aliceryhl, netdev,
	rust-for-linux, hkallweit1, tmgross, ojeda, alex.gaynor, gary,
	bjorn3_gh, benno.lossin, a.hindborg

On Thu, 3 Oct 2024 18:09:15 +0200
Andrew Lunn <andrew@lunn.ch> wrote:

> We probably also want a comment that this helper cannot be used in
> atomic context.

Yeah, I'll add such.

> Do we have a Rust equivalent of might_sleep()?
> 
> https://elixir.bootlin.com/linux/v6.12-rc1/source/include/linux/kernel.h#L93

No. I'll add bindings for might_sleep() and cpu_relax().

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: iopoll abstraction
  2024-10-03 16:00                 ` Andrew Lunn
@ 2024-10-04 11:54                   ` FUJITA Tomonori
  0 siblings, 0 replies; 40+ messages in thread
From: FUJITA Tomonori @ 2024-10-04 11:54 UTC (permalink / raw)
  To: andrew
  Cc: boqun.feng, fujita.tomonori, dirk.behme, aliceryhl, netdev,
	rust-for-linux, hkallweit1, tmgross, ojeda, alex.gaynor, gary,
	bjorn3_gh, benno.lossin, a.hindborg

On Thu, 3 Oct 2024 18:00:36 +0200
Andrew Lunn <andrew@lunn.ch> wrote:

>> > fn read_poll_timeout<Op, Cond, T: Copy>(
>> >     mut op: Op,
>> >     cond: Cond,
>> >     sleep: Delta,
>> >     timeout: Delta,
>> > ) -> Result<T>
>> > where
>> >     Op: FnMut() -> Result<T>,
>> >     Cond: Fn(T) -> bool,
>> > {
>> >     let timeout = Ktime::ktime_get() + timeout;
>> >     let ret = loop {
>> >         let val = op()?;
>> >         if cond(val) {
>> >             break Ok(val);
>> >         }
>> >         kernel::delay::sleep(sleep);
>> > 
>> >         if Ktime::ktime_get() > timeout {
>> >             break Err(code::ETIMEDOUT);
>> >         }
>> >     };
>> > 
>> >     ret
>> > }
> 
> This appears to have the usual bug when people implement it themselves
> and i then point them at iopoll.h, which so far as been bug free.

Ah, in the next submission, I'll try to ensure that the Rust version
works the same way as the C version.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-01 12:31   ` Andrew Lunn
  2024-10-01 15:08     ` Miguel Ojeda
  2024-10-02 11:34     ` FUJITA Tomonori
@ 2024-10-04 12:08     ` FUJITA Tomonori
  2024-10-04 14:08       ` Andrew Lunn
  2 siblings, 1 reply; 40+ messages in thread
From: FUJITA Tomonori @ 2024-10-04 12:08 UTC (permalink / raw)
  To: andrew
  Cc: fujita.tomonori, netdev, rust-for-linux, hkallweit1, tmgross,
	ojeda, alex.gaynor, gary, bjorn3_gh, benno.lossin, a.hindborg,
	aliceryhl

On Tue, 1 Oct 2024 14:31:39 +0200
Andrew Lunn <andrew@lunn.ch> wrote:

>> +/// Sleeps for a given duration.
>> +///
>> +/// Equivalent to the kernel's [`fsleep`] function, internally calls `udelay`,
>> +/// `usleep_range`, or `msleep`.
> 
> Is it possible to cross reference
> Documentation/timers/timers-howto.rst ?  fsleep() points to it, so it
> would e good if the Rust version also did.

Looks like the pointer to Documentation/timers/timers-howto.rst in
fsleep will be removed soon.

https://lore.kernel.org/all/20240911-devel-anna-maria-b4-timers-flseep-v2-0-b0d3f33ccfe0@linutronix.de/

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: iopoll abstraction
  2024-10-04 11:48                   ` FUJITA Tomonori
@ 2024-10-04 13:37                     ` Andrew Lunn
  0 siblings, 0 replies; 40+ messages in thread
From: Andrew Lunn @ 2024-10-04 13:37 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: boqun.feng, dirk.behme, aliceryhl, netdev, rust-for-linux,
	hkallweit1, tmgross, ojeda, alex.gaynor, gary, bjorn3_gh,
	benno.lossin, a.hindborg

On Fri, Oct 04, 2024 at 08:48:03PM +0900, FUJITA Tomonori wrote:
> On Thu, 3 Oct 2024 18:09:15 +0200
> Andrew Lunn <andrew@lunn.ch> wrote:
> 
> > We probably also want a comment that this helper cannot be used in
> > atomic context.
> 
> Yeah, I'll add such.
> 
> > Do we have a Rust equivalent of might_sleep()?
> > 
> > https://elixir.bootlin.com/linux/v6.12-rc1/source/include/linux/kernel.h#L93
> 
> No. I'll add bindings for might_sleep() and cpu_relax().

Please make sure you involve the scheduler people. This is now well
outside of networking, same as the discussion around time has little
to do with networking.

The might_sleep() is not a strong requirement for iopoll, so you might
want to get the basic functionality merged first, and then once
might_sleep() is agreed on, add it to iopoll. It is just a debug
feature.

	Andrew

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH net-next v1 1/2] rust: add delay abstraction
  2024-10-04 12:08     ` FUJITA Tomonori
@ 2024-10-04 14:08       ` Andrew Lunn
  0 siblings, 0 replies; 40+ messages in thread
From: Andrew Lunn @ 2024-10-04 14:08 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: netdev, rust-for-linux, hkallweit1, tmgross, ojeda, alex.gaynor,
	gary, bjorn3_gh, benno.lossin, a.hindborg, aliceryhl

On Fri, Oct 04, 2024 at 09:08:19PM +0900, FUJITA Tomonori wrote:
> On Tue, 1 Oct 2024 14:31:39 +0200
> Andrew Lunn <andrew@lunn.ch> wrote:
> 
> >> +/// Sleeps for a given duration.
> >> +///
> >> +/// Equivalent to the kernel's [`fsleep`] function, internally calls `udelay`,
> >> +/// `usleep_range`, or `msleep`.
> > 
> > Is it possible to cross reference
> > Documentation/timers/timers-howto.rst ?  fsleep() points to it, so it
> > would e good if the Rust version also did.
> 
> Looks like the pointer to Documentation/timers/timers-howto.rst in
> fsleep will be removed soon.
> 
> https://lore.kernel.org/all/20240911-devel-anna-maria-b4-timers-flseep-v2-0-b0d3f33ccfe0@linutronix.de/

It would be more accurate to say it gets replaced with a new document:

Documentation/timers/delay_sleep_functions.rst

So please reference that.

	Andrew

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2024-10-04 14:08 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-01 11:25 [PATCH net-next v1 0/2] add delay abstraction (sleep functions) FUJITA Tomonori
2024-10-01 11:25 ` [PATCH net-next v1 1/2] rust: add delay abstraction FUJITA Tomonori
2024-10-01 11:33   ` Alice Ryhl
2024-10-01 12:31   ` Andrew Lunn
2024-10-01 15:08     ` Miguel Ojeda
2024-10-02 11:34     ` FUJITA Tomonori
2024-10-02 12:18       ` Andrew Lunn
2024-10-02 12:35         ` Miguel Ojeda
2024-10-02 12:51           ` Andrew Lunn
2024-10-02 13:21             ` Miguel Ojeda
2024-10-02 20:04               ` Thomas Gleixner
2024-10-02 12:37         ` Alice Ryhl
2024-10-02 13:58           ` FUJITA Tomonori
2024-10-02 14:27             ` Alice Ryhl
2024-10-02 14:40               ` FUJITA Tomonori
2024-10-02 14:52                 ` Miguel Ojeda
2024-10-02 19:40                   ` Thomas Gleixner
2024-10-03  1:24                     ` FUJITA Tomonori
2024-10-03 10:50                       ` Miguel Ojeda
2024-10-03 12:33                         ` Andrew Lunn
2024-10-04 12:08     ` FUJITA Tomonori
2024-10-04 14:08       ` Andrew Lunn
2024-10-01 11:25 ` [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready FUJITA Tomonori
2024-10-01 11:36   ` Alice Ryhl
2024-10-01 12:48     ` Andrew Lunn
2024-10-02  4:39       ` iopoll abstraction (was: Re: [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready) Dirk Behme
2024-10-02  9:56         ` iopoll abstraction FUJITA Tomonori
2024-10-03 11:52           ` Boqun Feng
2024-10-03 13:45             ` FUJITA Tomonori
2024-10-03 14:25               ` Boqun Feng
2024-10-03 16:00                 ` Andrew Lunn
2024-10-04 11:54                   ` FUJITA Tomonori
2024-10-03 16:09                 ` Andrew Lunn
2024-10-04 11:48                   ` FUJITA Tomonori
2024-10-04 13:37                     ` Andrew Lunn
2024-10-02 10:13       ` [PATCH net-next v1 2/2] net: phy: qt2025: wait until PHY becomes ready FUJITA Tomonori
2024-10-02 12:31         ` Andrew Lunn
2024-10-03  5:07           ` FUJITA Tomonori
2024-10-02 11:17     ` FUJITA Tomonori
2024-10-01 11:39 ` [PATCH net-next v1 0/2] add delay abstraction (sleep functions) Alice Ryhl

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).