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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
88f913f5ee
|
@ -1208,15 +1208,8 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
/* According to 802.3az,the EEE is supported only in full duplex-mode.
|
/* 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) &&
|
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))) {
|
|
||||||
int eee_lp, eee_cap, eee_adv;
|
int eee_lp, eee_cap, eee_adv;
|
||||||
u32 lp, cap, adv;
|
u32 lp, cap, adv;
|
||||||
int status;
|
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 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)
|
if (!phydev->drv)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
/* Mask prohibited EEE modes */
|
/* Get Supported EEE */
|
||||||
val &= ~phydev->eee_broken_modes;
|
cap = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
|
||||||
|
if (cap < 0)
|
||||||
|
return cap;
|
||||||
|
|
||||||
phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val);
|
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 */
|
||||||
|
adv &= ~phydev->eee_broken_modes;
|
||||||
|
|
||||||
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue