diff mbox series

[net-next,v2,2/6] rust: net::phy support probe callback

Message ID 20240731042136.201327-3-fujita.tomonori@gmail.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series net: phy: add Applied Micro QT2025 PHY driver | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 7 this patch: 7
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers warning 7 maintainers not CCed: aliceryhl@google.com alex.gaynor@gmail.com boqun.feng@gmail.com gary@garyguo.net a.hindborg@samsung.com bjorn3_gh@protonmail.com wedsonaf@gmail.com
netdev/build_clang success Errors and warnings before: 7 this patch: 7
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 7 this patch: 7
netdev/checkpatch warning WARNING: line length of 83 exceeds 80 columns WARNING: line length of 96 exceeds 80 columns
netdev/build_clang_rust fail Link
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-07-31--12-00 (tests: 707)

Commit Message

FUJITA Tomonori July 31, 2024, 4:21 a.m. UTC
Support phy_driver probe callback, used to set up device-specific
structures.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
 rust/kernel/net/phy.rs | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

Comments

Alice Ryhl July 31, 2024, 8:33 a.m. UTC | #1
On Wed, Jul 31, 2024 at 6:22 AM FUJITA Tomonori
<fujita.tomonori@gmail.com> wrote:
>
> Support phy_driver probe callback, used to set up device-specific
> structures.
>
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Andrew Lunn July 31, 2024, 12:24 p.m. UTC | #2
On Wed, Jul 31, 2024 at 01:21:32PM +0900, FUJITA Tomonori wrote:
> Support phy_driver probe callback, used to set up device-specific
> structures.
> 
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
> ---
>  rust/kernel/net/phy.rs | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
> 
> diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs
> index fd40b703d224..99a142348a34 100644
> --- a/rust/kernel/net/phy.rs
> +++ b/rust/kernel/net/phy.rs
> @@ -338,6 +338,20 @@ impl<T: Driver> Adapter<T> {
>          })
>      }
>  
> +    /// # Safety
> +    ///
> +    /// `phydev` must be passed by the corresponding callback in `phy_driver`.
> +    unsafe extern "C" fn probe_callback(phydev: *mut bindings::phy_device) -> core::ffi::c_int {
> +        from_result(|| {
> +            // SAFETY: This callback is called only in contexts
> +            // where we can exclusively access to `phy_device`, so the accessors on
> +            // `Device` are okay to call.

This one is slightly different to other callbacks. probe is called
without the mutex. Instead, probe is called before the device is
published. So the comment is correct, but given how important Rust
people take these SAFETY comments, maybe it should indicate it is
different to others?

	Andrew
Alice Ryhl July 31, 2024, 12:32 p.m. UTC | #3
On Wed, Jul 31, 2024 at 2:24 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Wed, Jul 31, 2024 at 01:21:32PM +0900, FUJITA Tomonori wrote:
> > Support phy_driver probe callback, used to set up device-specific
> > structures.
> >
> > Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
> > ---
> >  rust/kernel/net/phy.rs | 24 ++++++++++++++++++++++++
> >  1 file changed, 24 insertions(+)
> >
> > diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs
> > index fd40b703d224..99a142348a34 100644
> > --- a/rust/kernel/net/phy.rs
> > +++ b/rust/kernel/net/phy.rs
> > @@ -338,6 +338,20 @@ impl<T: Driver> Adapter<T> {
> >          })
> >      }
> >
> > +    /// # Safety
> > +    ///
> > +    /// `phydev` must be passed by the corresponding callback in `phy_driver`.
> > +    unsafe extern "C" fn probe_callback(phydev: *mut bindings::phy_device) -> core::ffi::c_int {
> > +        from_result(|| {
> > +            // SAFETY: This callback is called only in contexts
> > +            // where we can exclusively access to `phy_device`, so the accessors on
> > +            // `Device` are okay to call.
>
> This one is slightly different to other callbacks. probe is called
> without the mutex. Instead, probe is called before the device is
> published. So the comment is correct, but given how important Rust
> people take these SAFETY comments, maybe it should indicate it is
> different to others?

Interesting. Given that we don't hold the mutex, does that mean that
some of the methods on Device are not safe to call in this context? Or
is there something else that makes it okay to call them despite not
holding the mutex?

Alice
Andrew Lunn July 31, 2024, 8:57 p.m. UTC | #4
> > > +    /// `phydev` must be passed by the corresponding callback in `phy_driver`.
> > > +    unsafe extern "C" fn probe_callback(phydev: *mut bindings::phy_device) -> core::ffi::c_int {
> > > +        from_result(|| {
> > > +            // SAFETY: This callback is called only in contexts
> > > +            // where we can exclusively access to `phy_device`, so the accessors on
> > > +            // `Device` are okay to call.
> >
> > This one is slightly different to other callbacks. probe is called
> > without the mutex. Instead, probe is called before the device is
> > published. So the comment is correct, but given how important Rust
> > people take these SAFETY comments, maybe it should indicate it is
> > different to others?
> 
> Interesting. Given that we don't hold the mutex, does that mean that
> some of the methods on Device are not safe to call in this context? Or
> is there something else that makes it okay to call them despite not
> holding the mutex?

probe is always the first method called on a device driver to match it
to a device. Traditionally, if probe fails, the device is destroyed,
since there is no driver to drive it. probe needs to complete
successfully before the phy_device structure is published so a MAC
driver can reference it. If it is not published, nothing can have
access to it, so you don't need to worry about parallel activities on
it.

And a PHY driver does not need a probe function. Historically, probe
was all about, can this driver drive this hardware. However, since we
have ID registers in the hardware, we already know the driver can
drive the hardware. So probe is now about setting up whatever needs
setting up. For PHY drivers, there is often nothing, no local state
needed, etc. So the probe is optional.

	Andrew
FUJITA Tomonori Aug. 1, 2024, 12:17 a.m. UTC | #5
Thanks for the review!

On Wed, 31 Jul 2024 14:32:18 +0200
Alice Ryhl <aliceryhl@google.com> wrote:

>> > +    /// # Safety
>> > +    ///
>> > +    /// `phydev` must be passed by the corresponding callback in `phy_driver`.
>> > +    unsafe extern "C" fn probe_callback(phydev: *mut bindings::phy_device) -> core::ffi::c_int {
>> > +        from_result(|| {
>> > +            // SAFETY: This callback is called only in contexts
>> > +            // where we can exclusively access to `phy_device`, so the accessors on
>> > +            // `Device` are okay to call.
>>
>> This one is slightly different to other callbacks. probe is called
>> without the mutex. Instead, probe is called before the device is
>> published. So the comment is correct, but given how important Rust
>> people take these SAFETY comments, maybe it should indicate it is
>> different to others?
> 
> Interesting. Given that we don't hold the mutex, does that mean that
> some of the methods on Device are not safe to call in this context? Or
> is there something else that makes it okay to call them despite not
> holding the mutex?

Before the callback, the device object was initialized properly by
PHYLIB and no concurrent access so all the methods can be called
safely (no kernel panic), I think.

If the safety comment needs to updated, how about the following?

SAFETY: This callback is called only in contexts where we can
exclusively access to `phy_device` because it's not published yet, so
the accessors on `Device` are okay to call.
Alice Ryhl Aug. 1, 2024, 9:07 a.m. UTC | #6
On Thu, Aug 1, 2024 at 2:17 AM FUJITA Tomonori
<fujita.tomonori@gmail.com> wrote:
>
> Thanks for the review!
>
> On Wed, 31 Jul 2024 14:32:18 +0200
> Alice Ryhl <aliceryhl@google.com> wrote:
>
> >> > +    /// # Safety
> >> > +    ///
> >> > +    /// `phydev` must be passed by the corresponding callback in `phy_driver`.
> >> > +    unsafe extern "C" fn probe_callback(phydev: *mut bindings::phy_device) -> core::ffi::c_int {
> >> > +        from_result(|| {
> >> > +            // SAFETY: This callback is called only in contexts
> >> > +            // where we can exclusively access to `phy_device`, so the accessors on
> >> > +            // `Device` are okay to call.
> >>
> >> This one is slightly different to other callbacks. probe is called
> >> without the mutex. Instead, probe is called before the device is
> >> published. So the comment is correct, but given how important Rust
> >> people take these SAFETY comments, maybe it should indicate it is
> >> different to others?
> >
> > Interesting. Given that we don't hold the mutex, does that mean that
> > some of the methods on Device are not safe to call in this context? Or
> > is there something else that makes it okay to call them despite not
> > holding the mutex?
>
> Before the callback, the device object was initialized properly by
> PHYLIB and no concurrent access so all the methods can be called
> safely (no kernel panic), I think.
>
> If the safety comment needs to updated, how about the following?
>
> SAFETY: This callback is called only in contexts where we can
> exclusively access to `phy_device` because it's not published yet, so
> the accessors on `Device` are okay to call.

Yes, that sounds good to me. With the updated safety comment, feel
free to include my Reviewed-by in your next version.

Alice
Alice Ryhl Aug. 1, 2024, 9:07 a.m. UTC | #7
On Wed, Jul 31, 2024 at 10:57 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> > > > +    /// `phydev` must be passed by the corresponding callback in `phy_driver`.
> > > > +    unsafe extern "C" fn probe_callback(phydev: *mut bindings::phy_device) -> core::ffi::c_int {
> > > > +        from_result(|| {
> > > > +            // SAFETY: This callback is called only in contexts
> > > > +            // where we can exclusively access to `phy_device`, so the accessors on
> > > > +            // `Device` are okay to call.
> > >
> > > This one is slightly different to other callbacks. probe is called
> > > without the mutex. Instead, probe is called before the device is
> > > published. So the comment is correct, but given how important Rust
> > > people take these SAFETY comments, maybe it should indicate it is
> > > different to others?
> >
> > Interesting. Given that we don't hold the mutex, does that mean that
> > some of the methods on Device are not safe to call in this context? Or
> > is there something else that makes it okay to call them despite not
> > holding the mutex?
>
> probe is always the first method called on a device driver to match it
> to a device. Traditionally, if probe fails, the device is destroyed,
> since there is no driver to drive it. probe needs to complete
> successfully before the phy_device structure is published so a MAC
> driver can reference it. If it is not published, nothing can have
> access to it, so you don't need to worry about parallel activities on
> it.
>
> And a PHY driver does not need a probe function. Historically, probe
> was all about, can this driver drive this hardware. However, since we
> have ID registers in the hardware, we already know the driver can
> drive the hardware. So probe is now about setting up whatever needs
> setting up. For PHY drivers, there is often nothing, no local state
> needed, etc. So the probe is optional.

Makes sense. Thanks for the explanation!

Alice
diff mbox series

Patch

diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs
index fd40b703d224..99a142348a34 100644
--- a/rust/kernel/net/phy.rs
+++ b/rust/kernel/net/phy.rs
@@ -338,6 +338,20 @@  impl<T: Driver> Adapter<T> {
         })
     }
 
+    /// # Safety
+    ///
+    /// `phydev` must be passed by the corresponding callback in `phy_driver`.
+    unsafe extern "C" fn probe_callback(phydev: *mut bindings::phy_device) -> core::ffi::c_int {
+        from_result(|| {
+            // SAFETY: This callback is called only in contexts
+            // where we can exclusively access to `phy_device`, so the accessors on
+            // `Device` are okay to call.
+            let dev = unsafe { Device::from_raw(phydev) };
+            T::probe(dev)?;
+            Ok(0)
+        })
+    }
+
     /// # Safety
     ///
     /// `phydev` must be passed by the corresponding callback in `phy_driver`.
@@ -511,6 +525,11 @@  pub const fn create_phy_driver<T: Driver>() -> DriverVTable {
         } else {
             None
         },
+        probe: if T::HAS_PROBE {
+            Some(Adapter::<T>::probe_callback)
+        } else {
+            None
+        },
         get_features: if T::HAS_GET_FEATURES {
             Some(Adapter::<T>::get_features_callback)
         } else {
@@ -583,6 +602,11 @@  fn soft_reset(_dev: &mut Device) -> Result {
         kernel::build_error(VTABLE_DEFAULT_ERROR)
     }
 
+    /// Sets up device-specific structures during discovery.
+    fn probe(_dev: &mut Device) -> Result {
+        kernel::build_error(VTABLE_DEFAULT_ERROR)
+    }
+
     /// Probes the hardware to determine what abilities it has.
     fn get_features(_dev: &mut Device) -> Result {
         kernel::build_error(VTABLE_DEFAULT_ERROR)