All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Jakub Vaněk" <linuxtardis@gmail.com>
To: linux-kernel@vger.kernel.org, netdev@vger.kernel.org
Cc: "Andrew Lunn" <andrew@lunn.ch>,
	"Heiner Kallweit" <hkallweit1@gmail.com>,
	"Russell King" <linux@armlinux.org.uk>,
	"David S. Miller" <davem@davemloft.net>,
	"Eric Dumazet" <edumazet@google.com>,
	"Jakub Kicinski" <kuba@kernel.org>,
	"Paolo Abeni" <pabeni@redhat.com>,
	Frank <Frank.Sae@motor-comm.com>,
	"Sai Krishna" <saikrishnag@marvell.com>,
	"Daniel Golle" <daniel@makrotopia.org>,
	"Jakub Vaněk" <linuxtardis@gmail.com>
Subject: [PATCH net-next v2 2/5] of: mdio: Scan PHY address 0 last
Date: Sun,  1 Mar 2026 00:22:38 +0100	[thread overview]
Message-ID: <20260228232241.1274236-3-linuxtardis@gmail.com> (raw)
In-Reply-To: <20260228232241.1274236-1-linuxtardis@gmail.com>

Some PHY devices incorrectly treat address 0 as a broadcast address.
As a result, accesses to address 0 may cause multiple PHYs to respond,
making one or both PHYs work unreliably.

On several PHYs (e.g. Motorcomm YT8821 and Realtek RTL8221B), this
behavior can be disabled via a vendor-specific internal register.
However, for that to be useful, that register would have to be
programmed before address 0 is accessed for the first time.

Device Tree-based systems scan MDIO buses via of_mdiobus_register().
Modify the scanning order so that address 0 is scanned last. This
ensures PHY fixups for addresses 1-31 are applied before address 0
is accessed, allowing the collision to be prevented.

However, preserve the original probing order for one edge case: when
the Device Tree does not explicitly specify PHY addresses. In that
scenario, PHY DT nodes appear to be matched to devices based on a
sequential bus scan. Changing the scanning sequence could change
the association between DT nodes and PHY devices and potentially break
existing setups.

For example, with:

    mdio-bus {
        phy0: ethernet-phy {
            compatible = "ethernet-phy-id1234.5678";
        };
        phy1: ethernet-phy {
            compatible = "ethernet-phy-id90AB.CDEF";
        };
    };

scanning address 0 last could cause the PHY on address 0 to be associated
with the phy1 node.

Suggested-by: Daniel Golle <daniel@makrotopia.org>
Signed-off-by: Jakub Vaněk <linuxtardis@gmail.com>
---
 drivers/net/mdio/of_mdio.c | 35 +++++++++++++++++++++++++++++++----
 1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c
index b8d298c04d3f..a705991f6b04 100644
--- a/drivers/net/mdio/of_mdio.c
+++ b/drivers/net/mdio/of_mdio.c
@@ -27,6 +27,11 @@ MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("OpenFirmware MDIO bus (Ethernet PHY) accessors");
 
+enum scan_phase {
+	SCAN_PHASE_NOT_PHYAD_0,
+	SCAN_PHASE_PHYAD_0,
+};
+
 /* Extract the clause 22 phy ID from the compatible string of the form
  * ethernet-phy-idAAAA.BBBB */
 static int of_get_phy_id(struct device_node *device, u32 *phy_id)
@@ -137,7 +142,7 @@ bool of_mdiobus_child_is_phy(struct device_node *child)
 EXPORT_SYMBOL(of_mdiobus_child_is_phy);
 
 static int __of_mdiobus_parse_phys(struct mii_bus *mdio, struct device_node *np,
-				   bool *scanphys)
+				   bool *scanphys, enum scan_phase phase)
 {
 	struct device_node *child;
 	int addr, rc = 0;
@@ -149,7 +154,7 @@ static int __of_mdiobus_parse_phys(struct mii_bus *mdio, struct device_node *np,
 			if (!of_property_present(child, "reg"))
 				continue;
 
-			rc = __of_mdiobus_parse_phys(mdio, child, NULL);
+			rc = __of_mdiobus_parse_phys(mdio, child, NULL, phase);
 			if (rc && rc != -ENODEV)
 				goto exit;
 
@@ -164,6 +169,12 @@ static int __of_mdiobus_parse_phys(struct mii_bus *mdio, struct device_node *np,
 			continue;
 		}
 
+		if (phase == SCAN_PHASE_NOT_PHYAD_0 && addr == 0)
+			continue;
+
+		if (phase == SCAN_PHASE_PHYAD_0 && addr != 0)
+			continue;
+
 		if (of_mdiobus_child_is_phy(child))
 			rc = of_mdiobus_register_phy(mdio, child, addr);
 		else
@@ -223,8 +234,19 @@ int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np,
 	if (rc)
 		return rc;
 
-	/* Loop over the child nodes and register a phy_device for each phy */
-	rc = __of_mdiobus_parse_phys(mdio, np, &scanphys);
+	/* Loop over the child nodes and register a phy_device for each phy.
+	 * However, scan address 0 last. Some vendors consider it a broadcast
+	 * address and so their PHYs respond at it in addition to the actual PHY
+	 * address. Scanning addresses 1-31 first allows PHY fixups to stop
+	 * the potential collision at address 0 from occurring.
+	 */
+	rc = __of_mdiobus_parse_phys(mdio, np, &scanphys,
+				     SCAN_PHASE_NOT_PHYAD_0);
+	if (rc)
+		goto unregister;
+
+	rc = __of_mdiobus_parse_phys(mdio, np, &scanphys,
+				     SCAN_PHASE_PHYAD_0);
 	if (rc)
 		goto unregister;
 
@@ -238,6 +260,11 @@ int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np,
 		    of_node_name_eq(child, "ethernet-phy-package"))
 			continue;
 
+		/* Skip the SCAN_PHASE_NOT_PHYAD_0/SCAN_PHASE_PHYAD_0
+		 * stuff here. Some device tree setups may assume linear
+		 * assignment from address 0 onwards and the two-pass probing
+		 * is not worth breaking these setups.
+		 */
 		for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
 			/* skip already registered PHYs */
 			if (mdiobus_is_registered_device(mdio, addr))
-- 
2.43.0


  parent reply	other threads:[~2026-02-28 23:23 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-28 23:22 [PATCH net-next v2 0/5] net: phy: Disable MDIO broadcast address on YT8821 Jakub Vaněk
2026-02-28 23:22 ` [PATCH net-next v2 1/5] net: mdiobus: Scan buses in reverse order (31 -> 0) Jakub Vaněk
2026-03-01 15:11   ` Andrew Lunn
2026-03-01 17:03   ` Russell King (Oracle)
2026-03-01 17:24     ` Jakub Vaněk
2026-02-28 23:22 ` Jakub Vaněk [this message]
2026-02-28 23:22 ` [PATCH net-next v2 3/5] net: phy: Support PHY fixups on Clause 45 PHYs Jakub Vaněk
2026-02-28 23:22 ` [PATCH net-next v2 4/5] net: phy: Add infrastructure for PHY address 0 fixups Jakub Vaněk
2026-02-28 23:22 ` [PATCH net-next v2 5/5] net: phy: motorcomm: yt8821: Disable MDIO broadcast Jakub Vaněk
2026-03-01  2:43   ` kernel test robot
2026-03-01 16:06 ` [PATCH net-next v2 0/5] net: phy: Disable MDIO broadcast address on YT8821 Andrew Lunn
2026-03-01 17:07   ` Russell King (Oracle)
2026-03-01 17:15   ` Jakub Vaněk

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=20260228232241.1274236-3-linuxtardis@gmail.com \
    --to=linuxtardis@gmail.com \
    --cc=Frank.Sae@motor-comm.com \
    --cc=andrew@lunn.ch \
    --cc=daniel@makrotopia.org \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=hkallweit1@gmail.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=saikrishnag@marvell.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.