Skip to content

Commit e2668c3

Browse files
Russell King (Oracle)Paolo Abeni
authored andcommitted
net: phy: fix phy_ethtool_set_eee() incorrectly enabling LPI
When phy_ethtool_set_eee_noneg() detects a change in the LPI parameters, it attempts to update phylib state and trigger the link to cycle so the MAC sees the updated parameters. However, in doing so, it sets phydev->enable_tx_lpi depending on whether the EEE configuration allows the MAC to generate LPI without taking into account the result of negotiation. This can be demonstrated with a 1000base-T FD interface by: # ethtool --set-eee eno0 advertise 8 # cause EEE to be not negotiated # ethtool --set-eee eno0 tx-lpi off # ethtool --set-eee eno0 tx-lpi on This results in being true, despite EEE not having been negotiated and: # ethtool --show-eee eno0 EEE status: enabled - inactive Tx LPI: 250 (us) Supported EEE link modes: 100baseT/Full 1000baseT/Full Advertised EEE link modes: 100baseT/Full 1000baseT/Full Fix this by keeping track of whether EEE was negotiated via a new eee_active member in struct phy_device, and include this state in the decision whether phydev->enable_tx_lpi should be set. Fixes: 3e43b90 ("net: phy: Immediately call adjust_link if only tx_lpi_enabled changes") Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> Link: https://patch.msgid.link/E1tErSe-005RhB-2R@rmk-PC.armlinux.org.uk Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent 8d5c1b8 commit e2668c3

File tree

3 files changed

+21
-13
lines changed

3 files changed

+21
-13
lines changed

drivers/net/phy/phy-c45.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1530,7 +1530,7 @@ int genphy_c45_ethtool_get_eee(struct phy_device *phydev,
15301530
return ret;
15311531

15321532
data->eee_enabled = is_enabled;
1533-
data->eee_active = ret;
1533+
data->eee_active = phydev->eee_active;
15341534
linkmode_copy(data->supported, phydev->supported_eee);
15351535

15361536
return 0;

drivers/net/phy/phy.c

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -990,14 +990,14 @@ static int phy_check_link_status(struct phy_device *phydev)
990990
phydev->state = PHY_RUNNING;
991991
err = genphy_c45_eee_is_active(phydev,
992992
NULL, NULL, NULL);
993-
if (err <= 0)
994-
phydev->enable_tx_lpi = false;
995-
else
996-
phydev->enable_tx_lpi = phydev->eee_cfg.tx_lpi_enabled;
993+
phydev->eee_active = err > 0;
994+
phydev->enable_tx_lpi = phydev->eee_cfg.tx_lpi_enabled &&
995+
phydev->eee_active;
997996

998997
phy_link_up(phydev);
999998
} else if (!phydev->link && phydev->state != PHY_NOLINK) {
1000999
phydev->state = PHY_NOLINK;
1000+
phydev->eee_active = false;
10011001
phydev->enable_tx_lpi = false;
10021002
phy_link_down(phydev);
10031003
}
@@ -1685,15 +1685,21 @@ EXPORT_SYMBOL(phy_ethtool_get_eee);
16851685
static void phy_ethtool_set_eee_noneg(struct phy_device *phydev,
16861686
const struct eee_config *old_cfg)
16871687
{
1688-
if (phydev->eee_cfg.tx_lpi_enabled != old_cfg->tx_lpi_enabled ||
1688+
bool enable_tx_lpi;
1689+
1690+
if (!phydev->link)
1691+
return;
1692+
1693+
enable_tx_lpi = phydev->eee_cfg.tx_lpi_enabled && phydev->eee_active;
1694+
1695+
if (phydev->enable_tx_lpi != enable_tx_lpi ||
16891696
phydev->eee_cfg.tx_lpi_timer != old_cfg->tx_lpi_timer) {
1690-
phydev->enable_tx_lpi = eeecfg_mac_can_tx_lpi(&phydev->eee_cfg);
1691-
if (phydev->link) {
1692-
phydev->link = false;
1693-
phy_link_down(phydev);
1694-
phydev->link = true;
1695-
phy_link_up(phydev);
1696-
}
1697+
phydev->enable_tx_lpi = false;
1698+
phydev->link = false;
1699+
phy_link_down(phydev);
1700+
phydev->enable_tx_lpi = enable_tx_lpi;
1701+
phydev->link = true;
1702+
phy_link_up(phydev);
16971703
}
16981704
}
16991705

include/linux/phy.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,7 @@ struct macsec_ops;
602602
* @supported_eee: supported PHY EEE linkmodes
603603
* @advertising_eee: Currently advertised EEE linkmodes
604604
* @enable_tx_lpi: When True, MAC should transmit LPI to PHY
605+
* @eee_active: phylib private state, indicating that EEE has been negotiated
605606
* @eee_cfg: User configuration of EEE
606607
* @lp_advertising: Current link partner advertised linkmodes
607608
* @host_interfaces: PHY interface modes supported by host
@@ -723,6 +724,7 @@ struct phy_device {
723724
/* Energy efficient ethernet modes which should be prohibited */
724725
__ETHTOOL_DECLARE_LINK_MODE_MASK(eee_broken_modes);
725726
bool enable_tx_lpi;
727+
bool eee_active;
726728
struct eee_config eee_cfg;
727729

728730
/* Host supported PHY interface types. Should be ignored if empty. */

0 commit comments

Comments
 (0)