Skip to content

Commit 760b5e3

Browse files
oleremNipaLocal
authored andcommitted
net: usb: lan78xx: Integrate EEE support with phylink LPI API
Refactor Energy-Efficient Ethernet (EEE) support in the LAN78xx driver to fully integrate with the phylink Low Power Idle (LPI) API. This includes: - Replacing direct calls to `phy_ethtool_get_eee` and `phy_ethtool_set_eee` with `phylink_ethtool_get_eee` and `phylink_ethtool_set_eee`. - Implementing `.mac_enable_tx_lpi` and `.mac_disable_tx_lpi` to control LPI transitions via phylink. - Configuring `lpi_timer_default` to align with recommended values from LAN7800 documentation. - ensure EEE is disabled on controller reset Signed-off-by: Oleksij Rempel <[email protected]> Reviewed-by: Russell King (Oracle) <[email protected]> Signed-off-by: NipaLocal <nipa@local>
1 parent 2624b58 commit 760b5e3

File tree

1 file changed

+79
-44
lines changed

1 file changed

+79
-44
lines changed

drivers/net/usb/lan78xx.c

Lines changed: 79 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1789,54 +1789,15 @@ static int lan78xx_set_wol(struct net_device *netdev,
17891789
static int lan78xx_get_eee(struct net_device *net, struct ethtool_keee *edata)
17901790
{
17911791
struct lan78xx_net *dev = netdev_priv(net);
1792-
struct phy_device *phydev = net->phydev;
1793-
int ret;
1794-
u32 buf;
1795-
1796-
ret = usb_autopm_get_interface(dev->intf);
1797-
if (ret < 0)
1798-
return ret;
1799-
1800-
ret = phy_ethtool_get_eee(phydev, edata);
1801-
if (ret < 0)
1802-
goto exit;
18031792

1804-
ret = lan78xx_read_reg(dev, MAC_CR, &buf);
1805-
if (buf & MAC_CR_EEE_EN_) {
1806-
/* EEE_TX_LPI_REQ_DLY & tx_lpi_timer are same uSec unit */
1807-
ret = lan78xx_read_reg(dev, EEE_TX_LPI_REQ_DLY, &buf);
1808-
edata->tx_lpi_timer = buf;
1809-
} else {
1810-
edata->tx_lpi_timer = 0;
1811-
}
1812-
1813-
ret = 0;
1814-
exit:
1815-
usb_autopm_put_interface(dev->intf);
1816-
1817-
return ret;
1793+
return phylink_ethtool_get_eee(dev->phylink, edata);
18181794
}
18191795

18201796
static int lan78xx_set_eee(struct net_device *net, struct ethtool_keee *edata)
18211797
{
18221798
struct lan78xx_net *dev = netdev_priv(net);
1823-
int ret;
1824-
u32 buf;
1825-
1826-
ret = usb_autopm_get_interface(dev->intf);
1827-
if (ret < 0)
1828-
return ret;
18291799

1830-
ret = phy_ethtool_set_eee(net->phydev, edata);
1831-
if (ret < 0)
1832-
goto out;
1833-
1834-
buf = (u32)edata->tx_lpi_timer;
1835-
ret = lan78xx_write_reg(dev, EEE_TX_LPI_REQ_DLY, buf);
1836-
out:
1837-
usb_autopm_put_interface(dev->intf);
1838-
1839-
return ret;
1800+
return phylink_ethtool_set_eee(dev->phylink, edata);
18401801
}
18411802

18421803
static void lan78xx_get_drvinfo(struct net_device *net,
@@ -2557,10 +2518,62 @@ static void lan78xx_mac_link_up(struct phylink_config *config,
25572518
ERR_PTR(ret));
25582519
}
25592520

2521+
/**
2522+
* lan78xx_mac_eee_enable - Enable or disable MAC-side EEE support
2523+
* @dev: LAN78xx device
2524+
* @enable: true to enable EEE, false to disable
2525+
*
2526+
* This function sets or clears the MAC_CR_EEE_EN_ bit to control Energy
2527+
* Efficient Ethernet (EEE) operation. According to current understanding
2528+
* of the LAN7800 documentation, this bit can be modified while TX and RX
2529+
* are enabled. No explicit requirement was found to disable data paths
2530+
* before changing this bit.
2531+
*
2532+
* Return: 0 on success or a negative error code
2533+
*/
2534+
static int lan78xx_mac_eee_enable(struct lan78xx_net *dev, bool enable)
2535+
{
2536+
u32 mac_cr = 0;
2537+
2538+
if (enable)
2539+
mac_cr |= MAC_CR_EEE_EN_;
2540+
2541+
return lan78xx_update_reg(dev, MAC_CR, MAC_CR_EEE_EN_, mac_cr);
2542+
}
2543+
2544+
static void lan78xx_mac_disable_tx_lpi(struct phylink_config *config)
2545+
{
2546+
struct net_device *net = to_net_dev(config->dev);
2547+
struct lan78xx_net *dev = netdev_priv(net);
2548+
2549+
lan78xx_mac_eee_enable(dev, false);
2550+
}
2551+
2552+
static int lan78xx_mac_enable_tx_lpi(struct phylink_config *config, u32 timer,
2553+
bool tx_clk_stop)
2554+
{
2555+
struct net_device *net = to_net_dev(config->dev);
2556+
struct lan78xx_net *dev = netdev_priv(net);
2557+
int ret;
2558+
2559+
/* Software should only change this field when Energy Efficient
2560+
* Ethernet Enable (EEEEN) is cleared. We ensure that by clearing
2561+
* EEEEN during probe, and phylink itself guarantees that
2562+
* mac_disable_tx_lpi() will have been previously called.
2563+
*/
2564+
ret = lan78xx_write_reg(dev, EEE_TX_LPI_REQ_DLY, timer);
2565+
if (ret < 0)
2566+
return ret;
2567+
2568+
return lan78xx_mac_eee_enable(dev, true);
2569+
}
2570+
25602571
static const struct phylink_mac_ops lan78xx_phylink_mac_ops = {
25612572
.mac_config = lan78xx_mac_config,
25622573
.mac_link_down = lan78xx_mac_link_down,
25632574
.mac_link_up = lan78xx_mac_link_up,
2575+
.mac_disable_tx_lpi = lan78xx_mac_disable_tx_lpi,
2576+
.mac_enable_tx_lpi = lan78xx_mac_enable_tx_lpi,
25642577
};
25652578

25662579
/**
@@ -2756,12 +2769,36 @@ static int lan78xx_phylink_setup(struct lan78xx_net *dev)
27562769
pc->mac_capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE | MAC_10 |
27572770
MAC_100 | MAC_1000FD;
27582771
pc->mac_managed_pm = true;
2772+
pc->lpi_capabilities = MAC_100FD | MAC_1000FD;
2773+
/*
2774+
* Default TX LPI (Low Power Idle) request delay count is set to 50us.
2775+
*
2776+
* Source: LAN7800 Documentation, DS00001992H, Section 15.1.57, Page 204.
2777+
*
2778+
* Reasoning:
2779+
* According to the application note in the LAN7800 documentation, a
2780+
* zero delay may negatively impact the TX data path’s ability to
2781+
* support Gigabit operation. A value of 50us is recommended as a
2782+
* reasonable default when the part operates at Gigabit speeds,
2783+
* balancing stability and power efficiency in EEE mode. This delay can
2784+
* be increased based on performance testing, as EEE is designed for
2785+
* scenarios with mostly idle links and occasional bursts of full
2786+
* bandwidth transmission. The goal is to ensure reliable Gigabit
2787+
* performance without overly aggressive power optimization during
2788+
* inactive periods.
2789+
*/
2790+
pc->lpi_timer_default = 50;
2791+
pc->eee_enabled_default = true;
27592792

27602793
if (dev->chipid == ID_REV_CHIP_ID_7801_)
27612794
phy_interface_set_rgmii(pc->supported_interfaces);
27622795
else
27632796
__set_bit(PHY_INTERFACE_MODE_GMII, pc->supported_interfaces);
27642797

2798+
memcpy(dev->phylink_config.lpi_interfaces,
2799+
dev->phylink_config.supported_interfaces,
2800+
sizeof(dev->phylink_config.lpi_interfaces));
2801+
27652802
phylink = phylink_create(pc, dev->net->dev.fwnode,
27662803
dev->interface, &lan78xx_phylink_mac_ops);
27672804
if (IS_ERR(phylink))
@@ -2827,8 +2864,6 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
28272864
goto phylink_uninit;
28282865
}
28292866

2830-
phy_support_eee(phydev);
2831-
28322867
ret = lan78xx_configure_leds_from_dt(dev, phydev);
28332868
if (ret < 0)
28342869
goto phylink_uninit;
@@ -3333,7 +3368,7 @@ static int lan78xx_reset(struct lan78xx_net *dev)
33333368
if (ret < 0)
33343369
return ret;
33353370

3336-
buf &= ~(MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_);
3371+
buf &= ~(MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_ | MAC_CR_EEE_EN_);
33373372

33383373
/* LAN7801 only has RGMII mode */
33393374
if (dev->chipid == ID_REV_CHIP_ID_7801_)

0 commit comments

Comments
 (0)