Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: bcmgenet: fix broken EEE by converting to phylib-managed state

The bcmgenet EEE implementation is broken in several ways.
phy_support_eee() is never called, so the PHY never advertises EEE
and phylib never sets phydev->enable_tx_lpi. bcmgenet_mac_config()
checks priv->eee.eee_enabled to decide whether to enable the MAC
LPI logic, but that field is never initialised to true, so the MAC
never enters Low Power Idle even when EEE is negotiated - wasting
the power savings EEE is designed to provide. The only way to get
EEE working at all is a manual 'ethtool --set-eee eth0 eee on' after
every link-up, and even then bcmgenet_get_eee() immediately clobbers
the reported state because phy_ethtool_get_eee() overwrites
eee_enabled and tx_lpi_enabled with the uninitialised PHY eee_cfg
values. Finally, bcmgenet_mac_config() is only called on link-up,
so EEE is never disabled in hardware on link-down.

Fix all of this by removing the MAC-side EEE state tracking
(priv->eee) and aligning with the pattern used by other non-phylink
MAC drivers such as FEC.

Call phy_support_eee() in bcmgenet_mii_probe() so the PHY advertises
EEE link modes and phylib tracks negotiation state. Move the EEE
hardware control to bcmgenet_mii_setup(), which is called on every
link event, and drive it directly from phydev->enable_tx_lpi - the
flag phylib sets when EEE is negotiated and the user has not disabled
it. This enables EEE automatically once the link partner agrees and
disables it cleanly on link-down.

Make bcmgenet_get_eee() and bcmgenet_set_eee() pure passthroughs to
phy_ethtool_get_eee() and phy_ethtool_set_eee(), with the MAC
hardware register read/written for tx_lpi_timer. Drop struct
ethtool_keee eee from struct bcmgenet_priv.

Fixes: fe0d4fd9285e ("net: phy: Keep track of EEE configuration")
Link: https://lore.kernel.org/netdev/d352039f-4cbb-41e6-9aeb-0b4f3941b54c@lunn.ch/
Suggested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Tested-by: Florian Fainelli <florian.fainelli@broadcom.com>
Link: https://patch.msgid.link/20260310054935.1238594-1-nb@tipi-net.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Nicolai Buchwitz and committed by
Jakub Kicinski
908c344d 57885276

+18 -28
+12 -19
drivers/net/ethernet/broadcom/genet/bcmgenet.c
··· 1342 1342 } 1343 1343 } 1344 1344 1345 - void bcmgenet_eee_enable_set(struct net_device *dev, bool enable, 1346 - bool tx_lpi_enabled) 1345 + void bcmgenet_eee_enable_set(struct net_device *dev, bool enable) 1347 1346 { 1348 1347 struct bcmgenet_priv *priv = netdev_priv(dev); 1349 1348 u32 off = priv->hw_params->tbuf_offset + TBUF_ENERGY_CTRL; ··· 1362 1363 1363 1364 /* Enable EEE and switch to a 27Mhz clock automatically */ 1364 1365 reg = bcmgenet_readl(priv->base + off); 1365 - if (tx_lpi_enabled) 1366 + if (enable) 1366 1367 reg |= TBUF_EEE_EN | TBUF_PM_EN; 1367 1368 else 1368 1369 reg &= ~(TBUF_EEE_EN | TBUF_PM_EN); ··· 1381 1382 priv->clk_eee_enabled = false; 1382 1383 } 1383 1384 1384 - priv->eee.eee_enabled = enable; 1385 - priv->eee.tx_lpi_enabled = tx_lpi_enabled; 1386 1385 } 1387 1386 1388 1387 static int bcmgenet_get_eee(struct net_device *dev, struct ethtool_keee *e) 1389 1388 { 1390 1389 struct bcmgenet_priv *priv = netdev_priv(dev); 1391 - struct ethtool_keee *p = &priv->eee; 1390 + int ret; 1392 1391 1393 1392 if (GENET_IS_V1(priv)) 1394 1393 return -EOPNOTSUPP; ··· 1394 1397 if (!dev->phydev) 1395 1398 return -ENODEV; 1396 1399 1397 - e->tx_lpi_enabled = p->tx_lpi_enabled; 1400 + ret = phy_ethtool_get_eee(dev->phydev, e); 1401 + if (ret) 1402 + return ret; 1403 + 1404 + /* tx_lpi_timer is maintained by the MAC hardware register; the 1405 + * PHY-level eee_cfg timer is not set for GENET. 1406 + */ 1398 1407 e->tx_lpi_timer = bcmgenet_umac_readl(priv, UMAC_EEE_LPI_TIMER); 1399 1408 1400 - return phy_ethtool_get_eee(dev->phydev, e); 1409 + return 0; 1401 1410 } 1402 1411 1403 1412 static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_keee *e) 1404 1413 { 1405 1414 struct bcmgenet_priv *priv = netdev_priv(dev); 1406 - struct ethtool_keee *p = &priv->eee; 1407 - bool active; 1408 1415 1409 1416 if (GENET_IS_V1(priv)) 1410 1417 return -EOPNOTSUPP; ··· 1416 1415 if (!dev->phydev) 1417 1416 return -ENODEV; 1418 1417 1419 - p->eee_enabled = e->eee_enabled; 1420 - 1421 - if (!p->eee_enabled) { 1422 - bcmgenet_eee_enable_set(dev, false, false); 1423 - } else { 1424 - active = phy_init_eee(dev->phydev, false) >= 0; 1425 - bcmgenet_umac_writel(priv, e->tx_lpi_timer, UMAC_EEE_LPI_TIMER); 1426 - bcmgenet_eee_enable_set(dev, active, e->tx_lpi_enabled); 1427 - } 1418 + bcmgenet_umac_writel(priv, e->tx_lpi_timer, UMAC_EEE_LPI_TIMER); 1428 1419 1429 1420 return phy_ethtool_set_eee(dev->phydev, e); 1430 1421 }
+1 -4
drivers/net/ethernet/broadcom/genet/bcmgenet.h
··· 665 665 u8 sopass[SOPASS_MAX]; 666 666 667 667 struct bcmgenet_mib_counters mib; 668 - 669 - struct ethtool_keee eee; 670 668 }; 671 669 672 670 static inline bool bcmgenet_has_40bits(struct bcmgenet_priv *priv) ··· 747 749 int bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv, 748 750 enum bcmgenet_power_mode mode); 749 751 750 - void bcmgenet_eee_enable_set(struct net_device *dev, bool enable, 751 - bool tx_lpi_enabled); 752 + void bcmgenet_eee_enable_set(struct net_device *dev, bool enable); 752 753 753 754 #endif /* __BCMGENET_H__ */
+5 -5
drivers/net/ethernet/broadcom/genet/bcmmii.c
··· 29 29 struct bcmgenet_priv *priv = netdev_priv(dev); 30 30 struct phy_device *phydev = dev->phydev; 31 31 u32 reg, cmd_bits = 0; 32 - bool active; 33 32 34 33 /* speed */ 35 34 if (phydev->speed == SPEED_1000) ··· 89 90 bcmgenet_umac_writel(priv, reg, UMAC_CMD); 90 91 spin_unlock_bh(&priv->reg_lock); 91 92 92 - active = phy_init_eee(phydev, 0) >= 0; 93 - bcmgenet_eee_enable_set(dev, 94 - priv->eee.eee_enabled && active, 95 - priv->eee.tx_lpi_enabled); 96 93 } 97 94 98 95 /* setup netdev link state when PHY link status change and ··· 107 112 reg &= ~RGMII_LINK; 108 113 bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL); 109 114 } 115 + 116 + bcmgenet_eee_enable_set(dev, phydev->enable_tx_lpi); 110 117 111 118 phy_print_status(phydev); 112 119 } ··· 408 411 409 412 /* Indicate that the MAC is responsible for PHY PM */ 410 413 dev->phydev->mac_managed_pm = true; 414 + 415 + if (!GENET_IS_V1(priv)) 416 + phy_support_eee(dev->phydev); 411 417 412 418 return 0; 413 419 }