Commit a9f31047 authored by Florian Fainelli's avatar Florian Fainelli Committed by Jakub Kicinski

net: bcmgenet: Fix EEE implementation

We had a number of short comings:

- EEE must be re-evaluated whenever the state machine detects a link
  change as wight be switching from a link partner with EEE
  enabled/disabled

- tx_lpi_enabled controls whether EEE should be enabled/disabled for the
  transmit path, which applies to the TBUF block

- We do not need to forcibly enable EEE upon system resume, as the PHY
  state machine will trigger a link event that will do that, too

Fixes: 6ef398ea ("net: bcmgenet: add EEE support")
Signed-off-by: default avatarFlorian Fainelli <florian.fainelli@broadcom.com>
Reviewed-by: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Link: https://lore.kernel.org/r/20230606214348.2408018-1-florian.fainelli@broadcom.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent f0d75197
...@@ -1272,7 +1272,8 @@ static void bcmgenet_get_ethtool_stats(struct net_device *dev, ...@@ -1272,7 +1272,8 @@ static void bcmgenet_get_ethtool_stats(struct net_device *dev,
} }
} }
static void bcmgenet_eee_enable_set(struct net_device *dev, bool enable) void bcmgenet_eee_enable_set(struct net_device *dev, bool enable,
bool tx_lpi_enabled)
{ {
struct bcmgenet_priv *priv = netdev_priv(dev); struct bcmgenet_priv *priv = netdev_priv(dev);
u32 off = priv->hw_params->tbuf_offset + TBUF_ENERGY_CTRL; u32 off = priv->hw_params->tbuf_offset + TBUF_ENERGY_CTRL;
...@@ -1292,7 +1293,7 @@ static void bcmgenet_eee_enable_set(struct net_device *dev, bool enable) ...@@ -1292,7 +1293,7 @@ static void bcmgenet_eee_enable_set(struct net_device *dev, bool enable)
/* Enable EEE and switch to a 27Mhz clock automatically */ /* Enable EEE and switch to a 27Mhz clock automatically */
reg = bcmgenet_readl(priv->base + off); reg = bcmgenet_readl(priv->base + off);
if (enable) if (tx_lpi_enabled)
reg |= TBUF_EEE_EN | TBUF_PM_EN; reg |= TBUF_EEE_EN | TBUF_PM_EN;
else else
reg &= ~(TBUF_EEE_EN | TBUF_PM_EN); reg &= ~(TBUF_EEE_EN | TBUF_PM_EN);
...@@ -1313,6 +1314,7 @@ static void bcmgenet_eee_enable_set(struct net_device *dev, bool enable) ...@@ -1313,6 +1314,7 @@ static void bcmgenet_eee_enable_set(struct net_device *dev, bool enable)
priv->eee.eee_enabled = enable; priv->eee.eee_enabled = enable;
priv->eee.eee_active = enable; priv->eee.eee_active = enable;
priv->eee.tx_lpi_enabled = tx_lpi_enabled;
} }
static int bcmgenet_get_eee(struct net_device *dev, struct ethtool_eee *e) static int bcmgenet_get_eee(struct net_device *dev, struct ethtool_eee *e)
...@@ -1328,6 +1330,7 @@ static int bcmgenet_get_eee(struct net_device *dev, struct ethtool_eee *e) ...@@ -1328,6 +1330,7 @@ static int bcmgenet_get_eee(struct net_device *dev, struct ethtool_eee *e)
e->eee_enabled = p->eee_enabled; e->eee_enabled = p->eee_enabled;
e->eee_active = p->eee_active; e->eee_active = p->eee_active;
e->tx_lpi_enabled = p->tx_lpi_enabled;
e->tx_lpi_timer = bcmgenet_umac_readl(priv, UMAC_EEE_LPI_TIMER); e->tx_lpi_timer = bcmgenet_umac_readl(priv, UMAC_EEE_LPI_TIMER);
return phy_ethtool_get_eee(dev->phydev, e); return phy_ethtool_get_eee(dev->phydev, e);
...@@ -1337,7 +1340,6 @@ static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e) ...@@ -1337,7 +1340,6 @@ static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e)
{ {
struct bcmgenet_priv *priv = netdev_priv(dev); struct bcmgenet_priv *priv = netdev_priv(dev);
struct ethtool_eee *p = &priv->eee; struct ethtool_eee *p = &priv->eee;
int ret = 0;
if (GENET_IS_V1(priv)) if (GENET_IS_V1(priv))
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -1348,16 +1350,11 @@ static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e) ...@@ -1348,16 +1350,11 @@ static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e)
p->eee_enabled = e->eee_enabled; p->eee_enabled = e->eee_enabled;
if (!p->eee_enabled) { if (!p->eee_enabled) {
bcmgenet_eee_enable_set(dev, false); bcmgenet_eee_enable_set(dev, false, false);
} else { } else {
ret = phy_init_eee(dev->phydev, false); p->eee_active = phy_init_eee(dev->phydev, false) >= 0;
if (ret) {
netif_err(priv, hw, dev, "EEE initialization failed\n");
return ret;
}
bcmgenet_umac_writel(priv, e->tx_lpi_timer, UMAC_EEE_LPI_TIMER); bcmgenet_umac_writel(priv, e->tx_lpi_timer, UMAC_EEE_LPI_TIMER);
bcmgenet_eee_enable_set(dev, true); bcmgenet_eee_enable_set(dev, p->eee_active, e->tx_lpi_enabled);
} }
return phy_ethtool_set_eee(dev->phydev, e); return phy_ethtool_set_eee(dev->phydev, e);
...@@ -4279,9 +4276,6 @@ static int bcmgenet_resume(struct device *d) ...@@ -4279,9 +4276,6 @@ static int bcmgenet_resume(struct device *d)
if (!device_may_wakeup(d)) if (!device_may_wakeup(d))
phy_resume(dev->phydev); phy_resume(dev->phydev);
if (priv->eee.eee_enabled)
bcmgenet_eee_enable_set(dev, true);
bcmgenet_netif_start(dev); bcmgenet_netif_start(dev);
netif_device_attach(dev); netif_device_attach(dev);
......
...@@ -703,4 +703,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv, ...@@ -703,4 +703,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv, void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
enum bcmgenet_power_mode mode); enum bcmgenet_power_mode mode);
void bcmgenet_eee_enable_set(struct net_device *dev, bool enable,
bool tx_lpi_enabled);
#endif /* __BCMGENET_H__ */ #endif /* __BCMGENET_H__ */
...@@ -87,6 +87,11 @@ static void bcmgenet_mac_config(struct net_device *dev) ...@@ -87,6 +87,11 @@ static void bcmgenet_mac_config(struct net_device *dev)
reg |= CMD_TX_EN | CMD_RX_EN; reg |= CMD_TX_EN | CMD_RX_EN;
} }
bcmgenet_umac_writel(priv, reg, UMAC_CMD); bcmgenet_umac_writel(priv, reg, UMAC_CMD);
priv->eee.eee_active = phy_init_eee(phydev, 0) >= 0;
bcmgenet_eee_enable_set(dev,
priv->eee.eee_enabled && priv->eee.eee_active,
priv->eee.tx_lpi_enabled);
} }
/* setup netdev link state when PHY link status change and /* setup netdev link state when PHY link status change and
......
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