Commit 88f913f5 authored by David S. Miller's avatar David S. Miller

Merge branch 'phylib-EEE-updates'

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: default avatarDavid S. Miller <davem@davemloft.net>
parents eefe06e8 32d75141
......@@ -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;
......@@ -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;
}
......
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