Skip to content

Commit

Permalink
Merge branch 'phylib-EEE-updates'
Browse files Browse the repository at this point in the history
Russell King says:

====================
phylib EEE updates

This series of patches depends on the previous set of changes, and is
therefore net-next material.

While testing the EEE code, I discovered a number of issues:

1. It is possible to enable advertisment of EEE modes which are not
   supported by the hardware.  We omit to check the supported modes
   and mask off those modes that are not supported before writing the
   EEE advertisment register.

2. We need to restart autonegotiation after a change of the EEE
   advertisment, otherwise the link partner does not see the updated
   EEE modes.

3. SGMII connected PHYs are also capable of supporting EEE.

Through discussion with Florian, it has been decided to remove the check
for the PHY interface mode in patch (3).
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 2, 2017
2 parents eefe06e + 32d7514 commit 88f913f
Showing 1 changed file with 26 additions and 11 deletions.
37 changes: 26 additions & 11 deletions drivers/net/phy/phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -1208,15 +1208,8 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
return -EIO;

/* According to 802.3az,the EEE is supported only in full duplex-mode.
* Also EEE feature is active when core is operating with MII, GMII
* or RGMII (all kinds). Internal PHYs are also allowed to proceed and
* should return an error if they do not support EEE.
*/
if ((phydev->duplex == DUPLEX_FULL) &&
((phydev->interface == PHY_INTERFACE_MODE_MII) ||
(phydev->interface == PHY_INTERFACE_MODE_GMII) ||
phy_interface_is_rgmii(phydev) ||
phy_is_internal(phydev))) {
if (phydev->duplex == DUPLEX_FULL) {
int eee_lp, eee_cap, eee_adv;
u32 lp, cap, adv;
int status;
Expand Down Expand Up @@ -1332,15 +1325,37 @@ EXPORT_SYMBOL(phy_ethtool_get_eee);
*/
int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
{
int val = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
int cap, old_adv, adv, ret;

if (!phydev->drv)
return -EIO;

/* Get Supported EEE */
cap = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
if (cap < 0)
return cap;

old_adv = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
if (old_adv < 0)
return old_adv;

adv = ethtool_adv_to_mmd_eee_adv_t(data->advertised) & cap;

/* Mask prohibited EEE modes */
val &= ~phydev->eee_broken_modes;
adv &= ~phydev->eee_broken_modes;

phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val);
if (old_adv != adv) {
ret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, adv);
if (ret < 0)
return ret;

/* Restart autonegotiation so the new modes get sent to the
* link partner.
*/
ret = genphy_restart_aneg(phydev);
if (ret < 0)
return ret;
}

return 0;
}
Expand Down

0 comments on commit 88f913f

Please sign in to comment.