Commit d6ab9336 authored by Florian Fainelli's avatar Florian Fainelli Committed by David S. Miller

net: phy: marvell: Avoid unnecessary soft reset

The BMCR.RESET bit on the Marvell PHYs has a special meaning in that
it commits the register writes into the HW for it to latch and be
configured appropriately. Doing software resets causes link drops, and
this is unnecessary disruption if nothing changed.

Determine from marvell_set_polarity()'s return code whether the register value
was changed and if it was, propagate that to the logic that hits the software
reset bit.

This avoids doing unnecessary soft reset if the PHY is configured in
the same state it was previously, this also eliminates the need for a
m88e1111_config_aneg() function since it now is the same as
marvell_config_aneg().
Tested-by: default avatarWang, Dongsheng <dongsheng.wang@hxt-semitech.com>
Tested-by: default avatarChris Healy <cphealy@gmail.com>
Tested-by: default avatarAndrew Lunn <andrew@lunn.ch>
Tested-by: default avatarClemens Gruber <clemens.gruber@pqgruber.com>
Signed-off-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6e2d85ec
......@@ -265,7 +265,7 @@ static int marvell_set_polarity(struct phy_device *phydev, int polarity)
return err;
}
return 0;
return val != reg;
}
static int marvell_set_downshift(struct phy_device *phydev, bool enable,
......@@ -287,12 +287,15 @@ static int marvell_set_downshift(struct phy_device *phydev, bool enable,
static int marvell_config_aneg(struct phy_device *phydev)
{
int changed = 0;
int err;
err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
if (err < 0)
return err;
changed = err;
err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL,
MII_M1111_PHY_LED_DIRECT);
if (err < 0)
......@@ -302,7 +305,7 @@ static int marvell_config_aneg(struct phy_device *phydev)
if (err < 0)
return err;
if (phydev->autoneg != AUTONEG_ENABLE) {
if (phydev->autoneg != AUTONEG_ENABLE || changed) {
/* A write to speed/duplex bits (that is performed by
* genphy_config_aneg() call above) must be followed by
* a software reset. Otherwise, the write has no effect.
......@@ -350,42 +353,6 @@ static int m88e1101_config_aneg(struct phy_device *phydev)
return marvell_config_aneg(phydev);
}
static int m88e1111_config_aneg(struct phy_device *phydev)
{
int err;
/* The Marvell PHY has an errata which requires
* that certain registers get written in order
* to restart autonegotiation
*/
err = genphy_soft_reset(phydev);
err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
if (err < 0)
return err;
err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL,
MII_M1111_PHY_LED_DIRECT);
if (err < 0)
return err;
err = genphy_config_aneg(phydev);
if (err < 0)
return err;
if (phydev->autoneg != AUTONEG_ENABLE) {
/* A write to speed/duplex bits (that is performed by
* genphy_config_aneg() call above) must be followed by
* a software reset. Otherwise, the write has no effect.
*/
err = genphy_soft_reset(phydev);
if (err < 0)
return err;
}
return 0;
}
#ifdef CONFIG_OF_MDIO
/* Set and/or override some configuration registers based on the
* marvell,reg-init property stored in the of_node for the phydev.
......@@ -479,6 +446,7 @@ static int m88e1121_config_aneg_rgmii_delays(struct phy_device *phydev)
static int m88e1121_config_aneg(struct phy_device *phydev)
{
int changed = 0;
int err = 0;
if (phy_interface_is_rgmii(phydev)) {
......@@ -487,15 +455,26 @@ static int m88e1121_config_aneg(struct phy_device *phydev)
return err;
}
err = genphy_soft_reset(phydev);
err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
if (err < 0)
return err;
err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
changed = err;
err = genphy_config_aneg(phydev);
if (err < 0)
return err;
return genphy_config_aneg(phydev);
if (phydev->autoneg != autoneg || changed) {
/* A software reset is used to ensure a "commit" of the
* changes is done.
*/
err = genphy_soft_reset(phydev);
if (err < 0)
return err;
}
return 0;
}
static int m88e1318_config_aneg(struct phy_device *phydev)
......@@ -2067,7 +2046,7 @@ static struct phy_driver marvell_drivers[] = {
.flags = PHY_HAS_INTERRUPT,
.probe = marvell_probe,
.config_init = &m88e1111_config_init,
.config_aneg = &m88e1111_config_aneg,
.config_aneg = &marvell_config_aneg,
.read_status = &marvell_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment