rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v6 0/6] net: phy: add Applied Micro QT2025 PHY driver
@ 2024-08-20 22:57 FUJITA Tomonori
  2024-08-20 22:57 ` [PATCH net-next v6 1/6] rust: sizes: add commonly used constants FUJITA Tomonori
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: FUJITA Tomonori @ 2024-08-20 22:57 UTC (permalink / raw)
  To: netdev
  Cc: rust-for-linux, andrew, tmgross, miguel.ojeda.sandonis,
	benno.lossin, aliceryhl

This patchset adds a PHY driver for Applied Micro Circuits Corporation
QT2025.

The first patch adds Rust equivalent to include/linux/sizes.h, makes
code more readable. The 2-5th patches update the PHYLIB Rust bindings.
The 4th and 5th patches have been reviewed previously in a different
thread [1].

QT2025 PHY support was implemented as a part of an Ethernet driver for
Tehuti Networks TN40xx chips. Multiple vendors (DLink, Asus, Edimax,
QNAP, etc) developed adapters based on TN40xx chips. Tehuti Networks
went out of business and the driver wasn't merged into mainline. But
it's still distributed with some of the hardware (and also available
on some vendor sites).

The original driver handles multiple PHY hardware (AMCC QT2025, TI
TLK10232, Aqrate AQR105, and Marvell MV88X3120, MV88X3310, and
MV88E2010). I divided the original driver into MAC and PHY drivers and
implemented a QT2025 PHY driver in Rust.

The MAC driver for Tehuti Networks TN40xx chips was already merged in
6.11-rc1. The MAC and this PHY drivers have been tested with Edimax
EN-9320SFP+ 10G network adapter.

[1] https://lore.kernel.org/rust-for-linux/20240607052113.69026-1-fujita.tomonori@gmail.com/

v6:
- improve comments
- make the logic to load firmware more readable
- add Copy trait to reg::{C22 and C45}
- add Trevor Reviewed-by
v5: https://lore.kernel.org/netdev/20240819005345.84255-1-fujita.tomonori@gmail.com/
- fix the comments (3th patch)
- add RUST_FW_LOADER_ABSTRACTIONS dependency
- add Andrew and Benno Reviewed-by
v4: https://lore.kernel.org/netdev/20240817051939.77735-1-fujita.tomonori@gmail.com/
- fix the comments
- add Andrew's Reviewed-by
- fix the order of tags
- remove wrong endianness conversion
v3: https://lore.kernel.org/netdev/20240804233835.223460-1-fujita.tomonori@gmail.com/
- use addr_of_mut!` to avoid intermediate mutable reference
- update probe callback's Safety comment
- add MODULE_FIRMWARE equivalent
- add Alice's Reviewed-by
v2: https://lore.kernel.org/netdev/20240731042136.201327-1-fujita.tomonori@gmail.com/
- add comments in accordance with the hw datasheet
- unify C22 and C45 APIs
- load firmware in probe callback instead of config_init
- use firmware API
- handle firmware endian
- check firmware size
- use SZ_*K constants
- avoid confusing phy_id variable
v1: https://lore.kernel.org/netdev/20240415104701.4772-1-fujita.tomonori@gmail.com/

FUJITA Tomonori (6):
  rust: sizes: add commonly used constants
  rust: net::phy support probe callback
  rust: net::phy implement AsRef<kernel::device::Device> trait
  rust: net::phy unified read/write API for C22 and C45 registers
  rust: net::phy unified genphy_read_status function for C22 and C45
    registers
  net: phy: add Applied Micro QT2025 PHY driver

 MAINTAINERS                      |   8 ++
 drivers/net/phy/Kconfig          |   7 +
 drivers/net/phy/Makefile         |   1 +
 drivers/net/phy/ax88796b_rust.rs |   7 +-
 drivers/net/phy/qt2025.rs        |  98 ++++++++++++++
 rust/kernel/lib.rs               |   1 +
 rust/kernel/net/phy.rs           |  90 +++++++------
 rust/kernel/net/phy/reg.rs       | 224 +++++++++++++++++++++++++++++++
 rust/kernel/sizes.rs             |  26 ++++
 rust/uapi/uapi_helper.h          |   1 +
 10 files changed, 420 insertions(+), 43 deletions(-)
 create mode 100644 drivers/net/phy/qt2025.rs
 create mode 100644 rust/kernel/net/phy/reg.rs
 create mode 100644 rust/kernel/sizes.rs


base-commit: af3dc0ad3167985894a292968c67502f42854e6d
-- 
2.34.1


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

* [PATCH net-next v6 1/6] rust: sizes: add commonly used constants
  2024-08-20 22:57 [PATCH net-next v6 0/6] net: phy: add Applied Micro QT2025 PHY driver FUJITA Tomonori
@ 2024-08-20 22:57 ` FUJITA Tomonori
  2024-08-20 23:41   ` Greg KH
  2024-08-20 22:57 ` [PATCH net-next v6 2/6] rust: net::phy support probe callback FUJITA Tomonori
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: FUJITA Tomonori @ 2024-08-20 22:57 UTC (permalink / raw)
  To: netdev
  Cc: rust-for-linux, andrew, tmgross, miguel.ojeda.sandonis,
	benno.lossin, aliceryhl

Add rust equivalent to include/linux/sizes.h, makes code more
readable.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Trevor Gross <tmgross@umich.edu>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
 rust/kernel/lib.rs   |  1 +
 rust/kernel/sizes.rs | 26 ++++++++++++++++++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 rust/kernel/sizes.rs

diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 274bdc1b0a82..58ed400198bf 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -43,6 +43,7 @@
 pub mod page;
 pub mod prelude;
 pub mod print;
+pub mod sizes;
 mod static_assert;
 #[doc(hidden)]
 pub mod std_vendor;
diff --git a/rust/kernel/sizes.rs b/rust/kernel/sizes.rs
new file mode 100644
index 000000000000..834c343e4170
--- /dev/null
+++ b/rust/kernel/sizes.rs
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Commonly used sizes.
+//!
+//! C headers: [`include/linux/sizes.h`](srctree/include/linux/sizes.h).
+
+/// 0x00000400
+pub const SZ_1K: usize = bindings::SZ_1K as usize;
+/// 0x00000800
+pub const SZ_2K: usize = bindings::SZ_2K as usize;
+/// 0x00001000
+pub const SZ_4K: usize = bindings::SZ_4K as usize;
+/// 0x00002000
+pub const SZ_8K: usize = bindings::SZ_8K as usize;
+/// 0x00004000
+pub const SZ_16K: usize = bindings::SZ_16K as usize;
+/// 0x00008000
+pub const SZ_32K: usize = bindings::SZ_32K as usize;
+/// 0x00010000
+pub const SZ_64K: usize = bindings::SZ_64K as usize;
+/// 0x00020000
+pub const SZ_128K: usize = bindings::SZ_128K as usize;
+/// 0x00040000
+pub const SZ_256K: usize = bindings::SZ_256K as usize;
+/// 0x00080000
+pub const SZ_512K: usize = bindings::SZ_512K as usize;
-- 
2.34.1


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

* [PATCH net-next v6 2/6] rust: net::phy support probe callback
  2024-08-20 22:57 [PATCH net-next v6 0/6] net: phy: add Applied Micro QT2025 PHY driver FUJITA Tomonori
  2024-08-20 22:57 ` [PATCH net-next v6 1/6] rust: sizes: add commonly used constants FUJITA Tomonori
@ 2024-08-20 22:57 ` FUJITA Tomonori
  2024-08-20 22:57 ` [PATCH net-next v6 3/6] rust: net::phy implement AsRef<kernel::device::Device> trait FUJITA Tomonori
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: FUJITA Tomonori @ 2024-08-20 22:57 UTC (permalink / raw)
  To: netdev
  Cc: rust-for-linux, andrew, tmgross, miguel.ojeda.sandonis,
	benno.lossin, aliceryhl

Support phy_driver probe callback, used to set up device-specific
structures.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Trevor Gross <tmgross@umich.edu>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
 rust/kernel/net/phy.rs | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs
index fd40b703d224..5e8137a1972f 100644
--- a/rust/kernel/net/phy.rs
+++ b/rust/kernel/net/phy.rs
@@ -338,6 +338,21 @@ 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 `phy_device` because
+            // it's not published yet, 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 +526,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 +603,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)
-- 
2.34.1


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

* [PATCH net-next v6 3/6] rust: net::phy implement AsRef<kernel::device::Device> trait
  2024-08-20 22:57 [PATCH net-next v6 0/6] net: phy: add Applied Micro QT2025 PHY driver FUJITA Tomonori
  2024-08-20 22:57 ` [PATCH net-next v6 1/6] rust: sizes: add commonly used constants FUJITA Tomonori
  2024-08-20 22:57 ` [PATCH net-next v6 2/6] rust: net::phy support probe callback FUJITA Tomonori
@ 2024-08-20 22:57 ` FUJITA Tomonori
  2024-08-20 22:57 ` [PATCH net-next v6 4/6] rust: net::phy unified read/write API for C22 and C45 registers FUJITA Tomonori
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: FUJITA Tomonori @ 2024-08-20 22:57 UTC (permalink / raw)
  To: netdev
  Cc: rust-for-linux, andrew, tmgross, miguel.ojeda.sandonis,
	benno.lossin, aliceryhl

Implement AsRef<kernel::device::Device> trait for Device. A PHY driver
needs a reference to device::Device to call the firmware API.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Trevor Gross <tmgross@umich.edu>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
 rust/kernel/net/phy.rs | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs
index 5e8137a1972f..b16e8c10a0a2 100644
--- a/rust/kernel/net/phy.rs
+++ b/rust/kernel/net/phy.rs
@@ -7,8 +7,7 @@
 //! C headers: [`include/linux/phy.h`](srctree/include/linux/phy.h).
 
 use crate::{error::*, prelude::*, types::Opaque};
-
-use core::marker::PhantomData;
+use core::{marker::PhantomData, ptr::addr_of_mut};
 
 /// PHY state machine states.
 ///
@@ -58,8 +57,9 @@ pub enum DuplexMode {
 ///
 /// # Invariants
 ///
-/// Referencing a `phy_device` using this struct asserts that you are in
-/// a context where all methods defined on this struct are safe to call.
+/// - Referencing a `phy_device` using this struct asserts that you are in
+///   a context where all methods defined on this struct are safe to call.
+/// - This struct always has a valid `self.0.mdio.dev`.
 ///
 /// [`struct phy_device`]: srctree/include/linux/phy.h
 // During the calls to most functions in [`Driver`], the C side (`PHYLIB`) holds a lock that is
@@ -76,9 +76,11 @@ impl Device {
     ///
     /// # Safety
     ///
-    /// For the duration of 'a, the pointer must point at a valid `phy_device`,
-    /// and the caller must be in a context where all methods defined on this struct
-    /// are safe to call.
+    /// For the duration of `'a`,
+    /// - the pointer must point at a valid `phy_device`, and the caller
+    ///   must be in a context where all methods defined on this struct
+    ///   are safe to call.
+    /// - `(*ptr).mdio.dev` must be a valid.
     unsafe fn from_raw<'a>(ptr: *mut bindings::phy_device) -> &'a mut Self {
         // CAST: `Self` is a `repr(transparent)` wrapper around `bindings::phy_device`.
         let ptr = ptr.cast::<Self>();
@@ -302,6 +304,14 @@ pub fn genphy_read_abilities(&mut self) -> Result {
     }
 }
 
+impl AsRef<kernel::device::Device> for Device {
+    fn as_ref(&self) -> &kernel::device::Device {
+        let phydev = self.0.get();
+        // SAFETY: The struct invariant ensures that `mdio.dev` is valid.
+        unsafe { kernel::device::Device::as_ref(addr_of_mut!((*phydev).mdio.dev)) }
+    }
+}
+
 /// Defines certain other features this PHY supports (like interrupts).
 ///
 /// These flag values are used in [`Driver::FLAGS`].
-- 
2.34.1


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

* [PATCH net-next v6 4/6] rust: net::phy unified read/write API for C22 and C45 registers
  2024-08-20 22:57 [PATCH net-next v6 0/6] net: phy: add Applied Micro QT2025 PHY driver FUJITA Tomonori
                   ` (2 preceding siblings ...)
  2024-08-20 22:57 ` [PATCH net-next v6 3/6] rust: net::phy implement AsRef<kernel::device::Device> trait FUJITA Tomonori
@ 2024-08-20 22:57 ` FUJITA Tomonori
  2024-08-20 22:57 ` [PATCH net-next v6 5/6] rust: net::phy unified genphy_read_status function " FUJITA Tomonori
  2024-08-20 22:57 ` [PATCH net-next v6 6/6] net: phy: add Applied Micro QT2025 PHY driver FUJITA Tomonori
  5 siblings, 0 replies; 14+ messages in thread
From: FUJITA Tomonori @ 2024-08-20 22:57 UTC (permalink / raw)
  To: netdev
  Cc: rust-for-linux, andrew, tmgross, miguel.ojeda.sandonis,
	benno.lossin, aliceryhl

Add the unified read/write API for C22 and C45 registers. The
abstractions support access to only C22 registers now. Instead of
adding read/write_c45 methods specifically for C45, a new reg module
supports the unified API to access C22 and C45 registers with trait,
by calling an appropriate phylib functions.

Reviewed-by: Trevor Gross <tmgross@umich.edu>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
 MAINTAINERS                      |   1 +
 drivers/net/phy/ax88796b_rust.rs |   7 +-
 rust/kernel/net/phy.rs           |  31 ++---
 rust/kernel/net/phy/reg.rs       | 196 +++++++++++++++++++++++++++++++
 rust/uapi/uapi_helper.h          |   1 +
 5 files changed, 209 insertions(+), 27 deletions(-)
 create mode 100644 rust/kernel/net/phy/reg.rs

diff --git a/MAINTAINERS b/MAINTAINERS
index 5dbf23cf11c8..9dbfcf77acb2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8354,6 +8354,7 @@ L:	netdev@vger.kernel.org
 L:	rust-for-linux@vger.kernel.org
 S:	Maintained
 F:	rust/kernel/net/phy.rs
+F:	rust/kernel/net/phy/reg.rs
 
 EXEC & BINFMT API, ELF
 R:	Eric Biederman <ebiederm@xmission.com>
diff --git a/drivers/net/phy/ax88796b_rust.rs b/drivers/net/phy/ax88796b_rust.rs
index 5c92572962dc..8c7eb009d9fc 100644
--- a/drivers/net/phy/ax88796b_rust.rs
+++ b/drivers/net/phy/ax88796b_rust.rs
@@ -6,7 +6,7 @@
 //! C version of this driver: [`drivers/net/phy/ax88796b.c`](./ax88796b.c)
 use kernel::{
     c_str,
-    net::phy::{self, DeviceId, Driver},
+    net::phy::{self, reg::C22, DeviceId, Driver},
     prelude::*,
     uapi,
 };
@@ -24,7 +24,6 @@
     license: "GPL",
 }
 
-const MII_BMCR: u16 = uapi::MII_BMCR as u16;
 const BMCR_SPEED100: u16 = uapi::BMCR_SPEED100 as u16;
 const BMCR_FULLDPLX: u16 = uapi::BMCR_FULLDPLX as u16;
 
@@ -33,7 +32,7 @@
 // Toggle BMCR_RESET bit off to accommodate broken AX8796B PHY implementation
 // such as used on the Individual Computers' X-Surf 100 Zorro card.
 fn asix_soft_reset(dev: &mut phy::Device) -> Result {
-    dev.write(uapi::MII_BMCR as u16, 0)?;
+    dev.write(C22::BMCR, 0)?;
     dev.genphy_soft_reset()
 }
 
@@ -55,7 +54,7 @@ fn read_status(dev: &mut phy::Device) -> Result<u16> {
         }
         // If MII_LPA is 0, phy_resolve_aneg_linkmode() will fail to resolve
         // linkmode so use MII_BMCR as default values.
-        let ret = dev.read(MII_BMCR)?;
+        let ret = dev.read(C22::BMCR)?;
 
         if ret & BMCR_SPEED100 != 0 {
             dev.set_speed(uapi::SPEED_100);
diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs
index b16e8c10a0a2..45866db14c76 100644
--- a/rust/kernel/net/phy.rs
+++ b/rust/kernel/net/phy.rs
@@ -9,6 +9,8 @@
 use crate::{error::*, prelude::*, types::Opaque};
 use core::{marker::PhantomData, ptr::addr_of_mut};
 
+pub mod reg;
+
 /// PHY state machine states.
 ///
 /// Corresponds to the kernel's [`enum phy_state`].
@@ -177,32 +179,15 @@ pub fn set_duplex(&mut self, mode: DuplexMode) {
         unsafe { (*phydev).duplex = v };
     }
 
-    /// Reads a given C22 PHY register.
+    /// Reads a PHY register.
     // This function reads a hardware register and updates the stats so takes `&mut self`.
-    pub fn read(&mut self, regnum: u16) -> Result<u16> {
-        let phydev = self.0.get();
-        // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
-        // So it's just an FFI call, open code of `phy_read()` with a valid `phy_device` pointer
-        // `phydev`.
-        let ret = unsafe {
-            bindings::mdiobus_read((*phydev).mdio.bus, (*phydev).mdio.addr, regnum.into())
-        };
-        if ret < 0 {
-            Err(Error::from_errno(ret))
-        } else {
-            Ok(ret as u16)
-        }
+    pub fn read<R: reg::Register>(&mut self, reg: R) -> Result<u16> {
+        reg.read(self)
     }
 
-    /// Writes a given C22 PHY register.
-    pub fn write(&mut self, regnum: u16, val: u16) -> Result {
-        let phydev = self.0.get();
-        // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
-        // So it's just an FFI call, open code of `phy_write()` with a valid `phy_device` pointer
-        // `phydev`.
-        to_result(unsafe {
-            bindings::mdiobus_write((*phydev).mdio.bus, (*phydev).mdio.addr, regnum.into(), val)
-        })
+    /// Writes a PHY register.
+    pub fn write<R: reg::Register>(&mut self, reg: R, val: u16) -> Result {
+        reg.write(self, val)
     }
 
     /// Reads a paged register.
diff --git a/rust/kernel/net/phy/reg.rs b/rust/kernel/net/phy/reg.rs
new file mode 100644
index 000000000000..191b96a524f5
--- /dev/null
+++ b/rust/kernel/net/phy/reg.rs
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2024 FUJITA Tomonori <fujita.tomonori@gmail.com>
+
+//! PHY register interfaces.
+//!
+//! This module provides support for accessing PHY registers in the
+//! Ethernet management interface clauses 22 and 45 register namespaces, as
+//! defined in IEEE 802.3.
+
+use super::Device;
+use crate::build_assert;
+use crate::error::*;
+use crate::uapi;
+
+mod private {
+    /// Marker that a trait cannot be implemented outside of this crate
+    pub trait Sealed {}
+}
+
+/// Accesses PHY registers.
+///
+/// This trait is used to implement the unified interface to access
+/// C22 and C45 PHY registers.
+///
+/// # Examples
+///
+/// ```ignore
+/// fn link_change_notify(dev: &mut Device) {
+///     // read C22 BMCR register
+///     dev.read(C22::BMCR);
+///     // read C45 PMA/PMD control 1 register
+///     dev.read(C45::new(Mmd::PMAPMD, 0));
+/// }
+/// ```
+pub trait Register: private::Sealed {
+    /// Reads a PHY register.
+    fn read(&self, dev: &mut Device) -> Result<u16>;
+
+    /// Writes a PHY register.
+    fn write(&self, dev: &mut Device, val: u16) -> Result;
+}
+
+/// A single MDIO clause 22 register address (5 bits).
+#[derive(Copy, Clone)]
+pub struct C22(u8);
+
+impl C22 {
+    /// Basic mode control.
+    pub const BMCR: Self = C22(0x00);
+    /// Basic mode status.
+    pub const BMSR: Self = C22(0x01);
+    /// PHY identifier 1.
+    pub const PHYSID1: Self = C22(0x02);
+    /// PHY identifier 2.
+    pub const PHYSID2: Self = C22(0x03);
+    /// Auto-negotiation advertisement.
+    pub const ADVERTISE: Self = C22(0x04);
+    /// Auto-negotiation link partner base page ability.
+    pub const LPA: Self = C22(0x05);
+    /// Auto-negotiation expansion.
+    pub const EXPANSION: Self = C22(0x06);
+    /// Auto-negotiation next page transmit.
+    pub const NEXT_PAGE_TRANSMIT: Self = C22(0x07);
+    /// Auto-negotiation link partner received next page.
+    pub const LP_RECEIVED_NEXT_PAGE: Self = C22(0x08);
+    /// Master-slave control.
+    pub const MASTER_SLAVE_CONTROL: Self = C22(0x09);
+    /// Master-slave status.
+    pub const MASTER_SLAVE_STATUS: Self = C22(0x0a);
+    /// PSE Control.
+    pub const PSE_CONTROL: Self = C22(0x0b);
+    /// PSE Status.
+    pub const PSE_STATUS: Self = C22(0x0c);
+    /// MMD Register control.
+    pub const MMD_CONTROL: Self = C22(0x0d);
+    /// MMD Register address data.
+    pub const MMD_DATA: Self = C22(0x0e);
+    /// Extended status.
+    pub const EXTENDED_STATUS: Self = C22(0x0f);
+
+    /// Creates a new instance of `C22` with a vendor specific register.
+    pub const fn vendor_specific<const N: u8>() -> Self {
+        build_assert!(
+            N > 0x0f && N < 0x20,
+            "Vendor-specific register address must be between 16 and 31"
+        );
+        C22(N)
+    }
+}
+
+impl private::Sealed for C22 {}
+
+impl Register for C22 {
+    fn read(&self, dev: &mut Device) -> Result<u16> {
+        let phydev = dev.0.get();
+        // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Device`.
+        // So it's just an FFI call, open code of `phy_read()` with a valid `phy_device` pointer
+        // `phydev`.
+        let ret = unsafe {
+            bindings::mdiobus_read((*phydev).mdio.bus, (*phydev).mdio.addr, self.0.into())
+        };
+        to_result(ret)?;
+        Ok(ret as u16)
+    }
+
+    fn write(&self, dev: &mut Device, val: u16) -> Result {
+        let phydev = dev.0.get();
+        // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Device`.
+        // So it's just an FFI call, open code of `phy_write()` with a valid `phy_device` pointer
+        // `phydev`.
+        to_result(unsafe {
+            bindings::mdiobus_write((*phydev).mdio.bus, (*phydev).mdio.addr, self.0.into(), val)
+        })
+    }
+}
+
+/// A single MDIO clause 45 register device and address.
+#[derive(Copy, Clone)]
+pub struct Mmd(u8);
+
+impl Mmd {
+    /// Physical Medium Attachment/Dependent.
+    pub const PMAPMD: Self = Mmd(uapi::MDIO_MMD_PMAPMD as u8);
+    /// WAN interface sublayer.
+    pub const WIS: Self = Mmd(uapi::MDIO_MMD_WIS as u8);
+    /// Physical coding sublayer.
+    pub const PCS: Self = Mmd(uapi::MDIO_MMD_PCS as u8);
+    /// PHY Extender sublayer.
+    pub const PHYXS: Self = Mmd(uapi::MDIO_MMD_PHYXS as u8);
+    /// DTE Extender sublayer.
+    pub const DTEXS: Self = Mmd(uapi::MDIO_MMD_DTEXS as u8);
+    /// Transmission convergence.
+    pub const TC: Self = Mmd(uapi::MDIO_MMD_TC as u8);
+    /// Auto negotiation.
+    pub const AN: Self = Mmd(uapi::MDIO_MMD_AN as u8);
+    /// Separated PMA (1).
+    pub const SEPARATED_PMA1: Self = Mmd(8);
+    /// Separated PMA (2).
+    pub const SEPARATED_PMA2: Self = Mmd(9);
+    /// Separated PMA (3).
+    pub const SEPARATED_PMA3: Self = Mmd(10);
+    /// Separated PMA (4).
+    pub const SEPARATED_PMA4: Self = Mmd(11);
+    /// OFDM PMA/PMD.
+    pub const OFDM_PMAPMD: Self = Mmd(12);
+    /// Power unit.
+    pub const POWER_UNIT: Self = Mmd(13);
+    /// Clause 22 extension.
+    pub const C22_EXT: Self = Mmd(uapi::MDIO_MMD_C22EXT as u8);
+    /// Vendor specific 1.
+    pub const VEND1: Self = Mmd(uapi::MDIO_MMD_VEND1 as u8);
+    /// Vendor specific 2.
+    pub const VEND2: Self = Mmd(uapi::MDIO_MMD_VEND2 as u8);
+}
+
+/// A single MDIO clause 45 register device and address.
+///
+/// Clause 45 uses a 5-bit device address to access a specific MMD within
+/// a port, then a 16-bit register address to access a location within
+/// that device. `C45` represents this by storing a [`Mmd`] and
+/// a register number.
+pub struct C45 {
+    devad: Mmd,
+    regnum: u16,
+}
+
+impl C45 {
+    /// Creates a new instance of `C45`.
+    pub fn new(devad: Mmd, regnum: u16) -> Self {
+        Self { devad, regnum }
+    }
+}
+
+impl private::Sealed for C45 {}
+
+impl Register for C45 {
+    fn read(&self, dev: &mut Device) -> Result<u16> {
+        let phydev = dev.0.get();
+        // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Device`.
+        // So it's just an FFI call.
+        let ret =
+            unsafe { bindings::phy_read_mmd(phydev, self.devad.0.into(), self.regnum.into()) };
+        to_result(ret)?;
+        Ok(ret as u16)
+    }
+
+    fn write(&self, dev: &mut Device, val: u16) -> Result {
+        let phydev = dev.0.get();
+        // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Device`.
+        // So it's just an FFI call.
+        to_result(unsafe {
+            bindings::phy_write_mmd(phydev, self.devad.0.into(), self.regnum.into(), val)
+        })
+    }
+}
diff --git a/rust/uapi/uapi_helper.h b/rust/uapi/uapi_helper.h
index 08f5e9334c9e..76d3f103e764 100644
--- a/rust/uapi/uapi_helper.h
+++ b/rust/uapi/uapi_helper.h
@@ -7,5 +7,6 @@
  */
 
 #include <uapi/asm-generic/ioctl.h>
+#include <uapi/linux/mdio.h>
 #include <uapi/linux/mii.h>
 #include <uapi/linux/ethtool.h>
-- 
2.34.1


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

* [PATCH net-next v6 5/6] rust: net::phy unified genphy_read_status function for C22 and C45 registers
  2024-08-20 22:57 [PATCH net-next v6 0/6] net: phy: add Applied Micro QT2025 PHY driver FUJITA Tomonori
                   ` (3 preceding siblings ...)
  2024-08-20 22:57 ` [PATCH net-next v6 4/6] rust: net::phy unified read/write API for C22 and C45 registers FUJITA Tomonori
@ 2024-08-20 22:57 ` FUJITA Tomonori
  2024-08-20 22:57 ` [PATCH net-next v6 6/6] net: phy: add Applied Micro QT2025 PHY driver FUJITA Tomonori
  5 siblings, 0 replies; 14+ messages in thread
From: FUJITA Tomonori @ 2024-08-20 22:57 UTC (permalink / raw)
  To: netdev
  Cc: rust-for-linux, andrew, tmgross, miguel.ojeda.sandonis,
	benno.lossin, aliceryhl

Add unified genphy_read_status function for C22 and C45
registers. Instead of having genphy_c22 and genphy_c45 methods, this
unifies genphy_read_status functions for C22 and C45.

Reviewed-by: Trevor Gross <tmgross@umich.edu>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
 rust/kernel/net/phy.rs     | 12 ++----------
 rust/kernel/net/phy/reg.rs | 28 ++++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs
index 45866db14c76..1d47884aa3cf 100644
--- a/rust/kernel/net/phy.rs
+++ b/rust/kernel/net/phy.rs
@@ -252,16 +252,8 @@ pub fn genphy_suspend(&mut self) -> Result {
     }
 
     /// Checks the link status and updates current link state.
-    pub fn genphy_read_status(&mut self) -> Result<u16> {
-        let phydev = self.0.get();
-        // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
-        // So it's just an FFI call.
-        let ret = unsafe { bindings::genphy_read_status(phydev) };
-        if ret < 0 {
-            Err(Error::from_errno(ret))
-        } else {
-            Ok(ret as u16)
-        }
+    pub fn genphy_read_status<R: reg::Register>(&mut self) -> Result<u16> {
+        R::read_status(self)
     }
 
     /// Updates the link status.
diff --git a/rust/kernel/net/phy/reg.rs b/rust/kernel/net/phy/reg.rs
index 191b96a524f5..c784e6834bfa 100644
--- a/rust/kernel/net/phy/reg.rs
+++ b/rust/kernel/net/phy/reg.rs
@@ -31,6 +31,13 @@ pub trait Sealed {}
 ///     dev.read(C22::BMCR);
 ///     // read C45 PMA/PMD control 1 register
 ///     dev.read(C45::new(Mmd::PMAPMD, 0));
+///
+///     // Checks the link status as reported by registers in the C22 namespace
+///     // and updates current link state.
+///     dev.genphy_read_status::<phy::C22>();
+///     // Checks the link status as reported by registers in the C45 namespace
+///     // and updates current link state.
+///     dev.genphy_read_status::<phy::C45>();
 /// }
 /// ```
 pub trait Register: private::Sealed {
@@ -39,6 +46,9 @@ pub trait Register: private::Sealed {
 
     /// Writes a PHY register.
     fn write(&self, dev: &mut Device, val: u16) -> Result;
+
+    /// Checks the link status and updates current link state.
+    fn read_status(dev: &mut Device) -> Result<u16>;
 }
 
 /// A single MDIO clause 22 register address (5 bits).
@@ -113,6 +123,15 @@ fn write(&self, dev: &mut Device, val: u16) -> Result {
             bindings::mdiobus_write((*phydev).mdio.bus, (*phydev).mdio.addr, self.0.into(), val)
         })
     }
+
+    fn read_status(dev: &mut Device) -> Result<u16> {
+        let phydev = dev.0.get();
+        // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
+        // So it's just an FFI call.
+        let ret = unsafe { bindings::genphy_read_status(phydev) };
+        to_result(ret)?;
+        Ok(ret as u16)
+    }
 }
 
 /// A single MDIO clause 45 register device and address.
@@ -193,4 +212,13 @@ fn write(&self, dev: &mut Device, val: u16) -> Result {
             bindings::phy_write_mmd(phydev, self.devad.0.into(), self.regnum.into(), val)
         })
     }
+
+    fn read_status(dev: &mut Device) -> Result<u16> {
+        let phydev = dev.0.get();
+        // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
+        // So it's just an FFI call.
+        let ret = unsafe { bindings::genphy_c45_read_status(phydev) };
+        to_result(ret)?;
+        Ok(ret as u16)
+    }
 }
-- 
2.34.1


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

* [PATCH net-next v6 6/6] net: phy: add Applied Micro QT2025 PHY driver
  2024-08-20 22:57 [PATCH net-next v6 0/6] net: phy: add Applied Micro QT2025 PHY driver FUJITA Tomonori
                   ` (4 preceding siblings ...)
  2024-08-20 22:57 ` [PATCH net-next v6 5/6] rust: net::phy unified genphy_read_status function " FUJITA Tomonori
@ 2024-08-20 22:57 ` FUJITA Tomonori
  2024-08-23  5:25   ` Trevor Gross
  5 siblings, 1 reply; 14+ messages in thread
From: FUJITA Tomonori @ 2024-08-20 22:57 UTC (permalink / raw)
  To: netdev
  Cc: rust-for-linux, andrew, tmgross, miguel.ojeda.sandonis,
	benno.lossin, aliceryhl

This driver supports Applied Micro Circuits Corporation QT2025 PHY,
based on a driver for Tehuti Networks TN40xx chips.

The original driver for TN40xx chips supports multiple PHY hardware
(AMCC QT2025, TI TLK10232, Aqrate AQR105, and Marvell 88X3120,
88X3310, and MV88E2010). This driver is extracted from the original
driver and modified to a PHY driver in Rust.

This has been tested with Edimax EN-9320SFP+ 10G network adapter.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
 MAINTAINERS               |  7 +++
 drivers/net/phy/Kconfig   |  7 +++
 drivers/net/phy/Makefile  |  1 +
 drivers/net/phy/qt2025.rs | 98 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 113 insertions(+)
 create mode 100644 drivers/net/phy/qt2025.rs

diff --git a/MAINTAINERS b/MAINTAINERS
index 9dbfcf77acb2..d4464e59dfea 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1609,6 +1609,13 @@ F:	Documentation/admin-guide/perf/xgene-pmu.rst
 F:	Documentation/devicetree/bindings/perf/apm-xgene-pmu.txt
 F:	drivers/perf/xgene_pmu.c
 
+APPLIED MICRO QT2025 PHY DRIVER
+M:	FUJITA Tomonori <fujita.tomonori@gmail.com>
+L:	netdev@vger.kernel.org
+L:	rust-for-linux@vger.kernel.org
+S:	Maintained
+F:	drivers/net/phy/qt2025.rs
+
 APTINA CAMERA SENSOR PLL
 M:	Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
 L:	linux-media@vger.kernel.org
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index f530fcd092fe..01b235b3bb7e 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -112,6 +112,13 @@ config ADIN1100_PHY
 	  Currently supports the:
 	  - ADIN1100 - Robust,Industrial, Low Power 10BASE-T1L Ethernet PHY
 
+config AMCC_QT2025_PHY
+	tristate "AMCC QT2025 PHY"
+	depends on RUST_PHYLIB_ABSTRACTIONS
+	depends on RUST_FW_LOADER_ABSTRACTIONS
+	help
+	  Adds support for the Applied Micro Circuits Corporation QT2025 PHY.
+
 source "drivers/net/phy/aquantia/Kconfig"
 
 config AX88796B_PHY
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index f086a606a87e..669d71959be4 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_ADIN_PHY)		+= adin.o
 obj-$(CONFIG_ADIN1100_PHY)	+= adin1100.o
 obj-$(CONFIG_AIR_EN8811H_PHY)   += air_en8811h.o
 obj-$(CONFIG_AMD_PHY)		+= amd.o
+obj-$(CONFIG_AMCC_QT2025_PHY)	+= qt2025.o
 obj-$(CONFIG_AQUANTIA_PHY)	+= aquantia/
 ifdef CONFIG_AX88796B_RUST_PHY
   obj-$(CONFIG_AX88796B_PHY)	+= ax88796b_rust.o
diff --git a/drivers/net/phy/qt2025.rs b/drivers/net/phy/qt2025.rs
new file mode 100644
index 000000000000..a1505ffca9f5
--- /dev/null
+++ b/drivers/net/phy/qt2025.rs
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) Tehuti Networks Ltd.
+// Copyright (C) 2024 FUJITA Tomonori <fujita.tomonori@gmail.com>
+
+//! Applied Micro Circuits Corporation QT2025 PHY driver
+//!
+//! This driver is based on the vendor driver `QT2025_phy.c`. This source
+//! and firmware can be downloaded on the EN-9320SFP+ support site.
+use kernel::c_str;
+use kernel::error::code;
+use kernel::firmware::Firmware;
+use kernel::net::phy::{
+    self,
+    reg::{Mmd, C45},
+    DeviceId, Driver,
+};
+use kernel::prelude::*;
+use kernel::sizes::{SZ_16K, SZ_8K};
+
+kernel::module_phy_driver! {
+    drivers: [PhyQT2025],
+    device_table: [
+        DeviceId::new_with_driver::<PhyQT2025>(),
+    ],
+    name: "qt2025_phy",
+    author: "FUJITA Tomonori <fujita.tomonori@gmail.com>",
+    description: "AMCC QT2025 PHY driver",
+    license: "GPL",
+    firmware: ["qt2025-2.0.3.3.fw"],
+}
+
+struct PhyQT2025;
+
+#[vtable]
+impl Driver for PhyQT2025 {
+    const NAME: &'static CStr = c_str!("QT2025 10Gpbs SFP+");
+    const PHY_DEVICE_ID: phy::DeviceId = phy::DeviceId::new_with_exact_mask(0x0043A400);
+
+    fn probe(dev: &mut phy::Device) -> Result<()> {
+        // The vendor driver does the following checking but we have no idea why.
+        let hw_id = dev.read(C45::new(Mmd::PMAPMD, 0xd001))?;
+        if (hw_id >> 8) & 0xff != 0xb3 {
+            return Err(code::ENODEV);
+        }
+
+        // The Intel 8051 will remain in the reset state.
+        dev.write(C45::new(Mmd::PMAPMD, 0xC300), 0x0000)?;
+        // Configure the 8051 clock frequency.
+        dev.write(C45::new(Mmd::PMAPMD, 0xC302), 0x0004)?;
+        // Non loopback mode.
+        dev.write(C45::new(Mmd::PMAPMD, 0xC319), 0x0038)?;
+        // Global control bit to select between LAN and WAN (WIS) mode.
+        dev.write(C45::new(Mmd::PMAPMD, 0xC31A), 0x0098)?;
+        // The following writes use standardized registers (3.38 through
+        // 3.41 5/10/25GBASE-R PCS test pattern seed B) for something else.
+        // We don't know what.
+        dev.write(C45::new(Mmd::PCS, 0x0026), 0x0E00)?;
+        dev.write(C45::new(Mmd::PCS, 0x0027), 0x0893)?;
+        dev.write(C45::new(Mmd::PCS, 0x0028), 0xA528)?;
+        dev.write(C45::new(Mmd::PCS, 0x0029), 0x0003)?;
+        // Configure transmit and recovered clock.
+        dev.write(C45::new(Mmd::PMAPMD, 0xC30A), 0x06E1)?;
+        // The 8051 will finish the reset state.
+        dev.write(C45::new(Mmd::PMAPMD, 0xC300), 0x0002)?;
+        // The 8051 will start running from the boot ROM.
+        dev.write(C45::new(Mmd::PCS, 0xE854), 0x00C0)?;
+
+        let fw = Firmware::request(c_str!("qt2025-2.0.3.3.fw"), dev.as_ref())?;
+        if fw.data().len() > SZ_16K + SZ_8K {
+            return Err(code::EFBIG);
+        }
+
+        // The 24kB of program memory space is accessible by MDIO.
+        // The first 16kB of memory is located in the address range 3.8000h - 3.BFFFh.
+        // The next 8kB of memory is located at 4.8000h - 4.9FFFh.
+        let mut dst_offset = 0;
+        let mut dst_mmd = Mmd::PCS;
+        for (src_idx, val) in fw.data().iter().enumerate() {
+            if src_idx == SZ_16K {
+                // Start writing to the next register with no offset
+                dst_offset = 0;
+                dst_mmd = Mmd::PHYXS;
+            }
+
+            dev.write(C45::new(dst_mmd, 0x8000 + dst_offset), (*val).into())?;
+
+            dst_offset += 1;
+        }
+        // The Intel 8051 will start running from SRAM.
+        dev.write(C45::new(Mmd::PCS, 0xE854), 0x0040)?;
+
+        Ok(())
+    }
+
+    fn read_status(dev: &mut phy::Device) -> Result<u16> {
+        dev.genphy_read_status::<C45>()
+    }
+}
-- 
2.34.1


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

* Re: [PATCH net-next v6 1/6] rust: sizes: add commonly used constants
  2024-08-20 22:57 ` [PATCH net-next v6 1/6] rust: sizes: add commonly used constants FUJITA Tomonori
@ 2024-08-20 23:41   ` Greg KH
  2024-08-20 23:54     ` Danilo Krummrich
  2024-08-21  0:14     ` FUJITA Tomonori
  0 siblings, 2 replies; 14+ messages in thread
From: Greg KH @ 2024-08-20 23:41 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: netdev, rust-for-linux, andrew, tmgross, miguel.ojeda.sandonis,
	benno.lossin, aliceryhl

On Tue, Aug 20, 2024 at 10:57:14PM +0000, FUJITA Tomonori wrote:
> Add rust equivalent to include/linux/sizes.h, makes code more
> readable.
> 
> Reviewed-by: Alice Ryhl <aliceryhl@google.com>
> Reviewed-by: Andrew Lunn <andrew@lunn.ch>
> Reviewed-by: Benno Lossin <benno.lossin@proton.me>
> Reviewed-by: Trevor Gross <tmgross@umich.edu>
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
> ---
>  rust/kernel/lib.rs   |  1 +
>  rust/kernel/sizes.rs | 26 ++++++++++++++++++++++++++
>  2 files changed, 27 insertions(+)
>  create mode 100644 rust/kernel/sizes.rs
> 
> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> index 274bdc1b0a82..58ed400198bf 100644
> --- a/rust/kernel/lib.rs
> +++ b/rust/kernel/lib.rs
> @@ -43,6 +43,7 @@
>  pub mod page;
>  pub mod prelude;
>  pub mod print;
> +pub mod sizes;
>  mod static_assert;
>  #[doc(hidden)]
>  pub mod std_vendor;
> diff --git a/rust/kernel/sizes.rs b/rust/kernel/sizes.rs
> new file mode 100644
> index 000000000000..834c343e4170
> --- /dev/null
> +++ b/rust/kernel/sizes.rs
> @@ -0,0 +1,26 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! Commonly used sizes.
> +//!
> +//! C headers: [`include/linux/sizes.h`](srctree/include/linux/sizes.h).
> +
> +/// 0x00000400
> +pub const SZ_1K: usize = bindings::SZ_1K as usize;
> +/// 0x00000800
> +pub const SZ_2K: usize = bindings::SZ_2K as usize;
> +/// 0x00001000
> +pub const SZ_4K: usize = bindings::SZ_4K as usize;
> +/// 0x00002000
> +pub const SZ_8K: usize = bindings::SZ_8K as usize;
> +/// 0x00004000
> +pub const SZ_16K: usize = bindings::SZ_16K as usize;
> +/// 0x00008000
> +pub const SZ_32K: usize = bindings::SZ_32K as usize;
> +/// 0x00010000
> +pub const SZ_64K: usize = bindings::SZ_64K as usize;
> +/// 0x00020000
> +pub const SZ_128K: usize = bindings::SZ_128K as usize;
> +/// 0x00040000
> +pub const SZ_256K: usize = bindings::SZ_256K as usize;
> +/// 0x00080000
> +pub const SZ_512K: usize = bindings::SZ_512K as usize;

Why only some of the values in sizes.h?

And why can't sizes.h be directly translated into rust code without
having to do it "by hand" here?  We do that for other header file
bindings, right?

thanks,

greg k-h

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

* Re: [PATCH net-next v6 1/6] rust: sizes: add commonly used constants
  2024-08-20 23:41   ` Greg KH
@ 2024-08-20 23:54     ` Danilo Krummrich
  2024-08-21  0:22       ` Greg KH
  2024-08-21  0:14     ` FUJITA Tomonori
  1 sibling, 1 reply; 14+ messages in thread
From: Danilo Krummrich @ 2024-08-20 23:54 UTC (permalink / raw)
  To: Greg KH
  Cc: FUJITA Tomonori, netdev, rust-for-linux, andrew, tmgross,
	miguel.ojeda.sandonis, benno.lossin, aliceryhl

On 8/21/24 1:41 AM, Greg KH wrote:
> On Tue, Aug 20, 2024 at 10:57:14PM +0000, FUJITA Tomonori wrote:
>> Add rust equivalent to include/linux/sizes.h, makes code more
>> readable.
>>
>> Reviewed-by: Alice Ryhl <aliceryhl@google.com>
>> Reviewed-by: Andrew Lunn <andrew@lunn.ch>
>> Reviewed-by: Benno Lossin <benno.lossin@proton.me>
>> Reviewed-by: Trevor Gross <tmgross@umich.edu>
>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
>> ---
>>   rust/kernel/lib.rs   |  1 +
>>   rust/kernel/sizes.rs | 26 ++++++++++++++++++++++++++
>>   2 files changed, 27 insertions(+)
>>   create mode 100644 rust/kernel/sizes.rs
>>
>> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
>> index 274bdc1b0a82..58ed400198bf 100644
>> --- a/rust/kernel/lib.rs
>> +++ b/rust/kernel/lib.rs
>> @@ -43,6 +43,7 @@
>>   pub mod page;
>>   pub mod prelude;
>>   pub mod print;
>> +pub mod sizes;
>>   mod static_assert;
>>   #[doc(hidden)]
>>   pub mod std_vendor;
>> diff --git a/rust/kernel/sizes.rs b/rust/kernel/sizes.rs
>> new file mode 100644
>> index 000000000000..834c343e4170
>> --- /dev/null
>> +++ b/rust/kernel/sizes.rs
>> @@ -0,0 +1,26 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +//! Commonly used sizes.
>> +//!
>> +//! C headers: [`include/linux/sizes.h`](srctree/include/linux/sizes.h).
>> +
>> +/// 0x00000400
>> +pub const SZ_1K: usize = bindings::SZ_1K as usize;
>> +/// 0x00000800
>> +pub const SZ_2K: usize = bindings::SZ_2K as usize;
>> +/// 0x00001000
>> +pub const SZ_4K: usize = bindings::SZ_4K as usize;
>> +/// 0x00002000
>> +pub const SZ_8K: usize = bindings::SZ_8K as usize;
>> +/// 0x00004000
>> +pub const SZ_16K: usize = bindings::SZ_16K as usize;
>> +/// 0x00008000
>> +pub const SZ_32K: usize = bindings::SZ_32K as usize;
>> +/// 0x00010000
>> +pub const SZ_64K: usize = bindings::SZ_64K as usize;
>> +/// 0x00020000
>> +pub const SZ_128K: usize = bindings::SZ_128K as usize;
>> +/// 0x00040000
>> +pub const SZ_256K: usize = bindings::SZ_256K as usize;
>> +/// 0x00080000
>> +pub const SZ_512K: usize = bindings::SZ_512K as usize;
> 
> Why only some of the values in sizes.h?
> 
> And why can't sizes.h be directly translated into rust code without
> having to do it "by hand" here?  We do that for other header file
> bindings, right?

Those are all generated bindings from C headers, e.g. `bindings::SZ_2K `, but
bindgen isn't guaranteed to assign the type we want (`usize` in this case), plus
for size constants having the `bindings::` prefix doesn't really add any value.

Rust could also define those without using bindings at all, but this was already
discussed in earlier versions of this series.

- Danilo

> 
> thanks,
> 
> greg k-h
> 

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

* Re: [PATCH net-next v6 1/6] rust: sizes: add commonly used constants
  2024-08-20 23:41   ` Greg KH
  2024-08-20 23:54     ` Danilo Krummrich
@ 2024-08-21  0:14     ` FUJITA Tomonori
  1 sibling, 0 replies; 14+ messages in thread
From: FUJITA Tomonori @ 2024-08-21  0:14 UTC (permalink / raw)
  To: gregkh
  Cc: fujita.tomonori, netdev, rust-for-linux, andrew, tmgross,
	miguel.ojeda.sandonis, benno.lossin, aliceryhl

On Wed, 21 Aug 2024 07:41:24 +0800
Greg KH <gregkh@linuxfoundation.org> wrote:

>> +/// 0x00000400
>> +pub const SZ_1K: usize = bindings::SZ_1K as usize;
>> +/// 0x00000800
>> +pub const SZ_2K: usize = bindings::SZ_2K as usize;
>> +/// 0x00001000
>> +pub const SZ_4K: usize = bindings::SZ_4K as usize;
>> +/// 0x00002000
>> +pub const SZ_8K: usize = bindings::SZ_8K as usize;
>> +/// 0x00004000
>> +pub const SZ_16K: usize = bindings::SZ_16K as usize;
>> +/// 0x00008000
>> +pub const SZ_32K: usize = bindings::SZ_32K as usize;
>> +/// 0x00010000
>> +pub const SZ_64K: usize = bindings::SZ_64K as usize;
>> +/// 0x00020000
>> +pub const SZ_128K: usize = bindings::SZ_128K as usize;
>> +/// 0x00040000
>> +pub const SZ_256K: usize = bindings::SZ_256K as usize;
>> +/// 0x00080000
>> +pub const SZ_512K: usize = bindings::SZ_512K as usize;
> 
> Why only some of the values in sizes.h?

Because this driver needs only some SZ_*K and looks like SZ_*K are
more widely used. But we can add more anytime.

> And why can't sizes.h be directly translated into rust code without
> having to do it "by hand" here?  We do that for other header file
> bindings, right?

No. bindings::* are generated from C headers and kernel crates
give them to drivers by hand. For example, rust/kernel/page.rs has:

pub const PAGE_SIZE: usize = bindings::PAGE_SIZE;

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

* Re: [PATCH net-next v6 1/6] rust: sizes: add commonly used constants
  2024-08-20 23:54     ` Danilo Krummrich
@ 2024-08-21  0:22       ` Greg KH
  0 siblings, 0 replies; 14+ messages in thread
From: Greg KH @ 2024-08-21  0:22 UTC (permalink / raw)
  To: Danilo Krummrich
  Cc: FUJITA Tomonori, netdev, rust-for-linux, andrew, tmgross,
	miguel.ojeda.sandonis, benno.lossin, aliceryhl

On Wed, Aug 21, 2024 at 01:54:43AM +0200, Danilo Krummrich wrote:
> On 8/21/24 1:41 AM, Greg KH wrote:
> > On Tue, Aug 20, 2024 at 10:57:14PM +0000, FUJITA Tomonori wrote:
> > > Add rust equivalent to include/linux/sizes.h, makes code more
> > > readable.
> > > 
> > > Reviewed-by: Alice Ryhl <aliceryhl@google.com>
> > > Reviewed-by: Andrew Lunn <andrew@lunn.ch>
> > > Reviewed-by: Benno Lossin <benno.lossin@proton.me>
> > > Reviewed-by: Trevor Gross <tmgross@umich.edu>
> > > Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
> > > ---
> > >   rust/kernel/lib.rs   |  1 +
> > >   rust/kernel/sizes.rs | 26 ++++++++++++++++++++++++++
> > >   2 files changed, 27 insertions(+)
> > >   create mode 100644 rust/kernel/sizes.rs
> > > 
> > > diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> > > index 274bdc1b0a82..58ed400198bf 100644
> > > --- a/rust/kernel/lib.rs
> > > +++ b/rust/kernel/lib.rs
> > > @@ -43,6 +43,7 @@
> > >   pub mod page;
> > >   pub mod prelude;
> > >   pub mod print;
> > > +pub mod sizes;
> > >   mod static_assert;
> > >   #[doc(hidden)]
> > >   pub mod std_vendor;
> > > diff --git a/rust/kernel/sizes.rs b/rust/kernel/sizes.rs
> > > new file mode 100644
> > > index 000000000000..834c343e4170
> > > --- /dev/null
> > > +++ b/rust/kernel/sizes.rs
> > > @@ -0,0 +1,26 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +
> > > +//! Commonly used sizes.
> > > +//!
> > > +//! C headers: [`include/linux/sizes.h`](srctree/include/linux/sizes.h).
> > > +
> > > +/// 0x00000400
> > > +pub const SZ_1K: usize = bindings::SZ_1K as usize;
> > > +/// 0x00000800
> > > +pub const SZ_2K: usize = bindings::SZ_2K as usize;
> > > +/// 0x00001000
> > > +pub const SZ_4K: usize = bindings::SZ_4K as usize;
> > > +/// 0x00002000
> > > +pub const SZ_8K: usize = bindings::SZ_8K as usize;
> > > +/// 0x00004000
> > > +pub const SZ_16K: usize = bindings::SZ_16K as usize;
> > > +/// 0x00008000
> > > +pub const SZ_32K: usize = bindings::SZ_32K as usize;
> > > +/// 0x00010000
> > > +pub const SZ_64K: usize = bindings::SZ_64K as usize;
> > > +/// 0x00020000
> > > +pub const SZ_128K: usize = bindings::SZ_128K as usize;
> > > +/// 0x00040000
> > > +pub const SZ_256K: usize = bindings::SZ_256K as usize;
> > > +/// 0x00080000
> > > +pub const SZ_512K: usize = bindings::SZ_512K as usize;
> > 
> > Why only some of the values in sizes.h?
> > 
> > And why can't sizes.h be directly translated into rust code without
> > having to do it "by hand" here?  We do that for other header file
> > bindings, right?
> 
> Those are all generated bindings from C headers, e.g. `bindings::SZ_2K `, but
> bindgen isn't guaranteed to assign the type we want (`usize` in this case), plus
> for size constants having the `bindings::` prefix doesn't really add any value.
> 
> Rust could also define those without using bindings at all, but this was already
> discussed in earlier versions of this series.

Then this information should probably go in the changelog text so that
others don't keep asking the same question :)

thanks,

greg k-h

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

* Re: [PATCH net-next v6 6/6] net: phy: add Applied Micro QT2025 PHY driver
  2024-08-20 22:57 ` [PATCH net-next v6 6/6] net: phy: add Applied Micro QT2025 PHY driver FUJITA Tomonori
@ 2024-08-23  5:25   ` Trevor Gross
  2024-08-23 13:36     ` FUJITA Tomonori
  0 siblings, 1 reply; 14+ messages in thread
From: Trevor Gross @ 2024-08-23  5:25 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: netdev, rust-for-linux, andrew, miguel.ojeda.sandonis,
	benno.lossin, aliceryhl

On Tue, Aug 20, 2024 at 5:59 PM FUJITA Tomonori
<fujita.tomonori@gmail.com> wrote:
>
> This driver supports Applied Micro Circuits Corporation QT2025 PHY,
> based on a driver for Tehuti Networks TN40xx chips.
>
> The original driver for TN40xx chips supports multiple PHY hardware
> (AMCC QT2025, TI TLK10232, Aqrate AQR105, and Marvell 88X3120,
> 88X3310, and MV88E2010). This driver is extracted from the original
> driver and modified to a PHY driver in Rust.
>
> This has been tested with Edimax EN-9320SFP+ 10G network adapter.
>
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
> ---

> diff --git a/drivers/net/phy/qt2025.rs b/drivers/net/phy/qt2025.rs
> new file mode 100644
> index 000000000000..a1505ffca9f5
> --- /dev/null
> +++ b/drivers/net/phy/qt2025.rs
> @@ -0,0 +1,98 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) Tehuti Networks Ltd.
> +// Copyright (C) 2024 FUJITA Tomonori <fujita.tomonori@gmail.com>
> +
> +//! Applied Micro Circuits Corporation QT2025 PHY driver
> +//!
> +//! This driver is based on the vendor driver `QT2025_phy.c`. This source
> +//! and firmware can be downloaded on the EN-9320SFP+ support site.
> +use kernel::c_str;

Nit: line between module docs and the first import.

Could you add another note to the doc comment that the phy contains an
embedded Intel 8051 microcontroller? I was getting confused by the
below comments mentioning the 8051 until I realized this.

> +use kernel::error::code;
> +use kernel::firmware::Firmware;
> +use kernel::net::phy::{
> +    self,
> +    reg::{Mmd, C45},
> +    DeviceId, Driver,
> +};
> +use kernel::prelude::*;
> +use kernel::sizes::{SZ_16K, SZ_8K};
> +
> +kernel::module_phy_driver! {
> +    drivers: [PhyQT2025],
> +    device_table: [
> +        DeviceId::new_with_driver::<PhyQT2025>(),
> +    ],
> +    name: "qt2025_phy",
> +    author: "FUJITA Tomonori <fujita.tomonori@gmail.com>",
> +    description: "AMCC QT2025 PHY driver",
> +    license: "GPL",
> +    firmware: ["qt2025-2.0.3.3.fw"],
> +}
> +
> +struct PhyQT2025;
> +
> +#[vtable]
> +impl Driver for PhyQT2025 {
> +    const NAME: &'static CStr = c_str!("QT2025 10Gpbs SFP+");
> +    const PHY_DEVICE_ID: phy::DeviceId = phy::DeviceId::new_with_exact_mask(0x0043A400);
> +
> +    fn probe(dev: &mut phy::Device) -> Result<()> {
> +        // The vendor driver does the following checking but we have no idea why.
> +        let hw_id = dev.read(C45::new(Mmd::PMAPMD, 0xd001))?;
> +        if (hw_id >> 8) & 0xff != 0xb3 {
> +            return Err(code::ENODEV);
> +        }

I actually found this described in the datasheet for the QT2022:
1.D000h is a two-byte "product code", "1.D001h" is a one byte revision
code followed by one byte reserved. So 0xb3 is presumably something
like the major silicon revision number.

Based on how the vendor code is written, it seems like they are
expecting different phy revs to need different firmware. It might be
worth making a note that our firmware only works with 0xb3, whatever
exactly that means.

The `& 0xff` shouldn't be needed since `dev.read` returns an unsigned number.



I went through the datasheet and found some register names, listed
them below. Maybe it is worth putting the names in the comments if
they exist? Just to make things a bit more searchable if somebody
pulls up a datasheet.

> +        // The Intel 8051 will remain in the reset state.
> +        dev.write(C45::new(Mmd::PMAPMD, 0xC300), 0x0000)?;

This sets `MICRO_RESETN` to hold the embedded micro in reset while configuring.

> +        // Configure the 8051 clock frequency.
> +        dev.write(C45::new(Mmd::PMAPMD, 0xC302), 0x0004)?;

This one is `SREFCLK_FREQ`, embedded micro clock frequency. I couldn't
figure out what the meaning of the value is.

> +        // Non loopback mode.
> +        dev.write(C45::new(Mmd::PMAPMD, 0xC319), 0x0038)?;
> +        // Global control bit to select between LAN and WAN (WIS) mode.
> +        dev.write(C45::new(Mmd::PMAPMD, 0xC31A), 0x0098)?;

This LAN/WAN select is called  `CUS_LAN_WAN_CONFIG`

> +        // The following writes use standardized registers (3.38 through
> +        // 3.41 5/10/25GBASE-R PCS test pattern seed B) for something else.
> +        // We don't know what.
> +        dev.write(C45::new(Mmd::PCS, 0x0026), 0x0E00)?;
> +        dev.write(C45::new(Mmd::PCS, 0x0027), 0x0893)?;
> +        dev.write(C45::new(Mmd::PCS, 0x0028), 0xA528)?;
> +        dev.write(C45::new(Mmd::PCS, 0x0029), 0x0003)?;
> +        // Configure transmit and recovered clock.
> +        dev.write(C45::new(Mmd::PMAPMD, 0xC30A), 0x06E1)?;
> +        // The 8051 will finish the reset state.
> +        dev.write(C45::new(Mmd::PMAPMD, 0xC300), 0x0002)?;

`MICRO_RESETN` again, this time to start the embedded micro.

> +        // The 8051 will start running from the boot ROM.
> +        dev.write(C45::new(Mmd::PCS, 0xE854), 0x00C0)?;
> +
> +        let fw = Firmware::request(c_str!("qt2025-2.0.3.3.fw"), dev.as_ref())?;
> +        if fw.data().len() > SZ_16K + SZ_8K {
> +            return Err(code::EFBIG);
> +        }
> +
> +        // The 24kB of program memory space is accessible by MDIO.
> +        // The first 16kB of memory is located in the address range 3.8000h - 3.BFFFh.
> +        // The next 8kB of memory is located at 4.8000h - 4.9FFFh.
> +        let mut dst_offset = 0;
> +        let mut dst_mmd = Mmd::PCS;
> +        for (src_idx, val) in fw.data().iter().enumerate() {
> +            if src_idx == SZ_16K {
> +                // Start writing to the next register with no offset
> +                dst_offset = 0;
> +                dst_mmd = Mmd::PHYXS;
> +            }
> +
> +            dev.write(C45::new(dst_mmd, 0x8000 + dst_offset), (*val).into())?;
> +
> +            dst_offset += 1;
> +        }
> +        // The Intel 8051 will start running from SRAM.
> +        dev.write(C45::new(Mmd::PCS, 0xE854), 0x0040)?;


At this point the vendor driver looks like it does some verification:
it attempts to read 3.d7fd until it returns something other than 0x10
or 0, or times out. Could that be done here?

> +
> +        Ok(())
> +    }
> +
> +    fn read_status(dev: &mut phy::Device) -> Result<u16> {
> +        dev.genphy_read_status::<C45>()
> +    }
> +}
> --
> 2.34.1
>

Consistency nit: this file uses a mix of upper and lowercase hex
(mostly uppercase here) - we should probably be consistent. A quick
regex search looks like lowercase hex is about twice as common in the
kernel as uppercase so I think this may as well be updated.

---

Overall this looks pretty good to me, checking against both the
datasheet and the vendor driver we have. Mostly small suggestions
here, I'm happy to add a RB with my verification question addressed
and some rewording of the 0xd001 (phy revision) comment.

- Trevor

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

* Re: [PATCH net-next v6 6/6] net: phy: add Applied Micro QT2025 PHY driver
  2024-08-23  5:25   ` Trevor Gross
@ 2024-08-23 13:36     ` FUJITA Tomonori
  2024-08-23 19:13       ` Trevor Gross
  0 siblings, 1 reply; 14+ messages in thread
From: FUJITA Tomonori @ 2024-08-23 13:36 UTC (permalink / raw)
  To: tmgross
  Cc: fujita.tomonori, netdev, rust-for-linux, andrew,
	miguel.ojeda.sandonis, benno.lossin, aliceryhl

On Fri, 23 Aug 2024 00:25:23 -0500
Trevor Gross <tmgross@umich.edu> wrote:

>> +//! Applied Micro Circuits Corporation QT2025 PHY driver
>> +//!
>> +//! This driver is based on the vendor driver `QT2025_phy.c`. This source
>> +//! and firmware can be downloaded on the EN-9320SFP+ support site.
>> +use kernel::c_str;
> 
> Nit: line between module docs and the first import.

Oops, will fix.

> Could you add another note to the doc comment that the phy contains an
> embedded Intel 8051 microcontroller? I was getting confused by the
> below comments mentioning the 8051 until I realized this.

Sure, will add.

>> +#[vtable]
>> +impl Driver for PhyQT2025 {
>> +    const NAME: &'static CStr = c_str!("QT2025 10Gpbs SFP+");
>> +    const PHY_DEVICE_ID: phy::DeviceId = phy::DeviceId::new_with_exact_mask(0x0043A400);
>> +
>> +    fn probe(dev: &mut phy::Device) -> Result<()> {
>> +        // The vendor driver does the following checking but we have no idea why.
>> +        let hw_id = dev.read(C45::new(Mmd::PMAPMD, 0xd001))?;
>> +        if (hw_id >> 8) & 0xff != 0xb3 {
>> +            return Err(code::ENODEV);
>> +        }
> 
> I actually found this described in the datasheet for the QT2022:
> 1.D000h is a two-byte "product code", "1.D001h" is a one byte revision
> code followed by one byte reserved. So 0xb3 is presumably something
> like the major silicon revision number.

Thanks! I've not checked the QT2022 datasheet. Looks like both
registers are compatible with QT2025.

> Based on how the vendor code is written, it seems like they are
> expecting different phy revs to need different firmware. It might be
> worth making a note that our firmware only works with 0xb3, whatever
> exactly that means.

I'll update the comment.

> The `& 0xff` shouldn't be needed since `dev.read` returns an unsigned number.

Yeah, looks like unnecessary. We need the upper 8 bits of u16
here. I'll drop it.

> I went through the datasheet and found some register names, listed
> them below. Maybe it is worth putting the names in the comments if
> they exist? Just to make things a bit more searchable if somebody
> pulls up a datasheet.

Sure, I'll add them. 

>> +        // The Intel 8051 will remain in the reset state.
>> +        dev.write(C45::new(Mmd::PMAPMD, 0xC300), 0x0000)?;
> 
> This sets `MICRO_RESETN` to hold the embedded micro in reset while configuring.
> 
>> +        // Configure the 8051 clock frequency.
>> +        dev.write(C45::new(Mmd::PMAPMD, 0xC302), 0x0004)?;
> 
> This one is `SREFCLK_FREQ`, embedded micro clock frequency. I couldn't
> figure out what the meaning of the value is.
> 
>> +        // Non loopback mode.
>> +        dev.write(C45::new(Mmd::PMAPMD, 0xC319), 0x0038)?;
>> +        // Global control bit to select between LAN and WAN (WIS) mode.
>> +        dev.write(C45::new(Mmd::PMAPMD, 0xC31A), 0x0098)?;
> 
> This LAN/WAN select is called  `CUS_LAN_WAN_CONFIG`
> 
>> +        // The following writes use standardized registers (3.38 through
>> +        // 3.41 5/10/25GBASE-R PCS test pattern seed B) for something else.
>> +        // We don't know what.
>> +        dev.write(C45::new(Mmd::PCS, 0x0026), 0x0E00)?;
>> +        dev.write(C45::new(Mmd::PCS, 0x0027), 0x0893)?;
>> +        dev.write(C45::new(Mmd::PCS, 0x0028), 0xA528)?;
>> +        dev.write(C45::new(Mmd::PCS, 0x0029), 0x0003)?;
>> +        // Configure transmit and recovered clock.
>> +        dev.write(C45::new(Mmd::PMAPMD, 0xC30A), 0x06E1)?;
>> +        // The 8051 will finish the reset state.
>> +        dev.write(C45::new(Mmd::PMAPMD, 0xC300), 0x0002)?;
> 
> `MICRO_RESETN` again, this time to start the embedded micro.
> 
>> +        // The 8051 will start running from the boot ROM.
>> +        dev.write(C45::new(Mmd::PCS, 0xE854), 0x00C0)?;
>> +
>> +        let fw = Firmware::request(c_str!("qt2025-2.0.3.3.fw"), dev.as_ref())?;
>> +        if fw.data().len() > SZ_16K + SZ_8K {
>> +            return Err(code::EFBIG);
>> +        }
>> +
>> +        // The 24kB of program memory space is accessible by MDIO.
>> +        // The first 16kB of memory is located in the address range 3.8000h - 3.BFFFh.
>> +        // The next 8kB of memory is located at 4.8000h - 4.9FFFh.
>> +        let mut dst_offset = 0;
>> +        let mut dst_mmd = Mmd::PCS;
>> +        for (src_idx, val) in fw.data().iter().enumerate() {
>> +            if src_idx == SZ_16K {
>> +                // Start writing to the next register with no offset
>> +                dst_offset = 0;
>> +                dst_mmd = Mmd::PHYXS;
>> +            }
>> +
>> +            dev.write(C45::new(dst_mmd, 0x8000 + dst_offset), (*val).into())?;
>> +
>> +            dst_offset += 1;
>> +        }
>> +        // The Intel 8051 will start running from SRAM.
>> +        dev.write(C45::new(Mmd::PCS, 0xE854), 0x0040)?;
> 
> 
> At this point the vendor driver looks like it does some verification:
> it attempts to read 3.d7fd until it returns something other than 0x10
> or 0, or times out. Could that be done here?

Yeah, we better to wait here until the hw becomes ready (since the
8051 has just started) and check if it works correctly. A new Rust
abstraction for msleep() is necessary.

Even without the logic, the driver starts to work eventually (if the
hw isn't broken) so I didn't include it in the patchset. I'll work on
the abstraction and update the driver after this is merged.

>> +
>> +        Ok(())
>> +    }
>> +
>> +    fn read_status(dev: &mut phy::Device) -> Result<u16> {
>> +        dev.genphy_read_status::<C45>()
>> +    }
>> +}
>> --
>> 2.34.1
>>
> 
> Consistency nit: this file uses a mix of upper and lowercase hex
> (mostly uppercase here) - we should probably be consistent. A quick
> regex search looks like lowercase hex is about twice as common in the
> kernel as uppercase so I think this may as well be updated.

Ah, I'll use lowercase for all the hex in the driver.

It will be a new coding rule for rust code in kernel? If so, can a
checker tool warn this?

> Overall this looks pretty good to me, checking against both the
> datasheet and the vendor driver we have. Mostly small suggestions
> here, I'm happy to add a RB with my verification question addressed
> and some rewording of the 0xd001 (phy revision) comment.

Thanks a lot! I'll send v7 soon.

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

* Re: [PATCH net-next v6 6/6] net: phy: add Applied Micro QT2025 PHY driver
  2024-08-23 13:36     ` FUJITA Tomonori
@ 2024-08-23 19:13       ` Trevor Gross
  0 siblings, 0 replies; 14+ messages in thread
From: Trevor Gross @ 2024-08-23 19:13 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: netdev, rust-for-linux, andrew, miguel.ojeda.sandonis,
	benno.lossin, aliceryhl

On Fri, Aug 23, 2024 at 8:37 AM FUJITA Tomonori
<fujita.tomonori@gmail.com> wrote:
> > At this point the vendor driver looks like it does some verification:
> > it attempts to read 3.d7fd until it returns something other than 0x10
> > or 0, or times out. Could that be done here?
>
> Yeah, we better to wait here until the hw becomes ready (since the
> 8051 has just started) and check if it works correctly. A new Rust
> abstraction for msleep() is necessary.
>
> Even without the logic, the driver starts to work eventually (if the
> hw isn't broken) so I didn't include it in the patchset. I'll work on
> the abstraction and update the driver after this is merged.

It sounds okay to me to not block on this as long as it isn't glitchy
- It should probably be a FIXME?

> > Consistency nit: this file uses a mix of upper and lowercase hex
> > (mostly uppercase here) - we should probably be consistent. A quick
> > regex search looks like lowercase hex is about twice as common in the
> > kernel as uppercase so I think this may as well be updated.
>
> Ah, I'll use lowercase for all the hex in the driver.
>
> It will be a new coding rule for rust code in kernel? If so, can a
> checker tool warn this?

I don't know of any rule for this, I just noticed that the patch had
both and it made me take a look at what is used elsewhere. rustfmt has
an option to just commonize it for you, `hex_literal_case` [1], but it
is unstable. That would probably be nice at some point.

> > Overall this looks pretty good to me, checking against both the
> > datasheet and the vendor driver we have. Mostly small suggestions
> > here, I'm happy to add a RB with my verification question addressed
> > and some rewording of the 0xd001 (phy revision) comment.
>
> Thanks a lot! I'll send v7 soon.

Thanks!

- Trevor

[1]: https://rust-lang.github.io/rustfmt/?version=v1.6.0&search=#hex_literal_case

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

end of thread, other threads:[~2024-08-23 19:13 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-20 22:57 [PATCH net-next v6 0/6] net: phy: add Applied Micro QT2025 PHY driver FUJITA Tomonori
2024-08-20 22:57 ` [PATCH net-next v6 1/6] rust: sizes: add commonly used constants FUJITA Tomonori
2024-08-20 23:41   ` Greg KH
2024-08-20 23:54     ` Danilo Krummrich
2024-08-21  0:22       ` Greg KH
2024-08-21  0:14     ` FUJITA Tomonori
2024-08-20 22:57 ` [PATCH net-next v6 2/6] rust: net::phy support probe callback FUJITA Tomonori
2024-08-20 22:57 ` [PATCH net-next v6 3/6] rust: net::phy implement AsRef<kernel::device::Device> trait FUJITA Tomonori
2024-08-20 22:57 ` [PATCH net-next v6 4/6] rust: net::phy unified read/write API for C22 and C45 registers FUJITA Tomonori
2024-08-20 22:57 ` [PATCH net-next v6 5/6] rust: net::phy unified genphy_read_status function " FUJITA Tomonori
2024-08-20 22:57 ` [PATCH net-next v6 6/6] net: phy: add Applied Micro QT2025 PHY driver FUJITA Tomonori
2024-08-23  5:25   ` Trevor Gross
2024-08-23 13:36     ` FUJITA Tomonori
2024-08-23 19:13       ` Trevor Gross

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).