Skip to content

Commit 676cfca

Browse files
committed
Merge branch 'net-stmmac-clean-up-and-fix-eee-implementation'
Russell King says: ==================== net: stmmac: clean up and fix EEE implementation 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. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 7b24f16 + 1655a22 commit 676cfca

File tree

7 files changed

+85
-87
lines changed

7 files changed

+85
-87
lines changed

drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,10 +420,10 @@ static void dwmac4_set_eee_pls(struct mac_device_info *hw, int link)
420420
writel(value, ioaddr + GMAC4_LPI_CTRL_STATUS);
421421
}
422422

423-
static void dwmac4_set_eee_lpi_entry_timer(struct mac_device_info *hw, int et)
423+
static void dwmac4_set_eee_lpi_entry_timer(struct mac_device_info *hw, u32 et)
424424
{
425425
void __iomem *ioaddr = hw->pcsr;
426-
int value = et & STMMAC_ET_MAX;
426+
u32 value = et & STMMAC_ET_MAX;
427427
int regval;
428428

429429
/* Program LPI entry timer value into register */

drivers/net/ethernet/stmicro/stmmac/hwif.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ struct stmmac_ops {
363363
void (*set_eee_mode)(struct mac_device_info *hw,
364364
bool en_tx_lpi_clockgating);
365365
void (*reset_eee_mode)(struct mac_device_info *hw);
366-
void (*set_eee_lpi_entry_timer)(struct mac_device_info *hw, int et);
366+
void (*set_eee_lpi_entry_timer)(struct mac_device_info *hw, u32 et);
367367
void (*set_eee_timer)(struct mac_device_info *hw, int ls, int tw);
368368
void (*set_eee_pls)(struct mac_device_info *hw, int link);
369369
void (*debug)(struct stmmac_priv *priv, void __iomem *ioaddr,

drivers/net/ethernet/stmicro/stmmac/stmmac.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -305,11 +305,9 @@ struct stmmac_priv {
305305
int clk_csr;
306306
struct timer_list eee_ctrl_timer;
307307
int lpi_irq;
308-
int eee_enabled;
309-
int eee_active;
310-
int tx_lpi_timer;
311-
int tx_lpi_enabled;
312-
int eee_tw_timer;
308+
u32 tx_lpi_timer;
309+
bool eee_enabled;
310+
bool eee_active;
313311
bool eee_sw_timer_en;
314312
unsigned int mode;
315313
unsigned int chain_mode;
@@ -405,8 +403,6 @@ void stmmac_dvr_remove(struct device *dev);
405403
int stmmac_dvr_probe(struct device *device,
406404
struct plat_stmmacenet_data *plat_dat,
407405
struct stmmac_resources *res);
408-
void stmmac_disable_eee_mode(struct stmmac_priv *priv);
409-
bool stmmac_eee_init(struct stmmac_priv *priv);
410406
int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt);
411407
int stmmac_reinit_ringparam(struct net_device *dev, u32 rx_size, u32 tx_size);
412408
int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled);

drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
654654
(*(u32 *)p);
655655
}
656656
}
657-
if (priv->eee_enabled) {
657+
if (priv->dma_cap.eee) {
658658
int val = phylink_get_eee_err(priv->phylink);
659659
if (val)
660660
priv->xstats.phy_eee_wakeup_error_n = val;
@@ -898,39 +898,18 @@ static int stmmac_ethtool_op_get_eee(struct net_device *dev,
898898
if (!priv->dma_cap.eee)
899899
return -EOPNOTSUPP;
900900

901-
edata->tx_lpi_timer = priv->tx_lpi_timer;
902-
edata->tx_lpi_enabled = priv->tx_lpi_enabled;
903-
904901
return phylink_ethtool_get_eee(priv->phylink, edata);
905902
}
906903

907904
static int stmmac_ethtool_op_set_eee(struct net_device *dev,
908905
struct ethtool_keee *edata)
909906
{
910907
struct stmmac_priv *priv = netdev_priv(dev);
911-
int ret;
912908

913909
if (!priv->dma_cap.eee)
914910
return -EOPNOTSUPP;
915911

916-
if (priv->tx_lpi_enabled != edata->tx_lpi_enabled)
917-
netdev_warn(priv->dev,
918-
"Setting EEE tx-lpi is not supported\n");
919-
920-
if (!edata->eee_enabled)
921-
stmmac_disable_eee_mode(priv);
922-
923-
ret = phylink_ethtool_set_eee(priv->phylink, edata);
924-
if (ret)
925-
return ret;
926-
927-
if (edata->eee_enabled &&
928-
priv->tx_lpi_timer != edata->tx_lpi_timer) {
929-
priv->tx_lpi_timer = edata->tx_lpi_timer;
930-
stmmac_eee_init(priv);
931-
}
932-
933-
return 0;
912+
return phylink_ethtool_set_eee(priv->phylink, edata);
934913
}
935914

936915
static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv)

drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

Lines changed: 54 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
111111
NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
112112

113113
#define STMMAC_DEFAULT_LPI_TIMER 1000
114-
static int eee_timer = STMMAC_DEFAULT_LPI_TIMER;
115-
module_param(eee_timer, int, 0644);
114+
static unsigned int eee_timer = STMMAC_DEFAULT_LPI_TIMER;
115+
module_param(eee_timer, uint, 0644);
116116
MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec");
117117
#define STMMAC_LPI_T(x) (jiffies + usecs_to_jiffies(x))
118118

@@ -194,8 +194,6 @@ static void stmmac_verify_args(void)
194194
flow_ctrl = FLOW_OFF;
195195
if (unlikely((pause < 0) || (pause > 0xffff)))
196196
pause = PAUSE_TIME;
197-
if (eee_timer < 0)
198-
eee_timer = STMMAC_DEFAULT_LPI_TIMER;
199197
}
200198

201199
static void __stmmac_disable_all_queues(struct stmmac_priv *priv)
@@ -392,14 +390,14 @@ static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv, u32 queue)
392390
return dirty;
393391
}
394392

395-
static void stmmac_lpi_entry_timer_config(struct stmmac_priv *priv, bool en)
393+
static void stmmac_disable_hw_lpi_timer(struct stmmac_priv *priv)
396394
{
397-
int tx_lpi_timer;
395+
stmmac_set_eee_lpi_timer(priv, priv->hw, 0);
396+
}
398397

399-
/* Clear/set the SW EEE timer flag based on LPI ET enablement */
400-
priv->eee_sw_timer_en = en ? 0 : 1;
401-
tx_lpi_timer = en ? priv->tx_lpi_timer : 0;
402-
stmmac_set_eee_lpi_timer(priv, priv->hw, tx_lpi_timer);
398+
static void stmmac_enable_hw_lpi_timer(struct stmmac_priv *priv)
399+
{
400+
stmmac_set_eee_lpi_timer(priv, priv->hw, priv->tx_lpi_timer);
403401
}
404402

405403
/**
@@ -429,18 +427,13 @@ static int stmmac_enable_eee_mode(struct stmmac_priv *priv)
429427
}
430428

431429
/**
432-
* stmmac_disable_eee_mode - disable and exit from LPI mode
430+
* stmmac_disable_sw_eee_mode - disable and exit from LPI mode
433431
* @priv: driver private structure
434432
* Description: this function is to exit and disable EEE in case of
435433
* LPI state is true. This is called by the xmit.
436434
*/
437-
void stmmac_disable_eee_mode(struct stmmac_priv *priv)
435+
static void stmmac_disable_sw_eee_mode(struct stmmac_priv *priv)
438436
{
439-
if (!priv->eee_sw_timer_en) {
440-
stmmac_lpi_entry_timer_config(priv, 0);
441-
return;
442-
}
443-
444437
stmmac_reset_eee_mode(priv, priv->hw);
445438
del_timer_sync(&priv->eee_ctrl_timer);
446439
priv->tx_path_in_lpi_mode = false;
@@ -464,60 +457,70 @@ static void stmmac_eee_ctrl_timer(struct timer_list *t)
464457
/**
465458
* stmmac_eee_init - init EEE
466459
* @priv: driver private structure
460+
* @active: indicates whether EEE should be enabled.
467461
* Description:
468462
* if the GMAC supports the EEE (from the HW cap reg) and the phy device
469463
* can also manage EEE, this function enable the LPI state and start related
470464
* timer.
471465
*/
472-
bool stmmac_eee_init(struct stmmac_priv *priv)
466+
static void stmmac_eee_init(struct stmmac_priv *priv, bool active)
473467
{
474-
int eee_tw_timer = priv->eee_tw_timer;
468+
priv->eee_active = active;
475469

476470
/* Check if MAC core supports the EEE feature. */
477-
if (!priv->dma_cap.eee)
478-
return false;
471+
if (!priv->dma_cap.eee) {
472+
priv->eee_enabled = false;
473+
return;
474+
}
479475

480476
mutex_lock(&priv->lock);
481477

482478
/* Check if it needs to be deactivated */
483479
if (!priv->eee_active) {
484480
if (priv->eee_enabled) {
485481
netdev_dbg(priv->dev, "disable EEE\n");
486-
stmmac_lpi_entry_timer_config(priv, 0);
482+
priv->eee_sw_timer_en = true;
483+
stmmac_disable_hw_lpi_timer(priv);
487484
del_timer_sync(&priv->eee_ctrl_timer);
488-
stmmac_set_eee_timer(priv, priv->hw, 0, eee_tw_timer);
485+
stmmac_set_eee_timer(priv, priv->hw, 0,
486+
STMMAC_DEFAULT_TWT_LS);
489487
if (priv->hw->xpcs)
490488
xpcs_config_eee(priv->hw->xpcs,
491489
priv->plat->mult_fact_100ns,
492490
false);
493491
}
492+
priv->eee_enabled = false;
494493
mutex_unlock(&priv->lock);
495-
return false;
494+
return;
496495
}
497496

498497
if (priv->eee_active && !priv->eee_enabled) {
499-
timer_setup(&priv->eee_ctrl_timer, stmmac_eee_ctrl_timer, 0);
500498
stmmac_set_eee_timer(priv, priv->hw, STMMAC_DEFAULT_LIT_LS,
501-
eee_tw_timer);
499+
STMMAC_DEFAULT_TWT_LS);
502500
if (priv->hw->xpcs)
503501
xpcs_config_eee(priv->hw->xpcs,
504502
priv->plat->mult_fact_100ns,
505503
true);
506504
}
507505

508506
if (priv->plat->has_gmac4 && priv->tx_lpi_timer <= STMMAC_ET_MAX) {
507+
/* Use hardware LPI mode */
509508
del_timer_sync(&priv->eee_ctrl_timer);
510509
priv->tx_path_in_lpi_mode = false;
511-
stmmac_lpi_entry_timer_config(priv, 1);
510+
priv->eee_sw_timer_en = false;
511+
stmmac_enable_hw_lpi_timer(priv);
512512
} else {
513-
stmmac_lpi_entry_timer_config(priv, 0);
513+
/* Use software LPI mode */
514+
priv->eee_sw_timer_en = true;
515+
stmmac_disable_hw_lpi_timer(priv);
514516
mod_timer(&priv->eee_ctrl_timer,
515517
STMMAC_LPI_T(priv->tx_lpi_timer));
516518
}
517519

520+
priv->eee_enabled = true;
521+
518522
mutex_unlock(&priv->lock);
519523
netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n");
520-
return true;
521524
}
522525

523526
/* stmmac_get_tx_hwtstamp - get HW TX timestamps
@@ -974,9 +977,7 @@ static void stmmac_mac_link_down(struct phylink_config *config,
974977
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
975978

976979
stmmac_mac_set(priv, priv->ioaddr, false);
977-
priv->eee_active = false;
978-
priv->tx_lpi_enabled = false;
979-
priv->eee_enabled = stmmac_eee_init(priv);
980+
stmmac_eee_init(priv, false);
980981
stmmac_set_eee_pls(priv, priv->hw, false);
981982

982983
if (stmmac_fpe_supported(priv))
@@ -1085,11 +1086,10 @@ static void stmmac_mac_link_up(struct phylink_config *config,
10851086

10861087
stmmac_mac_set(priv, priv->ioaddr, true);
10871088
if (phy && priv->dma_cap.eee) {
1088-
priv->eee_active =
1089-
phy_init_eee(phy, !(priv->plat->flags &
1090-
STMMAC_FLAG_RX_CLK_RUNS_IN_LPI)) >= 0;
1091-
priv->eee_enabled = stmmac_eee_init(priv);
1092-
priv->tx_lpi_enabled = priv->eee_enabled;
1089+
phy_eee_rx_clock_stop(phy, !(priv->plat->flags &
1090+
STMMAC_FLAG_RX_CLK_RUNS_IN_LPI));
1091+
priv->tx_lpi_timer = phy->eee_cfg.tx_lpi_timer;
1092+
stmmac_eee_init(priv, phy->enable_tx_lpi);
10931093
stmmac_set_eee_pls(priv, priv->hw, true);
10941094
}
10951095

@@ -1187,6 +1187,16 @@ static int stmmac_init_phy(struct net_device *dev)
11871187
ret = phylink_fwnode_phy_connect(priv->phylink, fwnode, 0);
11881188
}
11891189

1190+
if (ret == 0) {
1191+
struct ethtool_keee eee;
1192+
1193+
/* Configure phylib's copy of the LPI timer */
1194+
if (!phylink_ethtool_get_eee(priv->phylink, &eee)) {
1195+
eee.tx_lpi_timer = priv->tx_lpi_timer;
1196+
phylink_ethtool_set_eee(priv->phylink, &eee);
1197+
}
1198+
}
1199+
11901200
if (!priv->plat->pmt) {
11911201
struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
11921202

@@ -3452,12 +3462,6 @@ static int stmmac_hw_setup(struct net_device *dev, bool ptp_register)
34523462
else if (ptp_register)
34533463
stmmac_ptp_register(priv);
34543464

3455-
priv->eee_tw_timer = STMMAC_DEFAULT_TWT_LS;
3456-
3457-
/* Convert the timer from msec to usec */
3458-
if (!priv->tx_lpi_timer)
3459-
priv->tx_lpi_timer = eee_timer * 1000;
3460-
34613465
if (priv->use_riwt) {
34623466
u32 queue;
34633467

@@ -3924,6 +3928,10 @@ static int __stmmac_open(struct net_device *dev,
39243928
u32 chan;
39253929
int ret;
39263930

3931+
/* Initialise the tx lpi timer, converting from msec to usec */
3932+
if (!priv->tx_lpi_timer)
3933+
priv->tx_lpi_timer = eee_timer * 1000;
3934+
39273935
ret = pm_runtime_resume_and_get(priv->device);
39283936
if (ret < 0)
39293937
return ret;
@@ -4038,11 +4046,6 @@ static int stmmac_release(struct net_device *dev)
40384046
/* Free the IRQ lines */
40394047
stmmac_free_irq(dev, REQ_IRQ_ERR_ALL, 0);
40404048

4041-
if (priv->eee_enabled) {
4042-
priv->tx_path_in_lpi_mode = false;
4043-
del_timer_sync(&priv->eee_ctrl_timer);
4044-
}
4045-
40464049
/* Stop TX/RX DMA and clear the descriptors */
40474050
stmmac_stop_all_dma(priv);
40484051

@@ -4494,7 +4497,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
44944497
first_tx = tx_q->cur_tx;
44954498

44964499
if (priv->tx_path_in_lpi_mode && priv->eee_sw_timer_en)
4497-
stmmac_disable_eee_mode(priv);
4500+
stmmac_disable_sw_eee_mode(priv);
44984501

44994502
/* Manage oversized TCP frames for GMAC4 device */
45004503
if (skb_is_gso(skb) && priv->tso) {
@@ -7409,6 +7412,8 @@ int stmmac_dvr_probe(struct device *device,
74097412

74107413
INIT_WORK(&priv->service_task, stmmac_service_task);
74117414

7415+
timer_setup(&priv->eee_ctrl_timer, stmmac_eee_ctrl_timer, 0);
7416+
74127417
/* Override with kernel parameters if supplied XXX CRS XXX
74137418
* this needs to have multiple instances
74147419
*/

drivers/net/phy/phy.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,27 @@ void phy_mac_interrupt(struct phy_device *phydev)
16401640
}
16411641
EXPORT_SYMBOL(phy_mac_interrupt);
16421642

1643+
/**
1644+
* phy_eee_rx_clock_stop() - configure PHY receive clock in LPI
1645+
* @phydev: target phy_device struct
1646+
* @clk_stop_enable: flag to indicate whether the clock can be stopped
1647+
*
1648+
* Configure whether the PHY can disable its receive clock during LPI mode,
1649+
* See IEEE 802.3 sections 22.2.2.2, 35.2.2.10, and 45.2.3.1.4.
1650+
*
1651+
* Returns: 0 or negative error.
1652+
*/
1653+
int phy_eee_rx_clock_stop(struct phy_device *phydev, bool clk_stop_enable)
1654+
{
1655+
/* Configure the PHY to stop receiving xMII
1656+
* clock while it is signaling LPI.
1657+
*/
1658+
return phy_modify_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1,
1659+
MDIO_PCS_CTRL1_CLKSTOP_EN,
1660+
clk_stop_enable ? MDIO_PCS_CTRL1_CLKSTOP_EN : 0);
1661+
}
1662+
EXPORT_SYMBOL_GPL(phy_eee_rx_clock_stop);
1663+
16431664
/**
16441665
* phy_init_eee - init and check the EEE feature
16451666
* @phydev: target phy_device struct
@@ -1664,11 +1685,7 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
16641685
return -EPROTONOSUPPORT;
16651686

16661687
if (clk_stop_enable)
1667-
/* Configure the PHY to stop receiving xMII
1668-
* clock while it is signaling LPI.
1669-
*/
1670-
ret = phy_set_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1,
1671-
MDIO_PCS_CTRL1_CLKSTOP_EN);
1688+
ret = phy_eee_rx_clock_stop(phydev, true);
16721689

16731690
return ret < 0 ? ret : 0;
16741691
}

include/linux/phy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2096,6 +2096,7 @@ int phy_unregister_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask);
20962096
int phy_unregister_fixup_for_id(const char *bus_id);
20972097
int phy_unregister_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask);
20982098

2099+
int phy_eee_rx_clock_stop(struct phy_device *phydev, bool clk_stop_enable);
20992100
int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable);
21002101
int phy_get_eee_err(struct phy_device *phydev);
21012102
int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_keee *data);

0 commit comments

Comments
 (0)