--- /dev/null
+From 2f3ce7a56c6e02bc0b258507f3a82b7511f62f9e Mon Sep 17 00:00:00 2001
+From: Marek Behún <kabel@kernel.org>
+Date: Tue, 21 Nov 2023 18:20:24 +0100
+Subject: net: sfp: rework the RollBall PHY waiting code
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RollBall SFP modules allow the access to PHY registers only after a
+certain time has passed. Until then, the registers read 0xffff.
+
+Currently we have quirks for modules where we need to wait either 25
+seconds or 4 seconds, but recently I got hands on another module where
+the wait is even shorter.
+
+Instead of hardcoding different wait times, lets rework the code:
+- increase the PHY retry count to 25
+- when RollBall module is detected, increase the PHY retry time from
+ 50ms to 1s
+
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/phy/sfp.c | 41 +++++++++++++++++++++--------------------
+ 1 file changed, 21 insertions(+), 20 deletions(-)
+
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -191,7 +191,7 @@ static const enum gpiod_flags gpio_flags
+ * R_PHY_RETRY is the number of attempts.
+ */
+ #define T_PHY_RETRY msecs_to_jiffies(50)
+-#define R_PHY_RETRY 12
++#define R_PHY_RETRY 25
+
+ /* SFP module presence detection is poor: the three MOD DEF signals are
+ * the same length on the PCB, which means it's possible for MOD DEF 0 to
+@@ -273,7 +273,7 @@ struct sfp {
+ struct sfp_eeprom_id id;
+ unsigned int module_power_mW;
+ unsigned int module_t_start_up;
+- unsigned int module_t_wait;
++ unsigned int phy_t_retry;
+
+ unsigned int rate_kbd;
+ unsigned int rs_threshold_kbd;
+@@ -357,18 +357,22 @@ static void sfp_fixup_10gbaset_30m(struc
+ sfp->id.base.extended_cc = SFF8024_ECC_10GBASE_T_SR;
+ }
+
+-static void sfp_fixup_rollball_proto(struct sfp *sfp, unsigned int secs)
++static void sfp_fixup_rollball(struct sfp *sfp)
+ {
+ sfp->mdio_protocol = MDIO_I2C_ROLLBALL;
+- sfp->module_t_wait = msecs_to_jiffies(secs * 1000);
++
++ /* RollBall modules may disallow access to PHY registers for up to 25
++ * seconds, and the reads return 0xffff before that. Increase the time
++ * between PHY probe retries from 50ms to 1s so that we will wait for
++ * the PHY for a sufficient amount of time.
++ */
++ sfp->phy_t_retry = msecs_to_jiffies(1000);
+ }
+
+ static void sfp_fixup_fs_10gt(struct sfp *sfp)
+ {
+ sfp_fixup_10gbaset_30m(sfp);
+-
+- // These SFPs need 4 seconds before the PHY can be accessed
+- sfp_fixup_rollball_proto(sfp, 4);
++ sfp_fixup_rollball(sfp);
+ }
+
+ static void sfp_fixup_halny_gsfp(struct sfp *sfp)
+@@ -380,12 +384,6 @@ static void sfp_fixup_halny_gsfp(struct
+ sfp->state_hw_mask &= ~(SFP_F_TX_FAULT | SFP_F_LOS);
+ }
+
+-static void sfp_fixup_rollball(struct sfp *sfp)
+-{
+- // Rollball SFPs need 25 seconds before the PHY can be accessed
+- sfp_fixup_rollball_proto(sfp, 25);
+-}
+-
+ static void sfp_fixup_rollball_cc(struct sfp *sfp)
+ {
+ sfp_fixup_rollball(sfp);
+@@ -2319,7 +2317,7 @@ static int sfp_sm_mod_probe(struct sfp *
+ mask |= SFP_F_RS1;
+
+ sfp->module_t_start_up = T_START_UP;
+- sfp->module_t_wait = T_WAIT;
++ sfp->phy_t_retry = T_PHY_RETRY;
+
+ sfp->tx_fault_ignore = false;
+
+@@ -2553,10 +2551,9 @@ static void sfp_sm_main(struct sfp *sfp,
+
+ /* We need to check the TX_FAULT state, which is not defined
+ * while TX_DISABLE is asserted. The earliest we want to do
+- * anything (such as probe for a PHY) is 50ms (or more on
+- * specific modules).
++ * anything (such as probe for a PHY) is 50ms.
+ */
+- sfp_sm_next(sfp, SFP_S_WAIT, sfp->module_t_wait);
++ sfp_sm_next(sfp, SFP_S_WAIT, T_WAIT);
+ break;
+
+ case SFP_S_WAIT:
+@@ -2570,8 +2567,8 @@ static void sfp_sm_main(struct sfp *sfp,
+ * deasserting.
+ */
+ timeout = sfp->module_t_start_up;
+- if (timeout > sfp->module_t_wait)
+- timeout -= sfp->module_t_wait;
++ if (timeout > T_WAIT)
++ timeout -= T_WAIT;
+ else
+ timeout = 1;
+
+@@ -2614,7 +2611,11 @@ static void sfp_sm_main(struct sfp *sfp,
+ ret = sfp_sm_probe_for_phy(sfp);
+ if (ret == -ENODEV) {
+ if (--sfp->sm_phy_retries) {
+- sfp_sm_next(sfp, SFP_S_INIT_PHY, T_PHY_RETRY);
++ sfp_sm_next(sfp, SFP_S_INIT_PHY,
++ sfp->phy_t_retry);
++ dev_dbg(sfp->dev,
++ "no PHY detected, %u tries left\n",
++ sfp->sm_phy_retries);
+ break;
+ } else {
+ dev_info(sfp->dev, "no PHY detected\n");
--- /dev/null
+From e9301af385e7864dea353f5e58cad7339dd6c718 Mon Sep 17 00:00:00 2001
+From: Marek Behún <kabel@kernel.org>
+Date: Tue, 19 Dec 2023 17:24:15 +0100
+Subject: net: sfp: fix PHY discovery for FS SFP-10G-T module
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit 2f3ce7a56c6e ("net: sfp: rework the RollBall PHY waiting code")
+changed the long wait before accessing RollBall / FS modules into
+probing for PHY every 1 second, and trying 25 times.
+
+Wei Lei reports that this does not work correctly on FS modules: when
+initializing, they may report values different from 0xffff in PHY ID
+registers for some MMDs, causing get_phy_c45_ids() to find some bogus
+MMD.
+
+Fix this by adding the module_t_wait member back, and setting it to 4
+seconds for FS modules.
+
+Fixes: 2f3ce7a56c6e ("net: sfp: rework the RollBall PHY waiting code")
+Reported-by: Wei Lei <quic_leiwei@quicinc.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Tested-by: Lei Wei <quic_leiwei@quicinc.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/phy/sfp.c | 17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -273,6 +273,7 @@ struct sfp {
+ struct sfp_eeprom_id id;
+ unsigned int module_power_mW;
+ unsigned int module_t_start_up;
++ unsigned int module_t_wait;
+ unsigned int phy_t_retry;
+
+ unsigned int rate_kbd;
+@@ -373,6 +374,12 @@ static void sfp_fixup_fs_10gt(struct sfp
+ {
+ sfp_fixup_10gbaset_30m(sfp);
+ sfp_fixup_rollball(sfp);
++
++ /* The RollBall fixup is not enough for FS modules, the AQR chip inside
++ * them does not return 0xffff for PHY ID registers in all MMDs for the
++ * while initializing. They need a 4 second wait before accessing PHY.
++ */
++ sfp->module_t_wait = msecs_to_jiffies(4000);
+ }
+
+ static void sfp_fixup_halny_gsfp(struct sfp *sfp)
+@@ -2317,6 +2324,7 @@ static int sfp_sm_mod_probe(struct sfp *
+ mask |= SFP_F_RS1;
+
+ sfp->module_t_start_up = T_START_UP;
++ sfp->module_t_wait = T_WAIT;
+ sfp->phy_t_retry = T_PHY_RETRY;
+
+ sfp->tx_fault_ignore = false;
+@@ -2551,9 +2559,10 @@ static void sfp_sm_main(struct sfp *sfp,
+
+ /* We need to check the TX_FAULT state, which is not defined
+ * while TX_DISABLE is asserted. The earliest we want to do
+- * anything (such as probe for a PHY) is 50ms.
++ * anything (such as probe for a PHY) is 50ms (or more on
++ * specific modules).
+ */
+- sfp_sm_next(sfp, SFP_S_WAIT, T_WAIT);
++ sfp_sm_next(sfp, SFP_S_WAIT, sfp->module_t_wait);
+ break;
+
+ case SFP_S_WAIT:
+@@ -2567,8 +2576,8 @@ static void sfp_sm_main(struct sfp *sfp,
+ * deasserting.
+ */
+ timeout = sfp->module_t_start_up;
+- if (timeout > T_WAIT)
+- timeout -= T_WAIT;
++ if (timeout > sfp->module_t_wait)
++ timeout -= sfp->module_t_wait;
+ else
+ timeout = 1;
+
--- /dev/null
+From 6999e0fc9a552ce98fcc66bee3dca7e55fba0ed3 Mon Sep 17 00:00:00 2001
+From: Marek Behún <kabel@kernel.org>
+Date: Tue, 23 Apr 2024 10:50:38 +0200
+Subject: net: sfp: update comment for FS SFP-10G-T quirk
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Update the comment for the Fibrestore SFP-10G-T module: since commit
+e9301af385e7 ("net: sfp: fix PHY discovery for FS SFP-10G-T module")
+we also do a 4 second wait before probing the PHY.
+
+Fixes: e9301af385e7 ("net: sfp: fix PHY discovery for FS SFP-10G-T module")
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Link: https://lore.kernel.org/r/20240423085039.26957-1-kabel@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/sfp.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -454,8 +454,9 @@ static const struct sfp_quirk sfp_quirks
+ SFP_QUIRK("ALCATELLUCENT", "3FE46541AA", sfp_quirk_2500basex,
+ sfp_fixup_long_startup),
+
+- // Fiberstore SFP-10G-T doesn't identify as copper, and uses the
+- // Rollball protocol to talk to the PHY.
++ // Fiberstore SFP-10G-T doesn't identify as copper, uses the Rollball
++ // protocol to talk to the PHY and needs 4 sec wait before probing the
++ // PHY.
+ SFP_QUIRK_F("FS", "SFP-10G-T", sfp_fixup_fs_10gt),
+
+ // Fiberstore GPON-ONU-34-20BI can operate at 2500base-X, but report 1.2GBd
--- /dev/null
+From cd4a32e60061789676f7f018a94fcc9ec56732a0 Mon Sep 17 00:00:00 2001
+From: Marek Behún <kabel@kernel.org>
+Date: Tue, 23 Apr 2024 10:50:39 +0200
+Subject: net: sfp: enhance quirk for Fibrestore 2.5G copper SFP module
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Enhance the quirk for Fibrestore 2.5G copper SFP module. The original
+commit e27aca3760c0 ("net: sfp: add quirk for FS's 2.5G copper SFP")
+introducing the quirk says that the PHY is inaccessible, but that is
+not true.
+
+The module uses Rollball protocol to talk to the PHY, and needs a 4
+second wait before probing it, same as FS 10G module.
+
+The PHY inside the module is Realtek RTL8221B-VB-CG PHY. The realtek
+driver recently gained support to set it up via clause 45 accesses.
+
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Link: https://lore.kernel.org/r/20240423085039.26957-2-kabel@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/sfp.c | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -370,18 +370,23 @@ static void sfp_fixup_rollball(struct sf
+ sfp->phy_t_retry = msecs_to_jiffies(1000);
+ }
+
+-static void sfp_fixup_fs_10gt(struct sfp *sfp)
++static void sfp_fixup_fs_2_5gt(struct sfp *sfp)
+ {
+- sfp_fixup_10gbaset_30m(sfp);
+ sfp_fixup_rollball(sfp);
+
+- /* The RollBall fixup is not enough for FS modules, the AQR chip inside
++ /* The RollBall fixup is not enough for FS modules, the PHY chip inside
+ * them does not return 0xffff for PHY ID registers in all MMDs for the
+ * while initializing. They need a 4 second wait before accessing PHY.
+ */
+ sfp->module_t_wait = msecs_to_jiffies(4000);
+ }
+
++static void sfp_fixup_fs_10gt(struct sfp *sfp)
++{
++ sfp_fixup_10gbaset_30m(sfp);
++ sfp_fixup_fs_2_5gt(sfp);
++}
++
+ static void sfp_fixup_halny_gsfp(struct sfp *sfp)
+ {
+ /* Ignore the TX_FAULT and LOS signals on this module.
+@@ -459,6 +464,10 @@ static const struct sfp_quirk sfp_quirks
+ // PHY.
+ SFP_QUIRK_F("FS", "SFP-10G-T", sfp_fixup_fs_10gt),
+
++ // Fiberstore SFP-2.5G-T uses Rollball protocol to talk to the PHY and
++ // needs 4 sec wait before probing the PHY.
++ SFP_QUIRK_F("FS", "SFP-2.5G-T", sfp_fixup_fs_2_5gt),
++
+ // Fiberstore GPON-ONU-34-20BI can operate at 2500base-X, but report 1.2GBd
+ // NRZ in their EEPROM
+ SFP_QUIRK("FS", "GPON-ONU-34-20BI", sfp_quirk_2500basex,
+@@ -475,9 +484,6 @@ static const struct sfp_quirk sfp_quirks
+ SFP_QUIRK("HUAWEI", "MA5671A", sfp_quirk_2500basex,
+ sfp_fixup_ignore_tx_fault),
+
+- // FS 2.5G Base-T
+- SFP_QUIRK_M("FS", "SFP-2.5G-T", sfp_quirk_oem_2_5g),
+-
+ // Lantech 8330-262D-E can operate at 2500base-X, but incorrectly report
+ // 2500MBd NRZ in their EEPROM
+ SFP_QUIRK_M("Lantech", "8330-262D-E", sfp_quirk_2500basex),
--- /dev/null
+From 05ec5c085eb7ae044d49e04a3cff194a0b2a3251 Mon Sep 17 00:00:00 2001
+From: Martin Schiller <ms@dev.tdt.de>
+Date: Thu, 27 Feb 2025 08:10:58 +0100
+Subject: net: sfp: add quirk for FS SFP-10GM-T copper SFP+ module
+
+Add quirk for a copper SFP that identifies itself as "FS" "SFP-10GM-T".
+It uses RollBall protocol to talk to the PHY and needs 4 sec wait before
+probing the PHY.
+
+Signed-off-by: Martin Schiller <ms@dev.tdt.de>
+Link: https://patch.msgid.link/20250227071058.1520027-1-ms@dev.tdt.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/sfp.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -370,7 +370,7 @@ static void sfp_fixup_rollball(struct sf
+ sfp->phy_t_retry = msecs_to_jiffies(1000);
+ }
+
+-static void sfp_fixup_fs_2_5gt(struct sfp *sfp)
++static void sfp_fixup_rollball_wait4s(struct sfp *sfp)
+ {
+ sfp_fixup_rollball(sfp);
+
+@@ -384,7 +384,7 @@ static void sfp_fixup_fs_2_5gt(struct sf
+ static void sfp_fixup_fs_10gt(struct sfp *sfp)
+ {
+ sfp_fixup_10gbaset_30m(sfp);
+- sfp_fixup_fs_2_5gt(sfp);
++ sfp_fixup_rollball_wait4s(sfp);
+ }
+
+ static void sfp_fixup_halny_gsfp(struct sfp *sfp)
+@@ -464,9 +464,10 @@ static const struct sfp_quirk sfp_quirks
+ // PHY.
+ SFP_QUIRK_F("FS", "SFP-10G-T", sfp_fixup_fs_10gt),
+
+- // Fiberstore SFP-2.5G-T uses Rollball protocol to talk to the PHY and
+- // needs 4 sec wait before probing the PHY.
+- SFP_QUIRK_F("FS", "SFP-2.5G-T", sfp_fixup_fs_2_5gt),
++ // Fiberstore SFP-2.5G-T and SFP-10GM-T uses Rollball protocol to talk
++ // to the PHY and needs 4 sec wait before probing the PHY.
++ SFP_QUIRK_F("FS", "SFP-2.5G-T", sfp_fixup_rollball_wait4s),
++ SFP_QUIRK_F("FS", "SFP-10GM-T", sfp_fixup_rollball_wait4s),
+
+ // Fiberstore GPON-ONU-34-20BI can operate at 2500base-X, but report 1.2GBd
+ // NRZ in their EEPROM
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
-@@ -472,6 +472,9 @@ static const struct sfp_quirk sfp_quirks
- // FS 2.5G Base-T
- SFP_QUIRK_M("FS", "SFP-2.5G-T", sfp_quirk_oem_2_5g),
+@@ -485,6 +485,9 @@ static const struct sfp_quirk sfp_quirks
+ SFP_QUIRK("HUAWEI", "MA5671A", sfp_quirk_2500basex,
+ sfp_fixup_ignore_tx_fault),
+ // OEM SFP-GE-T is 1000Base-T module
+ SFP_QUIRK_F("OEM", "SFP-GE-T", sfp_fixup_ignore_tx_fault),
// Lantech 8330-262D-E can operate at 2500base-X, but incorrectly report
// 2500MBd NRZ in their EEPROM
SFP_QUIRK_M("Lantech", "8330-262D-E", sfp_quirk_2500basex),
-@@ -2590,7 +2593,8 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -2604,7 +2607,8 @@ static void sfp_sm_main(struct sfp *sfp,
* or t_start_up, so assume there is a fault.
*/
sfp_sm_fault(sfp, SFP_S_INIT_TX_FAULT,
} else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR) {
init_done:
/* Create mdiobus and start trying for PHY */
-@@ -2844,10 +2848,12 @@ static void sfp_check_state(struct sfp *
+@@ -2862,10 +2866,12 @@ static void sfp_check_state(struct sfp *
mutex_lock(&sfp->st_mutex);
state = sfp_get_state(sfp);
changed = state ^ sfp->state;
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
-@@ -1557,6 +1557,10 @@ static void sfp_hwmon_probe(struct work_
+@@ -1570,6 +1570,10 @@ static void sfp_hwmon_probe(struct work_
struct sfp *sfp = container_of(work, struct sfp, hwmon_probe.work);
int err;
/* hwmon interface needs to access 16bit registers in atomic way to
* guarantee coherency of the diagnostic monitoring data. If it is not
* possible to guarantee coherency because EEPROM is broken in such way
-@@ -2416,6 +2420,13 @@ static void sfp_sm_module(struct sfp *sf
+@@ -2430,6 +2434,13 @@ static void sfp_sm_module(struct sfp *sf
return;
}
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
-@@ -663,10 +663,64 @@ static int sfp_i2c_write(struct sfp *sfp
+@@ -676,10 +676,64 @@ static int sfp_i2c_write(struct sfp *sfp
return ret == ARRAY_SIZE(msgs) ? len : 0;
}
sfp->i2c = i2c;
sfp->read = sfp_i2c_read;
-@@ -698,6 +752,29 @@ static int sfp_i2c_mdiobus_create(struct
+@@ -711,6 +765,29 @@ static int sfp_i2c_mdiobus_create(struct
return 0;
}
static void sfp_i2c_mdiobus_destroy(struct sfp *sfp)
{
mdiobus_unregister(sfp->i2c_mii);
-@@ -1875,9 +1952,15 @@ static void sfp_sm_fault(struct sfp *sfp
+@@ -1888,9 +1965,15 @@ static void sfp_sm_fault(struct sfp *sfp
static int sfp_sm_add_mdio_bus(struct sfp *sfp)
{