[PATCH net-next v2 7/8] net: phy: at803x: Fix SmartEEE support for some link configurations
From: Oleksij Rempel
Date: Mon Mar 27 2023 - 10:24:26 EST
This commit fixes SmartEEE support for certain link configurations on the
AR8035 PHY. Before this patch, if AR8035 was running with SmartEEE enabled
(EEE and LPI are on), it would not be able to establish a 100BaseTX/Half or
1000BaseT/Half link. A similar issue would occur with 100BaseTX/Full and an
LPI TX timer configured to less than 80 msec.
To avoid this issue, we need to keep LPI disabled before the link is
established and enable it only when a supported link configuration is
detected. By implementing this fix, the at803x driver can now correctly
handle SmartEEE features for various link configurations, improving link
establishment, compatibility, and overall performance.
Signed-off-by: Oleksij Rempel <o.rempel@xxxxxxxxxxxxxx>
---
drivers/net/phy/at803x.c | 38 +++++++++++++++++++++++++++++++++-----
1 file changed, 33 insertions(+), 5 deletions(-)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 4f65b3ebf806..5a12f778d675 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -1014,10 +1014,15 @@ static int at803x_smarteee_config(struct phy_device *phydev)
if (ret)
return ret;
- val = AT803X_MMD3_SMARTEEE_CTL3_LPI_EN |
- FIELD_PREP(AT803X_MMD3_SMARTEEE_LPI_TIME_HIGH,
- FIELD_GET(AT803X_MMD3_SMARTEEE_LPI_TIME_23_16,
- tx_lpi_timer_raw));
+ val = FIELD_PREP(AT803X_MMD3_SMARTEEE_LPI_TIME_HIGH,
+ FIELD_GET(AT803X_MMD3_SMARTEEE_LPI_TIME_23_16,
+ tx_lpi_timer_raw));
+
+ if (phydev->state == PHY_RUNNING &&
+ phy_check_valid(phydev->speed, phydev->duplex,
+ phydev->supported_eee)) {
+ val |= AT803X_MMD3_SMARTEEE_CTL3_LPI_EN;
+ }
return phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_MMD3_SMARTEEE_CTL3,
AT803X_MMD3_SMARTEEE_CTL3_LPI_EN |
@@ -1691,7 +1696,7 @@ static int at803x_get_eee(struct phy_device *phydev, struct ethtool_eee *data)
tx_timer_ns = tx_timer_raw * AT803X_MMD3_SMARTEEE_LPI_TIME_RESOL_NS;
data->tx_lpi_timer = DIV_ROUND_CLOSEST_ULL(tx_timer_ns, NSEC_PER_USEC);
- data->tx_lpi_enabled = !!(ret & AT803X_MMD3_SMARTEEE_CTL3_LPI_EN);
+ data->tx_lpi_enabled = priv->tx_lpi_on;
return genphy_c45_ethtool_get_eee(phydev, data);
}
@@ -1725,6 +1730,28 @@ static int at803x_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
return genphy_c45_ethtool_set_eee(phydev, data);
}
+static void at8035_link_change_notify(struct phy_device *phydev)
+{
+ struct at803x_priv *priv = phydev->priv;
+
+ if (phydev->mac_supports_eee || !phydev->is_smart_eee_phy)
+ return;
+
+ if (phydev->state == PHY_RUNNING) {
+ if (priv->tx_lpi_on && phy_check_valid(phydev->speed,
+ phydev->duplex,
+ phydev->supported_eee))
+ phy_set_bits_mmd(phydev, MDIO_MMD_PCS,
+ AT803X_MMD3_SMARTEEE_CTL3,
+ AT803X_MMD3_SMARTEEE_CTL3_LPI_EN);
+ } else {
+ if (priv->tx_lpi_on)
+ phy_clear_bits_mmd(phydev, MDIO_MMD_PCS,
+ AT803X_MMD3_SMARTEEE_CTL3,
+ AT803X_MMD3_SMARTEEE_CTL3_LPI_EN);
+ }
+}
+
static int qca83xx_config_init(struct phy_device *phydev)
{
u8 switch_revision;
@@ -2153,6 +2180,7 @@ static struct phy_driver at803x_driver[] = {
.cable_test_get_status = at803x_cable_test_get_status,
.get_eee = at803x_get_eee,
.set_eee = at803x_set_eee,
+ .link_change_notify = at8035_link_change_notify,
}, {
/* Qualcomm Atheros AR8030 */
.phy_id = ATH8030_PHY_ID,
--
2.30.2