mirror of
https://github.com/openwrt/openwrt.git
synced 2026-06-17 17:01:44 +04:00
realtek: dsa: postpone probe due to deferred PHYs
PHY drivers might need access to NVMEM or the filesystem to load calibration/initialization data. The driver will then return -EPROBE_DEFER to signal to the device core that the probe should be retried multiple times again in the 10s driver_deferred_probe_timeout. But when the switch driver calls dsa_register_switch(), it needs to connect the PHYs directly. As result, all PHYs without an driver will automatically get the default driver (either `genphy_c45_driver` or `genphy_driver`) assigned and initialized. But for PHYs with the additional initialization data from NVMEM/fs, this will usually result in not working PHYs. Since there are Realtek based boards with RTL826x PHYs and the new driver loads the initialization/patch values from rootfs, it is necessary to check in the beginning of the probe function whether the PHYs are ready and the probing can continue. If some driver is still without driver after the deferred probe period ended, the loading will just continue and the generic PHY drivers will still be used. Closes: #22811 Co-authored-by: Jonas Jelonek <jelonek.jonas@gmail.com> Co-authored-by: Markus Stockhausen <markus.stockhausen@gmx.de> Signed-off-by: Sven Eckelmann <sven@narfation.org> Link: https://github.com/openwrt/openwrt/pull/23075 Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
committed by
Robert Marko
parent
6a23733437
commit
ea3d646a08
@@ -211,6 +211,48 @@ u64 rtl839x_get_port_reg_le(int reg)
|
||||
return v;
|
||||
}
|
||||
|
||||
static bool rtldsa_phy_load_deferred(struct phy_device *phydev)
|
||||
{
|
||||
struct device *d = &phydev->mdio.dev;
|
||||
|
||||
if (d->driver)
|
||||
return false;
|
||||
|
||||
return driver_deferred_probe_check_state(d) == -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
static bool rtldsa_phys_load_deferred(void)
|
||||
{
|
||||
struct device_node *phy_node;
|
||||
struct phy_device *phydev;
|
||||
struct device_node *dn;
|
||||
bool deferred;
|
||||
|
||||
for_each_node_by_name(dn, "port") {
|
||||
if (!of_device_is_available(dn))
|
||||
continue;
|
||||
|
||||
phy_node = of_parse_phandle(dn, "phy-handle", 0);
|
||||
if (!phy_node)
|
||||
continue;
|
||||
|
||||
phydev = of_phy_find_device(phy_node);
|
||||
of_node_put(phy_node);
|
||||
if (!phydev)
|
||||
continue;
|
||||
|
||||
deferred = rtldsa_phy_load_deferred(phydev);
|
||||
put_device(&phydev->mdio.dev);
|
||||
|
||||
if (deferred) {
|
||||
of_node_put(dn);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
struct device_node *dn, *phy_node, *pcs_node, *led_node;
|
||||
@@ -1528,6 +1570,9 @@ static int rtl83xx_sw_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (rtldsa_phys_load_deferred())
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
err = rtldsa_ethernet_loaded(pdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
Reference in New Issue
Block a user