Hi, On 4/20/21 12:29 PM, Michael Walle wrote: > The commit c329e5afb42f ("net: phy: at803x: select correct page on > config init") selects the copper page during probe. This fails if the > copper page was already selected. In this case, the value of the copper > page (which is 1) is propagated through phy_restore_page() and is > finally returned for at803x_probe(). Fix it, by just using the > at803x_page_write() directly.
Ouch, i didn't spot that. Thanks for taking care. > > Also in case of an error, the regulator is not disabled and leads to a > WARN_ON() when the probe fails. This couldn't happen before, because > at803x_parse_dt() was the last call in at803x_probe(). It is hard to > see, that the parse_dt() actually enables the regulator. Thus move the > regulator_enable() to the probe function and undo it in case of an > error. > > Fixes: c329e5afb42f ("net: phy: at803x: select correct page on config init") > Signed-off-by: Michael Walle <mich...@walle.cc> Reviewed-by: David Bauer <m...@david-bauer.net> Best David > --- > Changes since v1: > - take the bus lock > > drivers/net/phy/at803x.c | 23 +++++++++++++++++------ > 1 file changed, 17 insertions(+), 6 deletions(-) > > diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c > index e0f56850edc5..32af52dd5aed 100644 > --- a/drivers/net/phy/at803x.c > +++ b/drivers/net/phy/at803x.c > @@ -554,10 +554,6 @@ static int at803x_parse_dt(struct phy_device *phydev) > phydev_err(phydev, "failed to get VDDIO regulator\n"); > return PTR_ERR(priv->vddio); > } > - > - ret = regulator_enable(priv->vddio); > - if (ret < 0) > - return ret; > } > > return 0; > @@ -579,15 +575,30 @@ static int at803x_probe(struct phy_device *phydev) > if (ret) > return ret; > > + if (priv->vddio) { > + ret = regulator_enable(priv->vddio); > + if (ret < 0) > + return ret; > + } > + > /* Some bootloaders leave the fiber page selected. > * Switch to the copper page, as otherwise we read > * the PHY capabilities from the fiber side. > */ > if (at803x_match_phy_id(phydev, ATH8031_PHY_ID)) { > - ret = phy_select_page(phydev, AT803X_PAGE_COPPER); > - ret = phy_restore_page(phydev, AT803X_PAGE_COPPER, ret); > + phy_lock_mdio_bus(phydev); > + ret = at803x_write_page(phydev, AT803X_PAGE_COPPER); > + phy_unlock_mdio_bus(phydev); > + if (ret) > + goto err; > } > > + return 0; > + > +err: > + if (priv->vddio) > + regulator_disable(priv->vddio); > + > return ret; > } > >