[PATCH net-next v2 4/5] net: phy: Add infrastructure for PHY address 0 fixups

From: Jakub Vaněk

Date: Sat Feb 28 2026 - 18:25:48 EST


Certain PHYs incorrectly treat MDIO address 0 as a broadcast address and
therefore respond both at address 0 and at their assigned address.
As outlined in the code, this is problematic. Provide a way to
disable this behaviour via a PHY fixup.

It would be ideal to have these collisions prevented early
by the bootloader, but there may be hardware (e.g. WiFi routers)
out there where the bootloader doesn't do this and cannot be easily
replaced.

Signed-off-by: Jakub Vaněk <linuxtardis@xxxxxxxxx>
---
drivers/net/phy/Makefile | 3 ++-
drivers/net/phy/phy_common_fixups.c | 26 ++++++++++++++++++++++++++
drivers/net/phy/phy_device.c | 4 ++++
drivers/net/phy/phylib-internal.h | 2 ++
4 files changed, 34 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/phy/phy_common_fixups.c

diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 3a34917adea7..3bf9ba208b90 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -3,7 +3,8 @@

libphy-y := phy.o phy-c45.o phy-core.o phy_device.o \
linkmode.o phy_link_topology.o \
- phy_caps.o mdio_bus_provider.o phy_port.o
+ phy_caps.o mdio_bus_provider.o phy_port.o \
+ phy_common_fixups.o
mdio-bus-y += mdio_bus.o mdio_device.o

ifdef CONFIG_PHYLIB
diff --git a/drivers/net/phy/phy_common_fixups.c b/drivers/net/phy/phy_common_fixups.c
new file mode 100644
index 000000000000..fa51c6d7b25f
--- /dev/null
+++ b/drivers/net/phy/phy_common_fixups.c
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/phy.h>
+
+#include "phylib-internal.h"
+
+/**
+ * phy_register_address_0_fixups - Register fixups for disabling MDIO
+ * broadcast address 0
+ *
+ * Some vendors interpret MDIO address 0 as a broadcast address and so their
+ * PHYs initially respond both at address 0 as well as at their normal
+ * address. This is problematic:
+ * - Linux may create two struct phy_device for a single device.
+ * - MDIO address collision may occur if there is another PHY
+ * legitimately listening on address 0.
+ *
+ * The broadcast address can often be disabled through some internal
+ * PHY register. These fixups are designed to do just that --
+ * they shall stop these PHYs from responding at address 0 before
+ * the MDIO address 0 is scanned for devices.
+ */
+int phy_register_address_0_fixups(void)
+{
+ return 0;
+}
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index db187d370eaa..2d4f119b45b4 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -3969,6 +3969,10 @@ static int __init phy_init(void)
if (rc)
goto err_ethtool_phy_ops;

+ rc = phy_register_address_0_fixups();
+ if (rc)
+ goto err_ethtool_phy_ops;
+
features_init();

rc = phy_driver_register(&genphy_c45_driver, THIS_MODULE);
diff --git a/drivers/net/phy/phylib-internal.h b/drivers/net/phy/phylib-internal.h
index dc9592c6bb8e..1e6ff8f2d721 100644
--- a/drivers/net/phy/phylib-internal.h
+++ b/drivers/net/phy/phylib-internal.h
@@ -22,4 +22,6 @@ void phy_check_downshift(struct phy_device *phydev);

int genphy_c45_read_eee_adv(struct phy_device *phydev, unsigned long *adv);

+int phy_register_address_0_fixups(void);
+
#endif /* __PHYLIB_INTERNAL_H */
--
2.43.0