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.

Merge branch 'net-phy-add-support-for-disabling-autonomous-eee'

Nicolai Buchwitz says:

====================
net: phy: add support for disabling autonomous EEE

Some PHYs implement autonomous EEE where the PHY manages EEE
independently, preventing the MAC from controlling LPI signaling.
This conflicts with MACs that implement their own LPI control.

This series adds a .disable_autonomous_eee callback to struct phy_driver
and calls it from phy_support_eee(). When a MAC indicates it supports
EEE, the PHY's autonomous EEE is automatically disabled. The setting is
persisted across suspend/resume by re-applying it in phy_init_hw() after
soft reset, following the same pattern suggested by Russell King for PHY
tunables [1].

Patch 1 adds the phylib infrastructure.
Patch 2 implements it for Broadcom BCM54xx (AutogrEEEn).
Patch 3 converts the Realtek RTL8211F, which previously unconditionally
disabled PHY-mode EEE in config_init.

This came up while adding EEE support to the Cadence macb driver (used
on Raspberry Pi 5 with a BCM54210PE PHY). The PHY's AutogrEEEn mode
prevented the MAC from tracking LPI state. The Realtek RTL8211F has
the same pattern, unconditionally disabling PHY-mode EEE with the
comment "Disable PHY-mode EEE so LPI is passed to the MAC".

Other BCM54xx PHYs likely have the same AutogrEEEn register layout,
but I only have access to the BCM54210PE/BCM54213PE datasheets. It
would be appreciated if Florian or others could confirm which other
BCM54xx variants share this register so we can wire them up too.

Tested on Raspberry Pi CM4 (bcmgenet + BCM54210PE),
Raspberry Pi CM5 (Cadence GEM + BCM54210PE) and
Raspberry Pi 5 (Cadence GEM + BCM54213PE).

[1] https://lore.kernel.org/netdev/acuwvoydmJusuj9x@shell.armlinux.org.uk/
====================

Link: https://patch.msgid.link/20260406-devel-autonomous-eee-v1-0-b335e7143711@tipi-net.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+50 -3
+7
drivers/net/phy/broadcom.c
··· 1452 1452 return genphy_read_status(phydev); 1453 1453 } 1454 1454 1455 + static int bcm54xx_disable_autonomous_eee(struct phy_device *phydev) 1456 + { 1457 + return bcm_phy_modify_exp(phydev, BCM54XX_TOP_MISC_MII_BUF_CNTL0, 1458 + BCM54XX_MII_BUF_CNTL0_AUTOGREEEN_EN, 0); 1459 + } 1460 + 1455 1461 static struct phy_driver broadcom_drivers[] = { 1456 1462 { 1457 1463 PHY_ID_MATCH_MODEL(PHY_ID_BCM5411), ··· 1501 1495 .get_wol = bcm54xx_phy_get_wol, 1502 1496 .set_wol = bcm54xx_phy_set_wol, 1503 1497 .led_brightness_set = bcm_phy_led_brightness_set, 1498 + .disable_autonomous_eee = bcm54xx_disable_autonomous_eee, 1504 1499 }, { 1505 1500 PHY_ID_MATCH_MODEL(PHY_ID_BCM5461), 1506 1501 .name = "Broadcom BCM5461",
+22
drivers/net/phy/phy_device.c
··· 1375 1375 return ret; 1376 1376 } 1377 1377 1378 + /* Re-apply autonomous EEE disable after soft reset */ 1379 + if (phydev->autonomous_eee_disabled && 1380 + phydev->drv->disable_autonomous_eee) { 1381 + ret = phydev->drv->disable_autonomous_eee(phydev); 1382 + if (ret) 1383 + return ret; 1384 + } 1385 + 1378 1386 return 0; 1379 1387 } 1380 1388 EXPORT_SYMBOL(phy_init_hw); ··· 2906 2898 linkmode_copy(phydev->advertising_eee, phydev->supported_eee); 2907 2899 phydev->eee_cfg.tx_lpi_enabled = true; 2908 2900 phydev->eee_cfg.eee_enabled = true; 2901 + 2902 + /* If the PHY supports autonomous EEE, disable it so the MAC can 2903 + * manage LPI signaling instead. The flag is stored so it can be 2904 + * re-applied after a PHY soft reset (e.g. suspend/resume). 2905 + */ 2906 + if (phydev->drv && phydev->drv->disable_autonomous_eee) { 2907 + int ret = phydev->drv->disable_autonomous_eee(phydev); 2908 + 2909 + if (ret) 2910 + phydev_warn(phydev, "Failed to disable autonomous EEE: %pe\n", 2911 + ERR_PTR(ret)); 2912 + else 2913 + phydev->autonomous_eee_disabled = true; 2914 + } 2909 2915 } 2910 2916 EXPORT_SYMBOL(phy_support_eee); 2911 2917
+4 -3
drivers/net/phy/realtek/realtek_main.c
··· 726 726 return phy_modify(phydev, RTL8211F_PHYCR1, mask, mask); 727 727 } 728 728 729 - static int rtl8211f_config_phy_eee(struct phy_device *phydev) 729 + static int rtl8211f_disable_autonomous_eee(struct phy_device *phydev) 730 730 { 731 - /* Disable PHY-mode EEE so LPI is passed to the MAC */ 732 731 return phy_modify(phydev, RTL8211F_PHYCR2, 733 732 RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); 734 733 } ··· 865 866 return ret; 866 867 } 867 868 868 - return rtl8211f_config_phy_eee(phydev); 869 + return 0; 869 870 } 870 871 871 872 static int rtl821x_suspend(struct phy_device *phydev) ··· 2459 2460 .led_hw_is_supported = rtl8211x_led_hw_is_supported, 2460 2461 .led_hw_control_get = rtl8211f_led_hw_control_get, 2461 2462 .led_hw_control_set = rtl8211f_led_hw_control_set, 2463 + .disable_autonomous_eee = rtl8211f_disable_autonomous_eee, 2462 2464 }, { 2463 2465 PHY_ID_MATCH_EXACT(RTL_8211FVD_PHYID), 2464 2466 .name = "RTL8211F-VD Gigabit Ethernet", ··· 2476 2476 .led_hw_is_supported = rtl8211x_led_hw_is_supported, 2477 2477 .led_hw_control_get = rtl8211f_led_hw_control_get, 2478 2478 .led_hw_control_set = rtl8211f_led_hw_control_set, 2479 + .disable_autonomous_eee = rtl8211f_disable_autonomous_eee, 2479 2480 }, { 2480 2481 .name = "Generic FE-GE Realtek PHY", 2481 2482 .match_phy_device = rtlgen_match_phy_device,
+3
include/linux/brcmphy.h
··· 266 266 #define BCM54XX_TOP_MISC_IDDQ_SD (1 << 2) 267 267 #define BCM54XX_TOP_MISC_IDDQ_SR (1 << 3) 268 268 269 + #define BCM54XX_TOP_MISC_MII_BUF_CNTL0 (MII_BCM54XX_EXP_SEL_TOP + 0x00) 270 + #define BCM54XX_MII_BUF_CNTL0_AUTOGREEEN_EN BIT(0) 271 + 269 272 #define BCM54XX_TOP_MISC_LED_CTL (MII_BCM54XX_EXP_SEL_TOP + 0x0C) 270 273 #define BCM54XX_LED4_SEL_INTR BIT(1) 271 274
+14
include/linux/phy.h
··· 612 612 * @advertising_eee: Currently advertised EEE linkmodes 613 613 * @enable_tx_lpi: When True, MAC should transmit LPI to PHY 614 614 * @eee_active: phylib private state, indicating that EEE has been negotiated 615 + * @autonomous_eee_disabled: Set when autonomous EEE has been disabled, 616 + * used to re-apply after PHY soft reset 615 617 * @eee_cfg: User configuration of EEE 616 618 * @lp_advertising: Current link partner advertised linkmodes 617 619 * @host_interfaces: PHY interface modes supported by host ··· 741 739 __ETHTOOL_DECLARE_LINK_MODE_MASK(eee_disabled_modes); 742 740 bool enable_tx_lpi; 743 741 bool eee_active; 742 + bool autonomous_eee_disabled; 744 743 struct eee_config eee_cfg; 745 744 746 745 /* Host supported PHY interface types. Should be ignored if empty. */ ··· 1361 1358 /** @get_stats: Return the statistic counter values */ 1362 1359 void (*get_stats)(struct phy_device *dev, 1363 1360 struct ethtool_stats *stats, u64 *data); 1361 + 1362 + /** 1363 + * @disable_autonomous_eee: Disable PHY-autonomous EEE 1364 + * 1365 + * Some PHYs manage EEE autonomously, preventing the MAC from 1366 + * controlling LPI signaling. This callback disables autonomous 1367 + * EEE at the PHY. 1368 + * 1369 + * Return: 0 on success, negative errno on failure. 1370 + */ 1371 + int (*disable_autonomous_eee)(struct phy_device *dev); 1364 1372 1365 1373 /* Get and Set PHY tunables */ 1366 1374 /** @get_tunable: Return the value of a tunable */