Live OF reconfiguration needs to create the same PHY and generic MDIO devices as initial bus population, including legacy PHY nodes that need address scanning. Factor fixed-address child registration and PHY address scanning into helpers. The old scan loop also visited every free address for a child without a reg property even when the child was not a PHY. Reject that case before scanning while preserving enumeration of valid PHY and generic MDIO children. Signed-off-by: James Hilliard --- drivers/net/mdio/of_mdio.c | 66 ++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c index b8d298c04d3f..051e449bbe7c 100644 --- a/drivers/net/mdio/of_mdio.c +++ b/drivers/net/mdio/of_mdio.c @@ -77,6 +77,15 @@ static int of_mdiobus_register_device(struct mii_bus *mdio, return 0; } +static int of_mdiobus_register_child(struct mii_bus *mdio, + struct device_node *child, u32 addr) +{ + if (of_mdiobus_child_is_phy(child)) + return of_mdiobus_register_phy(mdio, child, addr); + + return of_mdiobus_register_device(mdio, child, addr); +} + /* The following is a list of PHY compatible strings which appear in * some DTBs. The compatible string is never matched against a PHY * driver, so is pointless. We only expect devices which are not PHYs @@ -136,6 +145,32 @@ bool of_mdiobus_child_is_phy(struct device_node *child) } EXPORT_SYMBOL(of_mdiobus_child_is_phy); +static int of_mdiobus_scan_phy(struct mii_bus *mdio, + struct device_node *child) +{ + int addr, rc; + + if (!of_mdiobus_child_is_phy(child)) + return -ENODEV; + + for (addr = 0; addr < PHY_MAX_ADDR; addr++) { + if (mdiobus_is_registered_device(mdio, addr)) + continue; + + dev_info(&mdio->dev, "scan phy %pOFn at address %i\n", + child, addr); + + /* -ENODEV means that scanning should continue. */ + rc = of_mdiobus_register_child(mdio, child, addr); + if (!rc) + return 0; + if (rc != -ENODEV) + return rc; + } + + return -ENODEV; +} + static int __of_mdiobus_parse_phys(struct mii_bus *mdio, struct device_node *np, bool *scanphys) { @@ -164,10 +199,7 @@ static int __of_mdiobus_parse_phys(struct mii_bus *mdio, struct device_node *np, continue; } - if (of_mdiobus_child_is_phy(child)) - rc = of_mdiobus_register_phy(mdio, child, addr); - else - rc = of_mdiobus_register_device(mdio, child, addr); + rc = of_mdiobus_register_child(mdio, child, addr); if (rc == -ENODEV) dev_err(&mdio->dev, @@ -197,7 +229,7 @@ int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np, { struct device_node *child; bool scanphys = false; - int addr, rc; + int rc; if (!np) return __mdiobus_register(mdio, owner); @@ -238,27 +270,9 @@ int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np, of_node_name_eq(child, "ethernet-phy-package")) continue; - for (addr = 0; addr < PHY_MAX_ADDR; addr++) { - /* skip already registered PHYs */ - if (mdiobus_is_registered_device(mdio, addr)) - continue; - - /* be noisy to encourage people to set reg property */ - dev_info(&mdio->dev, "scan phy %pOFn at address %i\n", - child, addr); - - if (of_mdiobus_child_is_phy(child)) { - /* -ENODEV is the return code that PHYLIB has - * standardized on to indicate that bus - * scanning should continue. - */ - rc = of_mdiobus_register_phy(mdio, child, addr); - if (!rc) - break; - if (rc != -ENODEV) - goto put_unregister; - } - } + rc = of_mdiobus_scan_phy(mdio, child); + if (rc && rc != -ENODEV) + goto put_unregister; } return 0; -- 2.53.0