The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH net-next] net: phy: mdio-i2c: defer RollBall bridge probe to PHY discovery
@ 2026-06-04 18:12 Petr Wozniak
  2026-06-04 21:15 ` Maxime Chevallier
  2026-06-05  5:30 ` [PATCH v2 " Petr Wozniak
  0 siblings, 2 replies; 4+ messages in thread
From: Petr Wozniak @ 2026-06-04 18:12 UTC (permalink / raw)
  To: netdev
  Cc: kuba, andrew, hkallweit1, linux, davem, edumazet, pabeni,
	linux-phy, linux-kernel, maxime.chevallier, bjorn, olek2,
	Petr Wozniak

commit 8fe125892f40 ("net: phy: sfp: probe for RollBall I2C-to-MDIO
bridge in mdio-i2c") introduced a regression: for SFP modules inserted
before system boot, 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.
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.

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's 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 inserted before boot (e.g. FLYPRO
SFP-10GT-CS-30M with Aquantia AQR113C): the probe now runs after
initialization is complete and correctly returns 0 — 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>
---
 drivers/net/mdio/mdio-i2c.c   | 18 ++++--------------
 drivers/net/phy/sfp.c         | 18 ++++++++++++------
 include/linux/mdio/mdio-i2c.h |  1 +
 3 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/drivers/net/mdio/mdio-i2c.c b/drivers/net/mdio/mdio-i2c.c
--- a/drivers/net/mdio/mdio-i2c.c
+++ b/drivers/net/mdio/mdio-i2c.c
@@ -352,7 +352,7 @@
 	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 };
@@ -397,9 +397,11 @@

 	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;
@@ -419,7 +421,7 @@
 	if (ret != 1)
 		return -EIO;

-	return i2c_mii_probe_rollball(i2c);
+	return 0;
 }

 struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
@@ -444,12 +446,8 @@
 	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);
-			/* -ENODEV propagates to caller: no bridge present,
-			 * PHY probing should be skipped for this module. */
+			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
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -2028,17 +2028,8 @@ static int sfp_sm_add_mdio_bus(struct sfp *sfp)
 	dev_info(sfp->dev, "probing phy device through the [%s] protocol\n",
 		 mdio_i2c_proto_type(sfp->mdio_protocol));

-	int ret;
-
 	if (sfp->mdio_protocol == MDIO_I2C_NONE)
 		return 0;

-	ret = sfp_i2c_mdiobus_create(sfp);
-	if (ret == -ENODEV) {
-		/* Probe confirmed no bridge present; skip PHY discovery. */
-		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
@@ -2058,8 +2049,23 @@ static int sfp_sm_probe_for_phy(struct sfp *sfp)

 	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
--- a/include/linux/mdio/mdio-i2c.h
+++ b/include/linux/mdio/mdio-i2c.h
@@ -33,5 +33,6 @@

 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

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

* Re: [PATCH net-next] net: phy: mdio-i2c: defer RollBall bridge probe to PHY discovery
  2026-06-04 18:12 [PATCH net-next] net: phy: mdio-i2c: defer RollBall bridge probe to PHY discovery Petr Wozniak
@ 2026-06-04 21:15 ` Maxime Chevallier
  2026-06-05  5:30 ` [PATCH v2 " Petr Wozniak
  1 sibling, 0 replies; 4+ messages in thread
From: Maxime Chevallier @ 2026-06-04 21:15 UTC (permalink / raw)
  To: Petr Wozniak, netdev
  Cc: kuba, andrew, hkallweit1, linux, davem, edumazet, pabeni,
	linux-phy, linux-kernel, bjorn, olek2

Hi,

On 6/4/26 20:12, Petr Wozniak wrote:
> commit 8fe125892f40 ("net: phy: sfp: probe for RollBall I2C-to-MDIO
> bridge in mdio-i2c") introduced a regression: for SFP modules inserted
> before system boot, 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.
> 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.
> 
> 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's 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 inserted before boot (e.g. FLYPRO
> SFP-10GT-CS-30M with Aquantia AQR113C): the probe now runs after
> initialization is complete and correctly returns 0 — PHY detection
> proceeds normally.

I'm not sure I'm getting it, how come the init doesn't have time to complete
for modules that are present at boot, while it works for hotplugged modules ?

I'd expect modules to take even longer to init for hotplugged modules, as they
aren't sitting in the cage during the whole linux boot.

Maxime

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

* [PATCH v2 net-next] net: phy: mdio-i2c: defer RollBall bridge probe to PHY discovery
  2026-06-04 18:12 [PATCH net-next] net: phy: mdio-i2c: defer RollBall bridge probe to PHY discovery Petr Wozniak
  2026-06-04 21:15 ` Maxime Chevallier
@ 2026-06-05  5:30 ` Petr Wozniak
  2026-06-09  2:28   ` Jakub Kicinski
  1 sibling, 1 reply; 4+ messages in thread
From: Petr Wozniak @ 2026-06-05  5:30 UTC (permalink / raw)
  To: netdev
  Cc: kuba, andrew, hkallweit1, linux, davem, edumazet, pabeni,
	linux-phy, linux-kernel, maxime.chevallier, bjorn, olek2,
	Petr Wozniak

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's 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 — 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>
---
Changes in v2:
 - Generalize scope: regression affects both boot-inserted and hotplugged
   modules on hardware where bridge init exceeds 200 ms; Aleksander
   Bajkowski confirmed FLYPRO SFP-10GT-CS-30M / AQR113C broken even
   when hotplugged
 - Correct state machine description: probe runs in SFP_S_INIT (which
   follows SFP_S_WAIT), not "before initialization delays" (Jan Hoffmann)
 - No code changes from v1

 drivers/net/mdio/mdio-i2c.c   | 18 ++++--------------
 drivers/net/phy/sfp.c         | 18 ++++++++++++------
 include/linux/mdio/mdio-i2c.h |  1 +
 3 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/drivers/net/mdio/mdio-i2c.c b/drivers/net/mdio/mdio-i2c.c
--- a/drivers/net/mdio/mdio-i2c.c
+++ b/drivers/net/mdio/mdio-i2c.c
@@ -352,7 +352,7 @@
 	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 };
@@ -397,9 +397,11 @@

 	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;
@@ -419,7 +421,7 @@
 	if (ret != 1)
 		return -EIO;

-	return i2c_mii_probe_rollball(i2c);
+	return 0;
 }

 struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
@@ -444,12 +446,8 @@
 	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);
-			/* -ENODEV propagates to caller: no bridge present,
-			 * PHY probing should be skipped for this module. */
+			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
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -2028,17 +2028,8 @@ static int sfp_sm_add_mdio_bus(struct sfp *sfp)
 	dev_info(sfp->dev, "probing phy device through the [%s] protocol\n",
 		 mdio_i2c_proto_type(sfp->mdio_protocol));

-	int ret;
-
 	if (sfp->mdio_protocol == MDIO_I2C_NONE)
 		return 0;

-	ret = sfp_i2c_mdiobus_create(sfp);
-	if (ret == -ENODEV) {
-		/* Probe confirmed no bridge present; skip PHY discovery. */
-		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
@@ -2058,8 +2049,23 @@ static int sfp_sm_probe_for_phy(struct sfp *sfp)

 	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
--- a/include/linux/mdio/mdio-i2c.h
+++ b/include/linux/mdio/mdio-i2c.h
@@ -33,5 +33,6 @@

 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

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

* Re: [PATCH v2 net-next] net: phy: mdio-i2c: defer RollBall bridge probe to PHY discovery
  2026-06-05  5:30 ` [PATCH v2 " Petr Wozniak
@ 2026-06-09  2:28   ` Jakub Kicinski
  0 siblings, 0 replies; 4+ messages in thread
From: Jakub Kicinski @ 2026-06-09  2:28 UTC (permalink / raw)
  To: Petr Wozniak
  Cc: netdev, andrew, hkallweit1, linux, davem, edumazet, pabeni,
	linux-phy, linux-kernel, maxime.chevallier, bjorn, olek2

On Fri,  5 Jun 2026 07:30:56 +0200 Petr Wozniak wrote:
> 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's 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 — PHY detection proceeds normally.

$ git pw series apply 1106341
Failed to apply patch:
Applying: net: phy: mdio-i2c: defer RollBall bridge probe to PHY discovery
error: corrupt patch at .git/rebase-apply/patch:44
error: could not build fake ancestor
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Patch failed at 0001 net: phy: mdio-i2c: defer RollBall bridge probe to PHY discovery
-- 
pw-bot: cr


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

end of thread, other threads:[~2026-06-09  2:28 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-04 18:12 [PATCH net-next] net: phy: mdio-i2c: defer RollBall bridge probe to PHY discovery Petr Wozniak
2026-06-04 21:15 ` Maxime Chevallier
2026-06-05  5:30 ` [PATCH v2 " Petr Wozniak
2026-06-09  2:28   ` Jakub Kicinski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox