Commit a1affbcf authored by Florian Fainelli's avatar Florian Fainelli Committed by sanglipeng1
Browse files

net: bcmgenet: Fix EEE implementation

stable inclusion
from stable-v5.10.210
commit 9f53d24852ffe2c10c0952bdb64a1772ddbdd58f
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IAE52H

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=9f53d24852ffe2c10c0952bdb64a1772ddbdd58f



--------------------------------

commit a9f31047 upstream.

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.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarsanglipeng1 <sanglipeng1@jd.com>
parent 7bbaac2d
Loading
Loading
Loading
Loading
+8 −14
Original line number Diff line number Diff line
@@ -1248,7 +1248,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);
	u32 off = priv->hw_params->tbuf_offset + TBUF_ENERGY_CTRL;
@@ -1268,7 +1269,7 @@ static void bcmgenet_eee_enable_set(struct net_device *dev, bool enable)

	/* Enable EEE and switch to a 27Mhz clock automatically */
	reg = bcmgenet_readl(priv->base + off);
	if (enable)
	if (tx_lpi_enabled)
		reg |= TBUF_EEE_EN | TBUF_PM_EN;
	else
		reg &= ~(TBUF_EEE_EN | TBUF_PM_EN);
@@ -1289,6 +1290,7 @@ static void bcmgenet_eee_enable_set(struct net_device *dev, bool enable)

	priv->eee.eee_enabled = 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)
@@ -1304,6 +1306,7 @@ static int bcmgenet_get_eee(struct net_device *dev, struct ethtool_eee *e)

	e->eee_enabled = p->eee_enabled;
	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);

	return phy_ethtool_get_eee(dev->phydev, e);
@@ -1313,7 +1316,6 @@ static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e)
{
	struct bcmgenet_priv *priv = netdev_priv(dev);
	struct ethtool_eee *p = &priv->eee;
	int ret = 0;

	if (GENET_IS_V1(priv))
		return -EOPNOTSUPP;
@@ -1324,16 +1326,11 @@ static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e)
	p->eee_enabled = e->eee_enabled;

	if (!p->eee_enabled) {
		bcmgenet_eee_enable_set(dev, false);
		bcmgenet_eee_enable_set(dev, false, false);
	} else {
		ret = phy_init_eee(dev->phydev, 0);
		if (ret) {
			netif_err(priv, hw, dev, "EEE initialization failed\n");
			return ret;
		}

		p->eee_active = phy_init_eee(dev->phydev, false) >= 0;
		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);
@@ -4221,9 +4218,6 @@ static int bcmgenet_resume(struct device *d)
	if (!device_may_wakeup(d))
		phy_resume(dev->phydev);

	if (priv->eee.eee_enabled)
		bcmgenet_eee_enable_set(dev, true);

	bcmgenet_netif_start(dev);

	netif_device_attach(dev);
+3 −0
Original line number Diff line number Diff line
@@ -756,4 +756,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
			       enum bcmgenet_power_mode mode);

void bcmgenet_eee_enable_set(struct net_device *dev, bool enable,
			     bool tx_lpi_enabled);

#endif /* __BCMGENET_H__ */
+6 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@

#include "bcmgenet.h"


/* setup netdev link state when PHY link status change and
 * update UMAC and RGMII block when link up
 */
@@ -102,6 +103,11 @@ void bcmgenet_mii_setup(struct net_device *dev)
			reg |= CMD_TX_EN | CMD_RX_EN;
		}
		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);
	} else {
		/* done if nothing has changed */
		if (!status_changed)