From 6f2fc8584a46bb35787bfc1dad1fb7dd5898e21f Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 2 Mar 2024 20:53:00 +0100 Subject: [PATCH 1/7] net: add helpers for EEE configuration Add helpers that phylib and phylink can use to manage EEE configuration and determine whether the MAC should be permitted to use LPI based on that configuration. Signed-off-by: Russell King (Oracle) Signed-off-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: Oleksij Rempel Link: https://lore.kernel.org/r/20240302195306.3207716-2-o.rempel@pengutronix.de Signed-off-by: Jakub Kicinski --- include/net/eee.h | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 include/net/eee.h diff --git a/include/net/eee.h b/include/net/eee.h new file mode 100644 index 000000000000..84837aba3cd9 --- /dev/null +++ b/include/net/eee.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _EEE_H +#define _EEE_H + +#include + +struct eee_config { + u32 tx_lpi_timer; + bool tx_lpi_enabled; + bool eee_enabled; +}; + +static inline bool eeecfg_mac_can_tx_lpi(const struct eee_config *eeecfg) +{ + /* eee_enabled is the master on/off */ + if (!eeecfg->eee_enabled || !eeecfg->tx_lpi_enabled) + return false; + + return true; +} + +static inline void eeecfg_to_eee(struct ethtool_keee *eee, + const struct eee_config *eeecfg) +{ + eee->tx_lpi_timer = eeecfg->tx_lpi_timer; + eee->tx_lpi_enabled = eeecfg->tx_lpi_enabled; + eee->eee_enabled = eeecfg->eee_enabled; +} + +static inline void eee_to_eeecfg(struct eee_config *eeecfg, + const struct ethtool_keee *eee) +{ + eeecfg->tx_lpi_timer = eee->tx_lpi_timer; + eeecfg->tx_lpi_enabled = eee->tx_lpi_enabled; + eeecfg->eee_enabled = eee->eee_enabled; +} + +#endif From e3b6876ab85061e7de198f023a0c2bfc7478b420 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 2 Mar 2024 20:53:01 +0100 Subject: [PATCH 2/7] net: phy: Add phydev->enable_tx_lpi to simplify adjust link callbacks MAC drivers which support EEE need to know the results of the EEE auto-neg in order to program the hardware to perform EEE or not. The oddly named phy_init_eee() can be used to determine this, it returns 0 if EEE should be used, or a negative error code, e.g. -EOPPROTONOTSUPPORT if the PHY does not support EEE or negotiate resulted in it not being used. However, many MAC drivers get this wrong. Add phydev->enable_tx_lpi which indicates the result of the autoneg for EEE, including if EEE is administratively disabled with ethtool. The MAC driver can then access this in the same way as link speed and duplex in the adjust link callback. If enable_tx_lpi is true, the MAC should send low power indications and does not need to consider anything else with respect to EEE. Reviewed-by: Florian Fainelli Signed-off-by: Andrew Lunn Signed-off-by: Oleksij Rempel Link: https://lore.kernel.org/r/20240302195306.3207716-3-o.rempel@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/phy/phy.c | 7 +++++++ include/linux/phy.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 14224e06d69f..2bc0a7d51c63 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -983,9 +983,16 @@ static int phy_check_link_status(struct phy_device *phydev) if (phydev->link && phydev->state != PHY_RUNNING) { phy_check_downshift(phydev); phydev->state = PHY_RUNNING; + err = genphy_c45_eee_is_active(phydev, + NULL, NULL, NULL); + if (err < 0) + phydev->enable_tx_lpi = false; + else + phydev->enable_tx_lpi = !!err; phy_link_up(phydev); } else if (!phydev->link && phydev->state != PHY_NOLINK) { phydev->state = PHY_NOLINK; + phydev->enable_tx_lpi = false; phy_link_down(phydev); } diff --git a/include/linux/phy.h b/include/linux/phy.h index e3ab2c347a59..a880f6d7170e 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -594,6 +594,7 @@ struct macsec_ops; * @supported_eee: supported PHY EEE linkmodes * @advertising_eee: Currently advertised EEE linkmodes * @eee_enabled: Flag indicating whether the EEE feature is enabled + * @enable_tx_lpi: When True, MAC should transmit LPI to PHY * @lp_advertising: Current link partner advertised linkmodes * @host_interfaces: PHY interface modes supported by host * @eee_broken_modes: Energy efficient ethernet modes which should be prohibited @@ -713,6 +714,7 @@ struct phy_device { /* Energy efficient ethernet modes which should be prohibited */ u32 eee_broken_modes; + bool enable_tx_lpi; #ifdef CONFIG_LED_TRIGGER_PHY struct phy_led_trigger *phy_led_triggers; From fe0d4fd9285e5013b4bafbd3338847235b805a1c Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 2 Mar 2024 20:53:02 +0100 Subject: [PATCH 3/7] net: phy: Keep track of EEE configuration Have phylib keep track of the EEE configuration. This simplifies the MAC drivers, in that they don't need to store it. Future patches to phylib will also make use of this information to further simplify the MAC drivers. Reviewed-by: Russell King (Oracle) Signed-off-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: Oleksij Rempel Link: https://lore.kernel.org/r/20240302195306.3207716-4-o.rempel@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/phy/phy.c | 7 +++++-- include/linux/phy.h | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 2bc0a7d51c63..95c4ef5d4e97 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -1640,8 +1640,8 @@ EXPORT_SYMBOL(phy_get_eee_err); * @phydev: target phy_device struct * @data: ethtool_keee data * - * Description: it reportes the Supported/Advertisement/LP Advertisement - * capabilities. + * Description: reports the Supported/Advertisement/LP Advertisement + * capabilities, etc. */ int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_keee *data) { @@ -1652,6 +1652,7 @@ int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_keee *data) mutex_lock(&phydev->lock); ret = genphy_c45_ethtool_get_eee(phydev, data); + eeecfg_to_eee(data, &phydev->eee_cfg); mutex_unlock(&phydev->lock); return ret; @@ -1674,6 +1675,8 @@ int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_keee *data) mutex_lock(&phydev->lock); ret = genphy_c45_ethtool_set_eee(phydev, data); + if (!ret) + eee_to_eeecfg(&phydev->eee_cfg, data); mutex_unlock(&phydev->lock); return ret; diff --git a/include/linux/phy.h b/include/linux/phy.h index a880f6d7170e..695e366bd75c 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -30,6 +30,7 @@ #include #include +#include #define PHY_DEFAULT_FEATURES (SUPPORTED_Autoneg | \ SUPPORTED_TP | \ @@ -595,6 +596,7 @@ struct macsec_ops; * @advertising_eee: Currently advertised EEE linkmodes * @eee_enabled: Flag indicating whether the EEE feature is enabled * @enable_tx_lpi: When True, MAC should transmit LPI to PHY + * @eee_cfg: User configuration of EEE * @lp_advertising: Current link partner advertised linkmodes * @host_interfaces: PHY interface modes supported by host * @eee_broken_modes: Energy efficient ethernet modes which should be prohibited @@ -715,6 +717,7 @@ struct phy_device { /* Energy efficient ethernet modes which should be prohibited */ u32 eee_broken_modes; bool enable_tx_lpi; + struct eee_config eee_cfg; #ifdef CONFIG_LED_TRIGGER_PHY struct phy_led_trigger *phy_led_triggers; From 3e43b903da04927f60894a603678f761c66d6e37 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 2 Mar 2024 20:53:03 +0100 Subject: [PATCH 4/7] net: phy: Immediately call adjust_link if only tx_lpi_enabled changes The MAC driver changes its EEE hardware configuration in its adjust_link callback. This is called when auto-neg completes. Disabling EEE via eee_enabled false will trigger an autoneg, and as a result the adjust_link callback will be called with phydev->enable_tx_lpi set to false. Similarly, eee_enabled set to true and with a change of advertised link modes will result in a new autoneg, and a call the adjust_link call. If set_eee is called with only a change to tx_lpi_enabled which does not trigger an auto-neg, it is necessary to call the adjust_link callback so that the MAC is reconfigured to take this change into account. When setting phydev->enable_tx_lpi, take both eee_enabled and tx_lpi_enabled into account, so the MAC drivers just needs to act on phydev->enable_tx_lpi and not the whole EEE configuration. The same check should be done for tx_lpi_timer too. Signed-off-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: Oleksij Rempel Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20240302195306.3207716-5-o.rempel@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/phy/phy-c45.c | 14 ++++++++++++-- drivers/net/phy/phy.c | 40 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 3e95b8a15f44..5695935fdce9 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -1550,6 +1550,8 @@ EXPORT_SYMBOL(genphy_c45_ethtool_get_eee); * advertised, but the previously advertised link modes are * retained. This allows EEE to be enabled/disabled in a * non-destructive way. + * Returns either error code, 0 if there was no change, or positive + * value if there was a change which triggered auto-neg. */ int genphy_c45_ethtool_set_eee(struct phy_device *phydev, struct ethtool_keee *data) @@ -1576,8 +1578,16 @@ int genphy_c45_ethtool_set_eee(struct phy_device *phydev, phydev->eee_enabled = data->eee_enabled; ret = genphy_c45_an_config_eee_aneg(phydev); - if (ret > 0) - return phy_restart_aneg(phydev); + if (ret > 0) { + ret = phy_restart_aneg(phydev); + if (ret < 0) + return ret; + + /* explicitly return 1, otherwise (ret > 0) value will be + * overwritten by phy_restart_aneg(). + */ + return 1; + } return ret; } diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 95c4ef5d4e97..c3a0a5ee5f11 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -988,7 +988,8 @@ static int phy_check_link_status(struct phy_device *phydev) if (err < 0) phydev->enable_tx_lpi = false; else - phydev->enable_tx_lpi = !!err; + phydev->enable_tx_lpi = (err & phydev->eee_cfg.tx_lpi_enabled); + phy_link_up(phydev); } else if (!phydev->link && phydev->state != PHY_NOLINK) { phydev->state = PHY_NOLINK; @@ -1659,6 +1660,36 @@ int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_keee *data) } EXPORT_SYMBOL(phy_ethtool_get_eee); +/** + * phy_ethtool_set_eee_noneg - Adjusts MAC LPI configuration without PHY + * renegotiation + * @phydev: pointer to the target PHY device structure + * @data: pointer to the ethtool_keee structure containing the new EEE settings + * + * This function updates the Energy Efficient Ethernet (EEE) configuration + * for cases where only the MAC's Low Power Idle (LPI) configuration changes, + * without triggering PHY renegotiation. It ensures that the MAC is properly + * informed of the new LPI settings by cycling the link down and up, which + * is necessary for the MAC to adopt the new configuration. This adjustment + * is done only if there is a change in the tx_lpi_enabled or tx_lpi_timer + * configuration. + */ +static void phy_ethtool_set_eee_noneg(struct phy_device *phydev, + struct ethtool_keee *data) +{ + if (phydev->eee_cfg.tx_lpi_enabled != data->tx_lpi_enabled || + phydev->eee_cfg.tx_lpi_timer != data->tx_lpi_timer) { + eee_to_eeecfg(&phydev->eee_cfg, data); + phydev->enable_tx_lpi = eeecfg_mac_can_tx_lpi(&phydev->eee_cfg); + if (phydev->link) { + phydev->link = false; + phy_link_down(phydev); + phydev->link = true; + phy_link_up(phydev); + } + } +} + /** * phy_ethtool_set_eee - set EEE supported and status * @phydev: target phy_device struct @@ -1675,11 +1706,14 @@ int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_keee *data) mutex_lock(&phydev->lock); ret = genphy_c45_ethtool_set_eee(phydev, data); - if (!ret) + if (ret >= 0) { + if (ret == 0) + phy_ethtool_set_eee_noneg(phydev, data); eee_to_eeecfg(&phydev->eee_cfg, data); + } mutex_unlock(&phydev->lock); - return ret; + return ret < 0 ? ret : 0; } EXPORT_SYMBOL(phy_ethtool_set_eee); From 49168d1980e220cf3d1b761e1eafac62041cb94d Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 2 Mar 2024 20:53:04 +0100 Subject: [PATCH 5/7] net: phy: Add phy_support_eee() indicating MAC support EEE In order for EEE to operate, both the MAC and the PHY need to support it, similar to how pause works. With some exception - a number of PHYs have SmartEEE or AutoGrEEEn support in order to provide some EEE-like power savings with non-EEE capable MACs. Copy the pause concept and add the call phy_support_eee() which the MAC makes after connecting the PHY to indicate it supports EEE. phylib will then advertise EEE when auto-neg is performed. Signed-off-by: Andrew Lunn Signed-off-by: Oleksij Rempel Link: https://lore.kernel.org/r/20240302195306.3207716-6-o.rempel@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/phy/phy_device.c | 28 ++++++++++++++++++++++++++++ include/linux/phy.h | 3 ++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 2eefee970851..72452e6a478c 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -2910,6 +2910,34 @@ void phy_advertise_eee_all(struct phy_device *phydev) } EXPORT_SYMBOL_GPL(phy_advertise_eee_all); +/** + * phy_support_eee - Set initial EEE policy configuration + * @phydev: Target phy_device struct + * + * This function configures the initial policy for Energy Efficient Ethernet + * (EEE) on the specified PHY device, influencing that EEE capabilities are + * advertised before the link is established. It should be called during PHY + * registration by the MAC driver and/or the PHY driver (for SmartEEE PHYs) + * if MAC supports LPI or PHY is capable to compensate missing LPI functionality + * of the MAC. + * + * The function sets default EEE policy parameters, including preparing the PHY + * to advertise EEE capabilities based on hardware support. + * + * It also sets the expected configuration for Low Power Idle (LPI) in the MAC + * driver. If the PHY framework determines that both local and remote + * advertisements support EEE, and the negotiated link mode is compatible with + * EEE, it will set enable_tx_lpi = true. The MAC driver is expected to act on + * this setting by enabling the LPI timer if enable_tx_lpi is set. + */ +void phy_support_eee(struct phy_device *phydev) +{ + linkmode_copy(phydev->advertising_eee, phydev->supported_eee); + phydev->eee_cfg.tx_lpi_enabled = true; + phydev->eee_cfg.eee_enabled = true; +} +EXPORT_SYMBOL(phy_support_eee); + /** * phy_support_sym_pause - Enable support of symmetrical pause * @phydev: target phy_device struct diff --git a/include/linux/phy.h b/include/linux/phy.h index 695e366bd75c..3f68b8239bb1 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -706,7 +706,7 @@ struct phy_device { __ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising); /* used with phy_speed_down */ __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old); - /* used for eee validation */ + /* used for eee validation and configuration*/ __ETHTOOL_DECLARE_LINK_MODE_MASK(supported_eee); __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising_eee); bool eee_enabled; @@ -1973,6 +1973,7 @@ void phy_advertise_supported(struct phy_device *phydev); void phy_advertise_eee_all(struct phy_device *phydev); void phy_support_sym_pause(struct phy_device *phydev); void phy_support_asym_pause(struct phy_device *phydev); +void phy_support_eee(struct phy_device *phydev); void phy_set_sym_pause(struct phy_device *phydev, bool rx, bool tx, bool autoneg); void phy_set_asym_pause(struct phy_device *phydev, bool rx, bool tx); From aff1b8c84b44894f305f94b1a7aa4fc1e773c614 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 2 Mar 2024 20:53:05 +0100 Subject: [PATCH 6/7] net: fec: Move fec_enet_eee_mode_set() and helper earlier FEC is about to get its EEE code re-written. To allow this, move fec_enet_eee_mode_set() before fec_enet_adjust_link() which will need to call it. Signed-off-by: Andrew Lunn Signed-off-by: Oleksij Rempel Reviewed-by: Wei Fang Link: https://lore.kernel.org/r/20240302195306.3207716-7-o.rempel@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fec_main.c | 75 ++++++++++++----------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 207f1f66c117..a2c786550342 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2017,6 +2017,44 @@ static int fec_get_mac(struct net_device *ndev) /* * Phy section */ + +/* LPI Sleep Ts count base on tx clk (clk_ref). + * The lpi sleep cnt value = X us / (cycle_ns). + */ +static int fec_enet_us_to_tx_cycle(struct net_device *ndev, int us) +{ + struct fec_enet_private *fep = netdev_priv(ndev); + + return us * (fep->clk_ref_rate / 1000) / 1000; +} + +static int fec_enet_eee_mode_set(struct net_device *ndev, bool enable) +{ + struct fec_enet_private *fep = netdev_priv(ndev); + struct ethtool_keee *p = &fep->eee; + unsigned int sleep_cycle, wake_cycle; + int ret = 0; + + if (enable) { + ret = phy_init_eee(ndev->phydev, false); + if (ret) + return ret; + + sleep_cycle = fec_enet_us_to_tx_cycle(ndev, p->tx_lpi_timer); + wake_cycle = sleep_cycle; + } else { + sleep_cycle = 0; + wake_cycle = 0; + } + + p->tx_lpi_enabled = enable; + + writel(sleep_cycle, fep->hwp + FEC_LPI_SLEEP); + writel(wake_cycle, fep->hwp + FEC_LPI_WAKE); + + return 0; +} + static void fec_enet_adjust_link(struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); @@ -3121,43 +3159,6 @@ static int fec_enet_set_coalesce(struct net_device *ndev, return 0; } -/* LPI Sleep Ts count base on tx clk (clk_ref). - * The lpi sleep cnt value = X us / (cycle_ns). - */ -static int fec_enet_us_to_tx_cycle(struct net_device *ndev, int us) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - - return us * (fep->clk_ref_rate / 1000) / 1000; -} - -static int fec_enet_eee_mode_set(struct net_device *ndev, bool enable) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - struct ethtool_keee *p = &fep->eee; - unsigned int sleep_cycle, wake_cycle; - int ret = 0; - - if (enable) { - ret = phy_init_eee(ndev->phydev, false); - if (ret) - return ret; - - sleep_cycle = fec_enet_us_to_tx_cycle(ndev, p->tx_lpi_timer); - wake_cycle = sleep_cycle; - } else { - sleep_cycle = 0; - wake_cycle = 0; - } - - p->tx_lpi_enabled = enable; - - writel(sleep_cycle, fep->hwp + FEC_LPI_SLEEP); - writel(wake_cycle, fep->hwp + FEC_LPI_WAKE); - - return 0; -} - static int fec_enet_get_eee(struct net_device *ndev, struct ethtool_keee *edata) { From 6a2495adc0c83d039a872b75d9d348a5dd3eb9f4 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 2 Mar 2024 20:53:06 +0100 Subject: [PATCH 7/7] net: fec: Fixup EEE The enabling/disabling of EEE in the MAC should happen as a result of auto negotiation. So move the enable/disable into fec_enet_adjust_link() which gets called by phylib when there is a change in link status. fec_enet_set_eee() now just stores away the LPI timer value. Everything else is passed to phylib, so it can correctly setup the PHY. fec_enet_get_eee() relies on phylib doing most of the work, the MAC driver just adds the LPI timer value. Call phy_support_eee() if the quirk is present to indicate the MAC actually supports EEE. Signed-off-by: Andrew Lunn Tested-by: Oleksij Rempel (On iMX8MP debix) Signed-off-by: Oleksij Rempel Reviewed-by: Wei Fang Link: https://lore.kernel.org/r/20240302195306.3207716-8-o.rempel@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/fec_main.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index a2c786550342..d7693fdf640d 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2033,13 +2033,8 @@ static int fec_enet_eee_mode_set(struct net_device *ndev, bool enable) struct fec_enet_private *fep = netdev_priv(ndev); struct ethtool_keee *p = &fep->eee; unsigned int sleep_cycle, wake_cycle; - int ret = 0; if (enable) { - ret = phy_init_eee(ndev->phydev, false); - if (ret) - return ret; - sleep_cycle = fec_enet_us_to_tx_cycle(ndev, p->tx_lpi_timer); wake_cycle = sleep_cycle; } else { @@ -2047,8 +2042,6 @@ static int fec_enet_eee_mode_set(struct net_device *ndev, bool enable) wake_cycle = 0; } - p->tx_lpi_enabled = enable; - writel(sleep_cycle, fep->hwp + FEC_LPI_SLEEP); writel(wake_cycle, fep->hwp + FEC_LPI_WAKE); @@ -2094,6 +2087,8 @@ static void fec_enet_adjust_link(struct net_device *ndev) netif_tx_unlock_bh(ndev); napi_enable(&fep->napi); } + if (fep->quirks & FEC_QUIRK_HAS_EEE) + fec_enet_eee_mode_set(ndev, phy_dev->enable_tx_lpi); } else { if (fep->link) { netif_stop_queue(ndev); @@ -2453,6 +2448,9 @@ static int fec_enet_mii_probe(struct net_device *ndev) else phy_set_max_speed(phy_dev, 100); + if (fep->quirks & FEC_QUIRK_HAS_EEE) + phy_support_eee(phy_dev); + fep->link = 0; fep->full_duplex = 0; @@ -3172,7 +3170,6 @@ fec_enet_get_eee(struct net_device *ndev, struct ethtool_keee *edata) return -ENETDOWN; edata->tx_lpi_timer = p->tx_lpi_timer; - edata->tx_lpi_enabled = p->tx_lpi_enabled; return phy_ethtool_get_eee(ndev->phydev, edata); } @@ -3182,7 +3179,6 @@ fec_enet_set_eee(struct net_device *ndev, struct ethtool_keee *edata) { struct fec_enet_private *fep = netdev_priv(ndev); struct ethtool_keee *p = &fep->eee; - int ret = 0; if (!(fep->quirks & FEC_QUIRK_HAS_EEE)) return -EOPNOTSUPP; @@ -3192,15 +3188,6 @@ fec_enet_set_eee(struct net_device *ndev, struct ethtool_keee *edata) p->tx_lpi_timer = edata->tx_lpi_timer; - if (!edata->eee_enabled || !edata->tx_lpi_enabled || - !edata->tx_lpi_timer) - ret = fec_enet_eee_mode_set(ndev, false); - else - ret = fec_enet_eee_mode_set(ndev, true); - - if (ret) - return ret; - return phy_ethtool_set_eee(ndev->phydev, edata); }