On Wed, 8 Apr 2020 23:43:26 +0200 Clemens Gruber wrote: > The negotiation of flow control / pause frame modes was broken since > commit fcf1f59afc67 ("net: phy: marvell: rearrange to use > genphy_read_lpa()") moved the setting of phydev->duplex below the > phy_resolve_aneg_pause call. Due to a check of DUPLEX_FULL in that > function, phydev->pause was no longer set. > > Fix it by moving the parsing of the status variable before the blocks > dealing with the pause frames. > > Fixes: fcf1f59afc67 ("net: phy: marvell: rearrange to use genphy_read_lpa()") > Cc: stable@xxxxxxxxxxxxxxx # v5.6+ nit: please don't CC stable on networking patches > Signed-off-by: Clemens Gruber <clemens.gruber@xxxxxxxxxxxx> > --- > drivers/net/phy/marvell.c | 44 +++++++++++++++++++-------------------- > 1 file changed, 22 insertions(+), 22 deletions(-) > > diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c > index 4714ca0e0d4b..02cde4c0668c 100644 > --- a/drivers/net/phy/marvell.c > +++ b/drivers/net/phy/marvell.c > @@ -1263,6 +1263,28 @@ static int marvell_read_status_page_an(struct phy_device *phydev, > int lpa; > int err; > > + if (!(status & MII_M1011_PHY_STATUS_RESOLVED)) > + return 0; If we return early here won't we miss updating the advertising bits? We will no longer call e.g. fiber_lpa_mod_linkmode_lpa_t(). Perhaps extracting info from status should be moved to a helper so we can return early without affecting the rest of the flow? Is my understanding correct? Russell? > + if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) > + phydev->duplex = DUPLEX_FULL; > + else > + phydev->duplex = DUPLEX_HALF; > + > + switch (status & MII_M1011_PHY_STATUS_SPD_MASK) { > + case MII_M1011_PHY_STATUS_1000: > + phydev->speed = SPEED_1000; > + break; > + > + case MII_M1011_PHY_STATUS_100: > + phydev->speed = SPEED_100; > + break; > + > + default: > + phydev->speed = SPEED_10; > + break; > + } > + > if (!fiber) { > err = genphy_read_lpa(phydev); > if (err < 0) > @@ -1291,28 +1313,6 @@ static int marvell_read_status_page_an(struct phy_device *phydev, > } > } > > - if (!(status & MII_M1011_PHY_STATUS_RESOLVED)) > - return 0; > - > - if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) > - phydev->duplex = DUPLEX_FULL; > - else > - phydev->duplex = DUPLEX_HALF; > - > - switch (status & MII_M1011_PHY_STATUS_SPD_MASK) { > - case MII_M1011_PHY_STATUS_1000: > - phydev->speed = SPEED_1000; > - break; > - > - case MII_M1011_PHY_STATUS_100: > - phydev->speed = SPEED_100; > - break; > - > - default: > - phydev->speed = SPEED_10; > - break; > - } > - > return 0; > } >