net: stmmac: clean up and fix EEE implementation
Subsystems (5)
Russell King (Oracle)
reviewerv3 cover net: stmmac: clean up and fix EEE implementation
Hi,
This is a rework of stmmac's EEE support in light of the addition of EEE management to phylib. It's slightly more than 15 patches, but I think it makes sense to be so.
Patch 1 adds configuration of the receive clock phy_eee_rx_clock_stop() (which was part of another series, but is necessary for this patch set.)
Patch 2 converts stmmac to use phylib's tracking of tx_lpi_timer.
Patch 3 corrects the data type used for things involving the LPI timer. The user API uses u32, so stmmac should do too, rather than blindly converting it to "int". eee_timer is left for patch 4.
Patch 4 (new) uses an unsigned int for eee_timer.
Patch 5 makes stmmac EEE state depend on phylib's enable_tx_lpi flag, thus using phylib's resolution of EEE state.
Patch 6 removes redundant code from the ethtool EEE operations.
Patch 7 removes some redundant code in stmmac_disable_eee_mode() and renames it to stmmac_disable_sw_eee_mode() to better reflect its purpose.
Patch 8 removes the driver private tx_lpi_enabled, which is managed by phylib since patch 4.
Patch 9 removes the dependence of EEE error statistics on the EEE enable state, instead depending on whether EEE is supported by the hardware.
Patch 10 removes phy_init_eee(), instead using phy_eee_rx_clock_stop() to configure whether the PHY may stop the receive clock.
Patch 11 removes priv->eee_tw_timer, which is only ever set to one value at probe time, effectively it is a constant. Hence this is unnecessary complexity.
Patch 12 moves priv->eee_enabled into stmmac_eee_init(), and placing it under the protection of priv->lock, except when EEE is not supported (where it becomes constant-false.)
Patch 13 moves priv->eee_active also into stmmac_eee_init(), so the indication whether EEE should be enabled or not is passed in to this function.
Since both priv->eee_enabled and priv->eee_active are assigned true/false values, they should be typed "bool". Make it sew in patch 14. No Singer machine required.
Patch 15 moves the initialisation of priv->eee_ctrl_timer to the probe function - it makes no sense to re-initialise the timer each time we want to start using it.
Patch 16 removes the unnecessary EEE handling in the driver tear-down method. The core net code will have brought the interface down already, meaning EEE has already been disabled.
Patch 17 reorganises the code to split the hardware LPI timer control paths from the software LPI timer paths.
Patch 18 works on this further by eliminating stmmac_lpi_entry_timer_config() and making direct calls to the new functions. This reveals a potential bug where priv->eee_sw_timer_en is set true when EEE is disabled. This is not addressed in this series, but will be in a future separate patch - so that if fixing that causes a regression, it can be handled separately.
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 4 +- drivers/net/ethernet/stmicro/stmmac/hwif.h | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 10 +- .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 25 +---- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 103 +++++++++++---------- drivers/net/phy/phy.c | 27 +++++- include/linux/phy.h | 1 + 7 files changed, 85 insertions(+), 87 deletions(-)
Changes in v3:
- fix kerneldoc issue in old patch 12.
- add Andrew's r-bs.
- split eee_timer from other u32 conversions, remove check for negative eee_timer.
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
PATCH v3 1/18 net: phy: add configuration of rx clock stop mode
Add a function to allow configuration of the PCS's clock stop enable bit, used to configure whether the xMII receive clock can be stopped during LPI mode.
--- drivers/net/phy/phy.c | 27 ++++++++++++++++++++++----- include/linux/phy.h | 1 + 2 files changed, 23 insertions(+), 5 deletions(-)
drivers/net/phy/phy.c +22 -5
@@ -1640,6 +1640,27 @@ void phy_mac_interrupt(struct phy_device *phydev) }EXPORT_SYMBOL (phy_mac_interrupt); +/** +* phy_eee_rx_clock_stop() - configure PHY receive clock in LPI +* @phydev: target phy_device struct +* @clk_stop_enable: flag to indicate whether the clock can be stopped +* +* Configure whether the PHY can disable its receive clock during LPI mode, +* See IEEE 802.3 sections 22.2.2.2, 35.2.2.10, and 45.2.3.1.4. +* +* Returns: 0 or negative error. +*/ +int phy_eee_rx_clock_stop (struct phy_device *phydev,bool clk_stop_enable) +{ +/* Configure the PHY to stop receiving xMII +* clock while it is signaling LPI. +*/ +return phy_modify_mmd (phydev,MDIO_MMD_PCS ,MDIO_CTRL1 , +MDIO_PCS_CTRL1_CLKSTOP_EN , + clk_stop_enable ?MDIO_PCS_CTRL1_CLKSTOP_EN :0 ); +} +EXPORT_SYMBOL_GPL (phy_eee_rx_clock_stop); +/** * phy_init_eee - init and check the EEE feature * @phydev: target phy_device struct
@@ -1664,11 +1685,7 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)return -EPROTONOSUPPORT ;if (clk_stop_enable) -/* Configure the PHY to stop receiving xMII -* clock while it is signaling LPI. -*/ - ret =phy_set_bits_mmd (phydev,MDIO_MMD_PCS ,MDIO_CTRL1 , -MDIO_PCS_CTRL1_CLKSTOP_EN ); + ret =phy_eee_rx_clock_stop (phydev, true);return ret <0 ? ret :0 ; }
include/linux/phy.h +1 -0
@@ -2096,6 +2096,7 @@ int phy_unregister_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask);int phy_unregister_fixup_for_id (const char *bus_id);int phy_unregister_fixup_for_uid (u32 phy_uid,u32 phy_uid_mask); +int phy_eee_rx_clock_stop (struct phy_device *phydev,bool clk_stop_enable);int phy_init_eee (struct phy_device *phydev,bool clk_stop_enable);int phy_get_eee_err (struct phy_device *phydev);int phy_ethtool_set_eee (struct phy_device *phydev,struct ethtool_keee *data);
Signature · 1 line
2.30.2
PATCH v3 2/18 net: stmmac: move tx_lpi_timer tracking to phylib
In reply to Russell King (Oracle)When stmmac_ethtool_op_get_eee() is called, stmmac sets the tx_lpi_timer and tx_lpi_enabled members, and then calls into phylink and thus phylib. phylib overwrites these members.
phylib will also cause a link down/link up transition when settings that impact the MAC have been changed.
Convert stmmac to use the tx_lpi_timer setting in struct phy_device, updating priv->tx_lpi_timer each time when the link comes up, rather than trying to maintain this user setting itself. We initialise the phylib tx_lpi_timer setting by doing a get_ee-modify-set_eee sequence with the last known priv->tx_lpi_timer value. In order for this to work correctly, we also need this member to be initialised earlier.
As stmmac_eee_init() is no longer called outside of stmmac_main.c, make it static.
--- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 - .../ethernet/stmicro/stmmac/stmmac_ethtool.c | 14 +------------ .../net/ethernet/stmicro/stmmac/stmmac_main.c | 21 ++++++++++++++----- 3 files changed, 17 insertions(+), 19 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac.h +0 -1
@@ -406,7 +406,6 @@ int stmmac_dvr_probe(struct device *device,struct plat_stmmacenet_data *plat_dat, struct stmmac_resources *res);void stmmac_disable_eee_mode (struct stmmac_priv *priv); -bool stmmac_eee_init (struct stmmac_priv *priv);int stmmac_reinit_queues (struct net_device *dev,u32 rx_cnt,u32 tx_cnt);int stmmac_reinit_ringparam (struct net_device *dev,u32 rx_size,u32 tx_size);int stmmac_bus_clks_config (struct stmmac_priv *priv,bool enabled);
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +1 -13
@@ -898,7 +898,6 @@ static int stmmac_ethtool_op_get_eee(struct net_device *dev,if (!priv->dma_cap.eee)return -EOPNOTSUPP ; - edata->tx_lpi_timer = priv->tx_lpi_timer; edata->tx_lpi_enabled = priv->tx_lpi_enabled;return phylink_ethtool_get_eee (priv->phylink, edata);
@@ -908,7 +907,6 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev, struct ethtool_keee *edata) {struct stmmac_priv *priv =netdev_priv (dev); -int ret;if (!priv->dma_cap.eee)return -EOPNOTSUPP ;
@@ -920,17 +918,7 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,if (!edata->eee_enabled)stmmac_disable_eee_mode (priv); - ret =phylink_ethtool_set_eee (priv->phylink, edata); -if (ret) -return ret; - -if (edata->eee_enabled && - priv->tx_lpi_timer != edata->tx_lpi_timer) { - priv->tx_lpi_timer = edata->tx_lpi_timer; -stmmac_eee_init (priv); - } - -return 0 ; +return phylink_ethtool_set_eee (priv->phylink, edata); }static u32 stmmac_usec2riwt (u32 usec,struct stmmac_priv *priv)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +16 -5
@@ -469,7 +469,7 @@ static void stmmac_eee_ctrl_timer(struct timer_list *t)* can also manage EEE, this function enable the LPI state and start related * timer. */ -bool stmmac_eee_init (struct stmmac_priv *priv) +static bool stmmac_eee_init (struct stmmac_priv *priv) {int eee_tw_timer = priv->eee_tw_timer;
@@ -1088,6 +1088,7 @@ static void stmmac_mac_link_up(struct phylink_config *config, priv->eee_active =phy_init_eee (phy, !(priv->plat->flags &STMMAC_FLAG_RX_CLK_RUNS_IN_LPI )) >=0 ; + priv->tx_lpi_timer = phy->eee_cfg.tx_lpi_timer; priv->eee_enabled =stmmac_eee_init (priv); priv->tx_lpi_enabled = priv->eee_enabled;stmmac_set_eee_pls (priv, priv->hw, true);
@@ -1187,6 +1188,16 @@ static int stmmac_init_phy(struct net_device *dev) ret =phylink_fwnode_phy_connect (priv->phylink, fwnode,0 ); } +if (ret ==0 ) { +struct ethtool_keee eee; + +/* Configure phylib's copy of the LPI timer */ +if (phylink_ethtool_get_eee (priv->phylink, &eee)) { + eee.tx_lpi_timer = priv->tx_lpi_timer; +phylink_ethtool_set_eee (priv->phylink, &eee); + } + } +if (!priv->plat->pmt) {struct ethtool_wolinfo wol = { .cmd =ETHTOOL_GWOL };
@@ -3446,10 +3457,6 @@ static int stmmac_hw_setup(struct net_device *dev, bool ptp_register) priv->eee_tw_timer =STMMAC_DEFAULT_TWT_LS ; -/* Convert the timer from msec to usec */ -if (!priv->tx_lpi_timer) - priv->tx_lpi_timer = eee_timer *1000 ; -if (priv->use_riwt) {u32 queue;
@@ -3916,6 +3923,10 @@ static int __stmmac_open(struct net_device *dev,u32 chan;int ret; +/* Initialise the tx lpi timer, converting from msec to usec */ +if (!priv->tx_lpi_timer) + priv->tx_lpi_timer = eee_timer *1000 ; + ret =pm_runtime_resume_and_get (priv->device);if (ret <0 )return ret;
Signature · 1 line
2.30.2
Re: [PATCH net-next v3 02/18] net: stmmac: move tx_lpi_timer tracking to phylib
Quoted 14 lines · Russell King (Oracle)
When
stmmac_ethtool_op_get_eee()is called, stmmac sets thetx_lpi_timerandtx_lpi_enabledmembers, and then calls into phylink and thus phylib. phylib overwrites these members.phylib will also cause a link down/link up transition when settings that impact the MAC have been changed.
Convert stmmac to use the
tx_lpi_timersetting in structphy_device, updatingpriv->tx_lpi_timereach time when the link comes up, rather than trying to maintain this user setting itself. We initialise the phylibtx_lpi_timersetting by doing a get_ee-modify-set_eee sequence with the last knownpriv->tx_lpi_timervalue. In order for this to work correctly, we also need this member to be initialised earlier.
Quoted 5 lines
As
stmmac_eee_init()is no longer called outside ofstmmac_main.c, make it static.Reviewed-by Andrew Lunn <[email protected]>Signed-off-by Russell King (Oracle) <[email protected]>
Hi Russell,
I have completed the sanity test on the EEE changes to the stmmac driver.
It seems that most of the changes are acceptable with respect to EEE behavior.
However, I noticed that this part of the code requires a minor change to fix the logic:
/* Configure phylib's copy of the LPI timer */
if (phylink_ethtool_get_eee(priv->phylink, &eee) == 0) {
eee.tx_lpi_timer = priv->tx_lpi_timer;
phylink_ethtool_set_eee(priv->phylink, &eee);
}Otherwise, the "tx_lpi_timer" will not be set correctly during the initial state.
Russell King (Oracle)
reviewerRe: [PATCH net-next v3 02/18] net: stmmac: move tx_lpi_timer tracking to phylib
Hi,
Quoted 13 lines · Choong Yong Liang
I have completed the sanity test on the EEE changes to the stmmac driver.
It seems that most of the changes are acceptable with respect to EEE behavior.
However, I noticed that this part of the code requires a minor change to fix the logic:
/* Configure phylib's copy of the LPI timer */ if (phylink_ethtool_get_eee(priv->phylink, &eee) == 0) { eee.tx_lpi_timer = priv->tx_lpi_timer; phylink_ethtool_set_eee(priv->phylink, &eee); }
Quoted 4 lines
Otherwise, the "
tx_lpi_timer" will not be set correctly during the initial state.Tested-by Choong Yong Liang <[email protected]>
Thanks for testing. I can't update the series as there has been a power failure at home, hence the machine that has my git trees on is inaccessible at the moment.
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Russell King (Oracle)
reviewerRe: [PATCH net-next v3 02/18] net: stmmac: move tx_lpi_timer tracking to phylib
In reply to Choong Yong LiangHi,
Quoted 1 line · Choong Yong Liang
Tested-by Choong Yong Liang <[email protected]>
Please let me know if this is for the entire series.
Thanks.
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Re: [PATCH net-next v3 02/18] net: stmmac: move tx_lpi_timer tracking to phylib
Quoted 9 lines · Russell King (Oracle)
Hi,
Quoted 1 line · Choong Yong Liang
Tested-by Choong Yong Liang <[email protected]>Please let me know if this is for the entire series.
Thanks.
Yes, the test is for the entire series.
The only issue that was discovered is that during the initial state, the "tx_lpi_timer" is not set correctly. The "tx_lpi_timer" with a value of 0 causes the EEE to be unable to enter LPI mode.
PATCH v3 3/18 net: stmmac: use correct type for tx_lpi_timer
In reply to Russell King (Oracle)The ethtool interface uses u32 for tx_lpi_timer, and so does phylib. Use u32 to store this internally within stmmac rather than "int" which could misinterpret large values.
Correct "value" in dwmac4_set_eee_lpi_entry_timer() to use u32 rather than int, which is derived from tx_lpi_timer. Even though this path won't be used with values larger than STMMAC_ET_MAX, this brings consistency of type usage to the stmmac code for this variable.
We leave eee_timer unchanged for now, with the assumption that values up to INT_MAX will safely fit in a u32.
--- drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 4 ++-- drivers/net/ethernet/stmicro/stmmac/hwif.h | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-)
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +2 -2
@@ -420,10 +420,10 @@ static void dwmac4_set_eee_pls(struct mac_device_info *hw, int link)writel (value, ioaddr +GMAC4_LPI_CTRL_STATUS ); } -static void dwmac4_set_eee_lpi_entry_timer (struct mac_device_info *hw,int et) +static void dwmac4_set_eee_lpi_entry_timer (struct mac_device_info *hw,u32 et) {void __iomem *ioaddr = hw->pcsr; -int value = et &STMMAC_ET_MAX ; +u32 value = et &STMMAC_ET_MAX ;int regval;/* Program LPI entry timer value into register */
drivers/net/ethernet/stmicro/stmmac/hwif.h +1 -1
@@ -363,7 +363,7 @@ struct stmmac_ops {void (*set_eee_mode)(struct mac_device_info *hw,bool en_tx_lpi_clockgating);void (*reset_eee_mode)(struct mac_device_info *hw); -void (*set_eee_lpi_entry_timer)(struct mac_device_info *hw,int et); +void (*set_eee_lpi_entry_timer)(struct mac_device_info *hw,u32 et);void (*set_eee_timer)(struct mac_device_info *hw,int ls,int tw);void (*set_eee_pls)(struct mac_device_info *hw,int link); void (*debug)(struct stmmac_priv *priv, void __iomem *ioaddr,
drivers/net/ethernet/stmicro/stmmac/stmmac.h +1 -1
@@ -307,7 +307,7 @@ struct stmmac_priv {int lpi_irq;int eee_enabled;int eee_active; -int tx_lpi_timer; +u32 tx_lpi_timer;int tx_lpi_enabled;int eee_tw_timer;bool eee_sw_timer_en;
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +2 -2
@@ -394,11 +394,11 @@ static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv, u32 queue)static void stmmac_lpi_entry_timer_config (struct stmmac_priv *priv,bool en) { -int tx_lpi_timer; +u32 tx_lpi_timer;/* Clear/set the SW EEE timer flag based on LPI ET enablement */ priv->eee_sw_timer_en = en ?0 :1 ; - tx_lpi_timer = en ? priv->tx_lpi_timer :0 ; + tx_lpi_timer = en ? priv->tx_lpi_timer :0 ;stmmac_set_eee_lpi_timer (priv, priv->hw, tx_lpi_timer); }
Signature · 1 line
2.30.2
PATCH v3 4/18 net: stmmac: use unsigned int for eee_timer
In reply to Russell King (Oracle)Since eee_timer is used to initialise priv->tx_lpi_timer, this also should be unsigned to avoid a negative number being interpreted as a very large positive number. Note that this makes the check for negative numbers passed in as a module parameter redundant, and passing a negative number will now produce a large delay rather than the default. Since the default is used without an argument, passing a negative number would be quite obscure. However, if users do, then this will need to be revisited.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +2 -4
@@ -111,8 +111,8 @@ static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);#define STMMAC_DEFAULT_LPI_TIMER 1000 -static int eee_timer =STMMAC_DEFAULT_LPI_TIMER ; -module_param (eee_timer, int,0644 ); +static unsigned int eee_timer =STMMAC_DEFAULT_LPI_TIMER ; +module_param (eee_timer, uint,0644 );MODULE_PARM_DESC (eee_timer,"LPI tx expiration time in msec" );#define STMMAC_LPI_T (x) (jiffies + usecs_to_jiffies(x))
@@ -194,8 +194,6 @@ static void stmmac_verify_args(void) flow_ctrl =FLOW_OFF ;if (unlikely ((pause <0 ) || (pause >0xffff ))) pause =PAUSE_TIME ; -if (eee_timer <0 ) - eee_timer =STMMAC_DEFAULT_LPI_TIMER ; }static void __stmmac_disable_all_queues (struct stmmac_priv *priv)
Signature · 1 line
2.30.2
Re: [PATCH net-next v3 04/18] net: stmmac: use unsigned int for eee_timer
Quoted 10 lines · Russell King (Oracle)
Since
eee_timeris used to initialisepriv->tx_lpi_timer, this also should be unsigned to avoid a negative number being interpreted as a very large positive number. Note that this makes the check for negative numbers passed in as a module parameter redundant, and passing a negative number will now produce a large delay rather than the default. Since the default is used without an argument, passing a negative number would be quite obscure. However, if users do, then this will need to be revisited.Signed-off-by Russell King (Oracle) <[email protected]>
PATCH v3 5/18 net: stmmac: make EEE depend on phy->enable_tx_lpi
In reply to Russell King (Oracle)Make stmmac EEE depend on phylib's evaluation of user settings and PHY negotiation, as indicated by phy->enable_tx_lpi. This will ensure when phylib has evaluated that the user has disabled LPI, phy_init_eee() will not be called, and priv->eee_active will be false, causing LPI/EEE to be disabled.
This is an interim measure - phy_init_eee() will be removed in a later patch.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1 -1
@@ -1083,7 +1083,7 @@ static void stmmac_mac_link_up(struct phylink_config *config,stmmac_mac_set (priv, priv->ioaddr, true);if (phy && priv->dma_cap.eee) { - priv->eee_active = + priv->eee_active = phy->enable_tx_lpi &&phy_init_eee (phy, !(priv->plat->flags &STMMAC_FLAG_RX_CLK_RUNS_IN_LPI )) >=0 ; priv->tx_lpi_timer = phy->eee_cfg.tx_lpi_timer;
Signature · 1 line
2.30.2
PATCH v3 6/18 net: stmmac: remove redundant code from ethtool EEE ops
In reply to Russell King (Oracle)Setting edata->tx_lpi_enabled in stmmac_ethtool_op_get_eee() gets overwritten by phylib, so there's no point setting this.
In stmmac_ethtool_op_set_eee(), now that stmmac is using the result of phylib's evaluation of EEE, there is no need to handle anything in the ethtool EEE ops other than calling through to the appropriate phylink function, which will pass on to phylib the users request.
As stmmac_disable_eee_mode() is now no longer called from outside stmmac_main.c, make it static.
--- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 - drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 9 --------- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- 3 files changed, 1 insertion(+), 11 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac.h +0 -1
@@ -405,7 +405,6 @@ void stmmac_dvr_remove(struct device *dev);int stmmac_dvr_probe (struct device *device,struct plat_stmmacenet_data *plat_dat,struct stmmac_resources *res); -void stmmac_disable_eee_mode (struct stmmac_priv *priv);int stmmac_reinit_queues (struct net_device *dev,u32 rx_cnt,u32 tx_cnt);int stmmac_reinit_ringparam (struct net_device *dev,u32 rx_size,u32 tx_size);int stmmac_bus_clks_config (struct stmmac_priv *priv,bool enabled);
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +0 -9
@@ -898,8 +898,6 @@ static int stmmac_ethtool_op_get_eee(struct net_device *dev,if (!priv->dma_cap.eee)return -EOPNOTSUPP ; - edata->tx_lpi_enabled = priv->tx_lpi_enabled; -return phylink_ethtool_get_eee (priv->phylink, edata); }
@@ -911,13 +909,6 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,if (!priv->dma_cap.eee)return -EOPNOTSUPP ; -if (priv->tx_lpi_enabled != edata->tx_lpi_enabled) -netdev_warn (priv->dev, -"Setting EEE tx-lpi is not supported\n" ); - -if (!edata->eee_enabled) -stmmac_disable_eee_mode (priv); -return phylink_ethtool_set_eee (priv->phylink, edata); }
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1 -1
@@ -432,7 +432,7 @@ static int stmmac_enable_eee_mode(struct stmmac_priv *priv)* Description: this function is to exit and disable EEE in case of * LPI state is true. This is called by the xmit. */ -void stmmac_disable_eee_mode (struct stmmac_priv *priv) +static void stmmac_disable_eee_mode (struct stmmac_priv *priv) {if (!priv->eee_sw_timer_en) {stmmac_lpi_entry_timer_config (priv,0 );
Signature · 1 line
2.30.2
PATCH v3 7/18 net: stmmac: clean up stmmac_disable_eee_mode()
In reply to Russell King (Oracle)stmmac_disable_eee_mode() is now only called from stmmac_xmit() when both priv->tx_path_in_lpi_mode and priv->eee_sw_timer_en are true. Therefore:
if (!priv->eee_sw_timer_en)
in stmmac_disable_eee_mode() will never be true, so this is dead code. Remove it, and rename the function to indicate that it now only deals with software based EEE mode.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +3 -8
@@ -427,18 +427,13 @@ static int stmmac_enable_eee_mode(struct stmmac_priv *priv) }/** -* stmmac_disable_eee_mode - disable and exit from LPI mode +* stmmac_disable_sw_eee_mode - disable and exit from LPI mode * @priv: driver private structure * Description: this function is to exit and disable EEE in case of * LPI state is true. This is called by the xmit. */ -static void stmmac_disable_eee_mode (struct stmmac_priv *priv) +static void stmmac_disable_sw_eee_mode (struct stmmac_priv *priv) { -if (!priv->eee_sw_timer_en) { -stmmac_lpi_entry_timer_config (priv,0 ); -return ; - } -stmmac_reset_eee_mode (priv, priv->hw);del_timer_sync (&priv->eee_ctrl_timer); priv->tx_path_in_lpi_mode = false;
@@ -4495,7 +4490,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) first_tx = tx_q->cur_tx;if (priv->tx_path_in_lpi_mode && priv->eee_sw_timer_en) -stmmac_disable_eee_mode (priv); +stmmac_disable_sw_eee_mode (priv);/* Manage oversized TCP frames for GMAC4 device */ if (skb_is_gso (skb) && priv->tso) {
Signature · 1 line
2.30.2
PATCH v3 8/18 net: stmmac: remove priv->tx_lpi_enabled
In reply to Russell King (Oracle)Through using phylib's EEE state, priv->tx_lpi_enabled has become a write-only variable. Remove it.
--- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 - drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 -- 2 files changed, 3 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac.h +0 -1
@@ -308,7 +308,6 @@ struct stmmac_priv {int eee_enabled;int eee_active;u32 tx_lpi_timer; -int tx_lpi_enabled;int eee_tw_timer;bool eee_sw_timer_en;unsigned int mode;
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +0 -2
@@ -968,7 +968,6 @@ static void stmmac_mac_link_down(struct phylink_config *config,stmmac_mac_set (priv, priv->ioaddr, false); priv->eee_active = false; - priv->tx_lpi_enabled = false; priv->eee_enabled =stmmac_eee_init (priv);stmmac_set_eee_pls (priv, priv->hw, false);
@@ -1083,7 +1082,6 @@ static void stmmac_mac_link_up(struct phylink_config *config, STMMAC_FLAG_RX_CLK_RUNS_IN_LPI)) >= 0; priv->tx_lpi_timer = phy->eee_cfg.tx_lpi_timer; priv->eee_enabled =stmmac_eee_init (priv); - priv->tx_lpi_enabled = priv->eee_enabled;stmmac_set_eee_pls (priv, priv->hw, true); }
Signature · 1 line
2.30.2
PATCH v3 9/18 net: stmmac: report EEE error statistics if EEE is supported
In reply to Russell King (Oracle)Report the number of EEE error statistics in the xstats even when EEE is not enabled in hardware, but is supported. The PHY maintains this counter even when EEE is not enabled.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +1 -1
@@ -654,7 +654,7 @@ static void stmmac_get_ethtool_stats(struct net_device *dev, (*(u32 *)p); } } -if (priv->eee_enabled) { +if (priv->dma_cap.eee) {int val =phylink_get_eee_err (priv->phylink);if (val) priv->xstats.phy_eee_wakeup_error_n = val;
Signature · 1 line
2.30.2
PATCH v3 10/18 net: stmmac: convert to use phy_eee_rx_clock_stop()
In reply to Russell King (Oracle)Convert stmmac to use phy_eee_rx_clock_stop() to set the PHY receive clock stop in LPI setting, rather than calling the legacy phy_init_eee() function.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +3 -3
@@ -1077,10 +1077,10 @@ static void stmmac_mac_link_up(struct phylink_config *config,stmmac_mac_set (priv, priv->ioaddr, true);if (phy && priv->dma_cap.eee) { - priv->eee_active = phy->enable_tx_lpi && -phy_init_eee (phy, !(priv->plat->flags & -STMMAC_FLAG_RX_CLK_RUNS_IN_LPI )) >=0 ; +phy_eee_rx_clock_stop (phy, !(priv->plat->flags & +STMMAC_FLAG_RX_CLK_RUNS_IN_LPI )); priv->tx_lpi_timer = phy->eee_cfg.tx_lpi_timer; + priv->eee_active = phy->enable_tx_lpi; priv->eee_enabled =stmmac_eee_init (priv);stmmac_set_eee_pls (priv, priv->hw, true); }
Signature · 1 line
2.30.2
PATCH v3 11/18 net: stmmac: remove priv->eee_tw_timer
In reply to Russell King (Oracle)priv->eee_tw_timer is only assigned during initialisation to a constant value (STMMAC_DEFAULT_TWT_LS) and then never changed.
Remove priv->eee_tw_timer, and instead use STMMAC_DEFAULT_TWT_LS for both uses in stmmac_eee_init().
--- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 - drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 9 +++------ 2 files changed, 3 insertions(+), 7 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac.h +0 -1
@@ -308,7 +308,6 @@ struct stmmac_priv {int eee_enabled;int eee_active;u32 tx_lpi_timer; -int eee_tw_timer;bool eee_sw_timer_en;unsigned int mode;unsigned int chain_mode;
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +3 -6
@@ -464,8 +464,6 @@ static void stmmac_eee_ctrl_timer(struct timer_list *t)*/ static bool stmmac_eee_init (struct stmmac_priv *priv) { -int eee_tw_timer = priv->eee_tw_timer; -/* Check if MAC core supports the EEE feature. */ if (!priv->dma_cap.eee)return false;
@@ -478,7 +476,8 @@ static bool stmmac_eee_init(struct stmmac_priv *priv)netdev_dbg (priv->dev,"disable EEE\n" );stmmac_lpi_entry_timer_config (priv,0 );del_timer_sync (&priv->eee_ctrl_timer); -stmmac_set_eee_timer (priv, priv->hw,0 , eee_tw_timer); +stmmac_set_eee_timer (priv, priv->hw,0 , +STMMAC_DEFAULT_TWT_LS );if (priv->hw->xpcs) xpcs_config_eee(priv->hw->xpcs, priv->plat->mult_fact_100ns,
@@ -491,7 +490,7 @@ static bool stmmac_eee_init(struct stmmac_priv *priv)if (priv->eee_active && !priv->eee_enabled) {timer_setup (&priv->eee_ctrl_timer, stmmac_eee_ctrl_timer,0 );stmmac_set_eee_timer (priv, priv->hw,STMMAC_DEFAULT_LIT_LS , - eee_tw_timer); +STMMAC_DEFAULT_TWT_LS );if (priv->hw->xpcs) xpcs_config_eee(priv->hw->xpcs, priv->plat->mult_fact_100ns,
@@ -3446,8 +3445,6 @@ static int stmmac_hw_setup(struct net_device *dev, bool ptp_register)else if (ptp_register)stmmac_ptp_register (priv); - priv->eee_tw_timer =STMMAC_DEFAULT_TWT_LS ; -if (priv->use_riwt) {u32 queue;
Signature · 1 line
2.30.2
PATCH v3 12/18 net: stmmac: move priv->eee_enabled into stmmac_eee_init()
In reply to Russell King (Oracle)All call sites for stmmac_eee_init() assign the return code to priv->eee_enabled. Rather than having this coded at each call site, move the assignment inside stmmac_eee_init().
Since stmmac_init_eee() takes priv->lock before checking the state of priv->eee_enabled, move the assignment within the locked region. Also, stmmac_suspend() checks the state of this member under the lock. While two concurrent calls to stmmac_init_eee() aren't possible, there is a possibility that stmmac_suspend() may run concurrently with a change of priv->eee_enabled unless we modify it under the lock.
--- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +11 -7
@@ -462,11 +462,13 @@ static void stmmac_eee_ctrl_timer(struct timer_list *t)* can also manage EEE, this function enable the LPI state and start related * timer. */ -static bool stmmac_eee_init (struct stmmac_priv *priv) +static void stmmac_eee_init (struct stmmac_priv *priv) {/* Check if MAC core supports the EEE feature. */ -if (!priv->dma_cap.eee) -return false; +if (!priv->dma_cap.eee) { + priv->eee_enabled = false; +return ; + }mutex_lock (&priv->lock);
@@ -483,8 +485,9 @@ static bool stmmac_eee_init(struct stmmac_priv *priv) priv->plat->mult_fact_100ns, false); } + priv->eee_enabled = false;mutex_unlock (&priv->lock); -return false; +return ; }if (priv->eee_active && !priv->eee_enabled) {
@@ -507,9 +510,10 @@ static bool stmmac_eee_init(struct stmmac_priv *priv) STMMAC_LPI_T(priv->tx_lpi_timer)); } + priv->eee_enabled = true; +mutex_unlock (&priv->lock);netdev_dbg (priv->dev,"Energy-Efficient Ethernet initialized\n" ); -return true; }/* stmmac_get_tx_hwtstamp - get HW TX timestamps
@@ -967,7 +971,7 @@ static void stmmac_mac_link_down(struct phylink_config *config,stmmac_mac_set (priv, priv->ioaddr, false); priv->eee_active = false; - priv->eee_enabled =stmmac_eee_init (priv); +stmmac_eee_init (priv);stmmac_set_eee_pls (priv, priv->hw, false);if (stmmac_fpe_supported (priv))
@@ -1080,7 +1084,7 @@ static void stmmac_mac_link_up(struct phylink_config *config, STMMAC_FLAG_RX_CLK_RUNS_IN_LPI)); priv->tx_lpi_timer = phy->eee_cfg.tx_lpi_timer; priv->eee_active = phy->enable_tx_lpi; - priv->eee_enabled =stmmac_eee_init (priv); +stmmac_eee_init (priv);stmmac_set_eee_pls (priv, priv->hw, true); }
Signature · 1 line
2.30.2
PATCH v3 13/18 net: stmmac: move priv->eee_active into stmmac_eee_init()
In reply to Russell King (Oracle)Since all call sites of stmmac_eee_init() assign priv->eee_active immediately before, pass this state into stmmac_eee_init() and assign priv->eee_active within this function.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +6 -5
@@ -457,13 +457,16 @@ static void stmmac_eee_ctrl_timer(struct timer_list *t)/** * stmmac_eee_init - init EEE * @priv: driver private structure +* @active: indicates whether EEE should be enabled. * Description: * if the GMAC supports the EEE (from the HW cap reg) and the phy device * can also manage EEE, this function enable the LPI state and start related * timer. */ -static void stmmac_eee_init (struct stmmac_priv *priv) +static void stmmac_eee_init (struct stmmac_priv *priv,bool active) { + priv->eee_active = active; +/* Check if MAC core supports the EEE feature. */ if (!priv->dma_cap.eee) { priv->eee_enabled = false;
@@ -970,8 +973,7 @@ static void stmmac_mac_link_down(struct phylink_config *config,struct stmmac_priv *priv =netdev_priv (to_net_dev (config->dev));stmmac_mac_set (priv, priv->ioaddr, false); - priv->eee_active = false; -stmmac_eee_init (priv); +stmmac_eee_init (priv, false);stmmac_set_eee_pls (priv, priv->hw, false);if (stmmac_fpe_supported (priv))
@@ -1083,8 +1085,7 @@ static void stmmac_mac_link_up(struct phylink_config *config,phy_eee_rx_clock_stop (phy, !(priv->plat->flags &STMMAC_FLAG_RX_CLK_RUNS_IN_LPI )); priv->tx_lpi_timer = phy->eee_cfg.tx_lpi_timer; - priv->eee_active = phy->enable_tx_lpi; -stmmac_eee_init (priv); +stmmac_eee_init (priv, phy->enable_tx_lpi);stmmac_set_eee_pls (priv, priv->hw, true); }
Signature · 1 line
2.30.2
PATCH v3 14/18 net: stmmac: use boolean for eee_enabled and eee_active
In reply to Russell King (Oracle)priv->eee_enabled and priv->eee_active are both assigned using boolean values. Type them as bool rather than int.
--- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac.h +2 -2
@@ -305,9 +305,9 @@ struct stmmac_priv {int clk_csr;struct timer_list eee_ctrl_timer;int lpi_irq; -int eee_enabled; -int eee_active;u32 tx_lpi_timer; +bool eee_enabled; +bool eee_active;bool eee_sw_timer_en;unsigned int mode;unsigned int chain_mode;
Signature · 1 line
2.30.2
PATCH v3 15/18 net: stmmac: move setup of eee_ctrl_timer to stmmac_dvr_probe()
In reply to Russell King (Oracle)Move the initialisation of the EEE software timer to the probe function as it is unnecessary to do this each time we enable software LPI.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +2 -1
@@ -494,7 +494,6 @@ static void stmmac_eee_init(struct stmmac_priv *priv, bool active) }if (priv->eee_active && !priv->eee_enabled) { -timer_setup (&priv->eee_ctrl_timer, stmmac_eee_ctrl_timer,0 );stmmac_set_eee_timer (priv, priv->hw,STMMAC_DEFAULT_LIT_LS ,STMMAC_DEFAULT_TWT_LS );if (priv->hw->xpcs)
@@ -7405,6 +7404,8 @@ int stmmac_dvr_probe(struct device *device,INIT_WORK (&priv->service_task, stmmac_service_task); +timer_setup (&priv->eee_ctrl_timer, stmmac_eee_ctrl_timer,0 ); +/* Override with kernel parameters if supplied XXX CRS XXX * this needs to have multiple instances */
Signature · 1 line
2.30.2
PATCH v3 16/18 net: stmmac: remove unnecessary EEE handling in stmmac_release()
In reply to Russell King (Oracle)phylink_stop() will cause phylink to call the mac_link_down() operation before phylink_stop() returns. As mac_link_down() will call stmmac_eee_init(false), this will set both priv->eee_active and priv->eee_enabled to be false, deleting the eee_ctrl_timer if priv->eee_enabled was previously set.
As stmmac_release() calls phylink_stop() before checking whether priv->eee_enabled is true, this is a condition that can never be satisfied, and thus the code within this if() block will never be executed. Remove it.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 5 ----- 1 file changed, 5 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +0 -5
@@ -4033,11 +4033,6 @@ static int stmmac_release(struct net_device *dev)/* Free the IRQ lines */ stmmac_free_irq (dev,REQ_IRQ_ERR_ALL ,0 ); -if (priv->eee_enabled) { - priv->tx_path_in_lpi_mode = false; -del_timer_sync (&priv->eee_ctrl_timer); - } -/* Stop TX/RX DMA and clear the descriptors */ stmmac_stop_all_dma (priv);
Signature · 1 line
2.30.2
PATCH v3 17/18 net: stmmac: split hardware LPI timer control
In reply to Russell King (Oracle)Provide stmmac_disable_hw_lpi_timer() and stmmac_enable_hw_lpi_timer() to control the hardware transmit LPI timer.
--- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +14 -4
@@ -390,14 +390,24 @@ static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv, u32 queue)return dirty; } -static void stmmac_lpi_entry_timer_config (struct stmmac_priv *priv,bool en) +static void stmmac_disable_hw_lpi_timer (struct stmmac_priv *priv) +{ +stmmac_set_eee_lpi_timer (priv, priv->hw,0 ); +} + +static void stmmac_enable_hw_lpi_timer (struct stmmac_priv *priv) { -u32 tx_lpi_timer; +stmmac_set_eee_lpi_timer (priv, priv->hw, priv->tx_lpi_timer); +} +static void stmmac_lpi_entry_timer_config (struct stmmac_priv *priv,bool en) +{/* Clear/set the SW EEE timer flag based on LPI ET enablement */ priv->eee_sw_timer_en = en ?0 :1 ; - tx_lpi_timer = en ? priv->tx_lpi_timer :0 ; -stmmac_set_eee_lpi_timer (priv, priv->hw, tx_lpi_timer); +if (en) +stmmac_enable_hw_lpi_timer (priv); +else +stmmac_disable_hw_lpi_timer (priv); }/**
Signature · 1 line
2.30.2
PATCH v3 18/18 net: stmmac: remove stmmac_lpi_entry_timer_config()
In reply to Russell King (Oracle)Remove stmmac_lpi_entry_timer_config(), setting priv->eee_sw_timer_en at the original call sites, and calling the appropriate stmmac_xxx_hw_lpi_timer() function. No functional change.
--- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +8 -13
@@ -400,16 +400,6 @@ static void stmmac_enable_hw_lpi_timer(struct stmmac_priv *priv)stmmac_set_eee_lpi_timer (priv, priv->hw, priv->tx_lpi_timer); } -static void stmmac_lpi_entry_timer_config (struct stmmac_priv *priv,bool en) -{ -/* Clear/set the SW EEE timer flag based on LPI ET enablement */ - priv->eee_sw_timer_en = en ?0 :1 ; -if (en) -stmmac_enable_hw_lpi_timer (priv); -else -stmmac_disable_hw_lpi_timer (priv); -} -/** * stmmac_enable_eee_mode - check and enter in LPI mode * @priv: driver private structure
@@ -489,7 +479,8 @@ static void stmmac_eee_init(struct stmmac_priv *priv, bool active)if (!priv->eee_active) {if (priv->eee_enabled) {netdev_dbg (priv->dev,"disable EEE\n" ); -stmmac_lpi_entry_timer_config (priv,0 ); + priv->eee_sw_timer_en = true; +stmmac_disable_hw_lpi_timer (priv);del_timer_sync (&priv->eee_ctrl_timer);stmmac_set_eee_timer (priv, priv->hw,0 ,STMMAC_DEFAULT_TWT_LS );
@@ -513,11 +504,15 @@ static void stmmac_eee_init(struct stmmac_priv *priv, bool active) }if (priv->plat->has_gmac4 && priv->tx_lpi_timer <=STMMAC_ET_MAX ) { +/* Use hardware LPI mode */ del_timer_sync (&priv->eee_ctrl_timer); priv->tx_path_in_lpi_mode = false; -stmmac_lpi_entry_timer_config (priv,1 ); + priv->eee_sw_timer_en = false; +stmmac_enable_hw_lpi_timer (priv); }else { -stmmac_lpi_entry_timer_config (priv,0 ); +/* Use software LPI mode */ + priv->eee_sw_timer_en = true; +stmmac_disable_hw_lpi_timer (priv);mod_timer (&priv->eee_ctrl_timer,STMMAC_LPI_T (priv->tx_lpi_timer)); }
Signature · 1 line
2.30.2