From: Petr Wozniak <petr.wozniak@gmail.com>
To: linux@armlinux.org.uk, andrew@lunn.ch, hkallweit1@gmail.com
Cc: kuba@kernel.org, davem@davemloft.net, edumazet@google.com,
pabeni@redhat.com, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org,
maxime.chevallier@bootlin.com, bjorn@mork.no, olek2@wp.pl,
kabel@kernel.org, Petr Wozniak <petr.wozniak@gmail.com>
Subject: [PATCH net-next v3 2/2] net: phy: mdio-i2c: defer RollBall bridge probe to PHY discovery
Date: Tue, 23 Jun 2026 10:05:38 +0200 [thread overview]
Message-ID: <20260623080538.7646-3-petr.wozniak@gmail.com> (raw)
In-Reply-To: <20260623080538.7646-1-petr.wozniak@gmail.com>
commit 8fe125892f40 ("net: phy: sfp: probe for RollBall I2C-to-MDIO
bridge in mdio-i2c") introduced a regression: the RollBall I2C-to-MDIO
bridge is not yet ready to respond to CMD_READ/CMD_DONE cycles when
sfp_sm_add_mdio_bus() runs in SFP_S_INIT. The 200 ms probe times out,
i2c_mii_probe_rollball() returns -ENODEV, and sfp_sm_add_mdio_bus()
sets mdio_protocol = MDIO_I2C_NONE. By the time sfp_sm_probe_for_phy()
runs (up to ~17 s later on affected hardware), the bridge is fully
initialized but PHY probing is skipped because the protocol has already
been changed to NONE.
This affects both modules inserted before boot and hotplugged modules on
hardware where bridge initialization exceeds the 200 ms probe window
(confirmed: FLYPRO SFP-10GT-CS-30M with Aquantia AQR113C, hotplugged).
Move the probe from i2c_mii_init_rollball(), called at bus-creation time,
to sfp_sm_probe_for_phy() in sfp.c, where it runs after the SFP state
machine module initialization delays. Export the probe function as
mdio_i2c_probe_rollball() so sfp.c can call it.
For RTL8261BE-based modules the probe correctly returns -ENODEV at PHY
discovery time, causing sfp_sm_probe_for_phy() to destroy the MDIO bus
and set MDIO_I2C_NONE, eliminating the 5+ minute PHY probe retry loop.
For genuine RollBall modules (e.g. FLYPRO SFP-10GT-CS-30M with Aquantia
AQR113C) the probe now runs after initialization is complete and
correctly returns 0, so PHY detection proceeds normally.
Reported-by: Aleksander Bajkowski <olek2@wp.pl>
Fixes: 8fe125892f40 ("net: phy: sfp: probe for RollBall I2C-to-MDIO bridge in mdio-i2c")
Signed-off-by: Petr Wozniak <petr.wozniak@gmail.com>
---
v3: regenerated against net-next (v2 failed to apply due to transit
corruption); fixed block comment style (checkpatch); no functional
change.
v2: commit message only - generalized scope (Aleksander Bajkowski);
corrected SM description (Jan Hoffmann); no code change from v1.
v1: initial.
drivers/net/mdio/mdio-i2c.c | 15 +++++++++------
drivers/net/phy/sfp.c | 22 +++++++++++++---------
include/linux/mdio/mdio-i2c.h | 1 +
3 files changed, 23 insertions(+), 15 deletions(-)
diff --git a/drivers/net/mdio/mdio-i2c.c b/drivers/net/mdio/mdio-i2c.c
index b88f63234b4e..2a3a418c1369 100644
--- a/drivers/net/mdio/mdio-i2c.c
+++ b/drivers/net/mdio/mdio-i2c.c
@@ -419,7 +419,7 @@ static int i2c_mii_write_rollball(struct mii_bus *bus, int phy_id, int devad,
return 0;
}
-static int i2c_mii_probe_rollball(struct i2c_adapter *i2c)
+int mdio_i2c_probe_rollball(struct i2c_adapter *i2c)
{
u8 data_buf[] = { ROLLBALL_DATA_ADDR, 0x01, 0x00, 0x00 };
u8 cmd_buf[] = { ROLLBALL_CMD_ADDR, ROLLBALL_CMD_READ };
@@ -462,9 +462,13 @@ static int i2c_mii_probe_rollball(struct i2c_adapter *i2c)
return -ENODEV;
}
+EXPORT_SYMBOL_GPL(mdio_i2c_probe_rollball);
static int i2c_mii_init_rollball(struct i2c_adapter *i2c)
{
+ /* Send the RollBall unlock password; bridge presence is verified
+ * later, in sfp_sm_probe_for_phy(), after module initialization.
+ */
struct i2c_msg msg;
u8 pw[5];
int ret;
@@ -486,7 +490,7 @@ static int i2c_mii_init_rollball(struct i2c_adapter *i2c)
if (ret != 1)
return -EIO;
- return i2c_mii_probe_rollball(i2c);
+ return 0;
}
static bool mdio_i2c_check_functionality(struct i2c_adapter *i2c,
@@ -531,10 +535,9 @@ struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
case MDIO_I2C_ROLLBALL:
ret = i2c_mii_init_rollball(i2c);
if (ret < 0) {
- if (ret != -ENODEV)
- dev_err(parent,
- "Cannot initialize RollBall MDIO I2C protocol: %d\n",
- ret);
+ dev_err(parent,
+ "Cannot initialize RollBall MDIO I2C protocol: %d\n",
+ ret);
mdiobus_free(mii);
return ERR_PTR(ret);
}
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index c4d274ab651e..bbfaa0450798 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -2174,17 +2174,10 @@ static void sfp_sm_fault(struct sfp *sfp, unsigned int next_state, bool warn)
static int sfp_sm_add_mdio_bus(struct sfp *sfp)
{
- int ret;
-
if (sfp->mdio_protocol == MDIO_I2C_NONE)
return 0;
- ret = sfp_i2c_mdiobus_create(sfp);
- if (ret == -ENODEV) {
- sfp->mdio_protocol = MDIO_I2C_NONE;
- return 0;
- }
- return ret;
+ return sfp_i2c_mdiobus_create(sfp);
}
/* Probe a SFP for a PHY device if the module supports copper - the PHY
@@ -2215,7 +2208,18 @@ static int sfp_sm_probe_for_phy(struct sfp *sfp)
break;
case MDIO_I2C_ROLLBALL:
- err = sfp_sm_probe_phy(sfp, SFP_PHY_ADDR_ROLLBALL, true);
+ /* Probe here, after module initialization delays, so that
+ * genuine RollBall bridges have had time to start up.
+ * Modules without a bridge (e.g. RTL8261BE) return -ENODEV.
+ */
+ err = mdio_i2c_probe_rollball(sfp->i2c);
+ if (err == -ENODEV) {
+ sfp_i2c_mdiobus_destroy(sfp);
+ sfp->mdio_protocol = MDIO_I2C_NONE;
+ break;
+ }
+ if (!err)
+ err = sfp_sm_probe_phy(sfp, SFP_PHY_ADDR_ROLLBALL, true);
break;
}
diff --git a/include/linux/mdio/mdio-i2c.h b/include/linux/mdio/mdio-i2c.h
index 65b550a6fc32..5cf14f45c94b 100644
--- a/include/linux/mdio/mdio-i2c.h
+++ b/include/linux/mdio/mdio-i2c.h
@@ -20,5 +20,6 @@ enum mdio_i2c_proto {
struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
enum mdio_i2c_proto protocol);
+int mdio_i2c_probe_rollball(struct i2c_adapter *i2c);
#endif
--
2.51.0
next prev parent reply other threads:[~2026-06-23 8:05 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-23 8:05 [PATCH net-next v3 0/2] net: phy: sfp/mdio-i2c: defer RollBall probe + fix mii_bus leak Petr Wozniak
2026-06-23 8:05 ` [PATCH net-next v3 1/2] net: phy: sfp: free mii_bus in sfp_i2c_mdiobus_destroy Petr Wozniak
2026-06-23 16:23 ` Maxime Chevallier
2026-06-23 8:05 ` Petr Wozniak [this message]
2026-06-23 16:28 ` [PATCH net-next v3 2/2] net: phy: mdio-i2c: defer RollBall bridge probe to PHY discovery Maxime Chevallier
2026-06-23 16:34 ` [PATCH net-next v3 0/2] net: phy: sfp/mdio-i2c: defer RollBall probe + fix mii_bus leak Maxime Chevallier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260623080538.7646-3-petr.wozniak@gmail.com \
--to=petr.wozniak@gmail.com \
--cc=andrew@lunn.ch \
--cc=bjorn@mork.no \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=hkallweit1@gmail.com \
--cc=kabel@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-phy@lists.infradead.org \
--cc=linux@armlinux.org.uk \
--cc=maxime.chevallier@bootlin.com \
--cc=netdev@vger.kernel.org \
--cc=olek2@wp.pl \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox