Skip to content

Commit 49725ff

Browse files
junxiaocPaolo Abeni
authored andcommitted
net: stmmac: power up/down serdes in stmmac_open/release
This commit fixes DMA engine reset timeout issue in suspend/resume with ADLink I-Pi SMARC Plus board which dmesg shows: ... [ 54.678271] PM: suspend exit [ 54.754066] intel-eth-pci 0000:00:1d.2 enp0s29f2: PHY [stmmac-3:01] driver [Maxlinear Ethernet GPY215B] (irq=POLL) [ 54.755808] intel-eth-pci 0000:00:1d.2 enp0s29f2: Register MEM_TYPE_PAGE_POOL RxQ-0 ... [ 54.780482] intel-eth-pci 0000:00:1d.2 enp0s29f2: Register MEM_TYPE_PAGE_POOL RxQ-7 [ 55.784098] intel-eth-pci 0000:00:1d.2: Failed to reset the dma [ 55.784111] intel-eth-pci 0000:00:1d.2 enp0s29f2: stmmac_hw_setup: DMA engine initialization failed [ 55.784115] intel-eth-pci 0000:00:1d.2 enp0s29f2: stmmac_open: Hw setup failed ... The issue is related with serdes which impacts clock. There is serdes in ADLink I-Pi SMARC board ethernet controller. Please refer to commit b9663b7 ("net: stmmac: Enable SERDES power up/down sequence") for detial. When issue is reproduced, DMA engine clock is not ready because serdes is not powered up. To reproduce DMA engine reset timeout issue with hardware which has serdes in GBE controller, install Ubuntu. In Ubuntu GUI, click "Power Off/Log Out" -> "Suspend" menu, it disables network interface, then goes to sleep mode. When it wakes up, it enables network interface again. Stmmac driver is called in this way: 1. stmmac_release: Stop network interface. In this function, it disables DMA engine and network interface; 2. stmmac_suspend: It is called in kernel suspend flow. But because network interface has been disabled(netif_running(ndev) is false), it does nothing and returns directly; 3. System goes into S3 or S0ix state. Some time later, system is waken up by keyboard or mouse; 4. stmmac_resume: It does nothing because network interface has been disabled; 5. stmmac_open: It is called to enable network interace again. DMA engine is initialized in this API, but serdes is not power on so there will be DMA engine reset timeout issue. Similarly, serdes powerdown should be added in stmmac_release. Network interface might be disabled by cmd "ifconfig eth0 down", DMA engine, phy and mac have been disabled in ndo_stop callback, serdes should be powered down as well. It doesn't make sense that serdes is on while other components have been turned off. If ethernet interface is in enabled state(netif_running(ndev) is true) before suspend/resume, the issue couldn't be reproduced because serdes could be powered up in stmmac_resume. Because serdes_powerup is added in stmmac_open, it doesn't need to be called in probe function. Fixes: b9663b7 ("net: stmmac: Enable SERDES power up/down sequence") Signed-off-by: Junxiao Chang <[email protected]> Reviewed-by: Voon Weifeng <[email protected]> Tested-by: Jimmy JS Chen <[email protected]> Tested-by: Looi, Hong Aun <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
1 parent 0dc3837 commit 49725ff

File tree

1 file changed

+13
-10
lines changed

1 file changed

+13
-10
lines changed

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

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3801,6 +3801,15 @@ static int __stmmac_open(struct net_device *dev,
38013801

38023802
stmmac_reset_queues_param(priv);
38033803

3804+
if (priv->plat->serdes_powerup) {
3805+
ret = priv->plat->serdes_powerup(dev, priv->plat->bsp_priv);
3806+
if (ret < 0) {
3807+
netdev_err(priv->dev, "%s: Serdes powerup failed\n",
3808+
__func__);
3809+
goto init_error;
3810+
}
3811+
}
3812+
38043813
ret = stmmac_hw_setup(dev, true);
38053814
if (ret < 0) {
38063815
netdev_err(priv->dev, "%s: Hw setup failed\n", __func__);
@@ -3904,6 +3913,10 @@ static int stmmac_release(struct net_device *dev)
39043913
/* Disable the MAC Rx/Tx */
39053914
stmmac_mac_set(priv, priv->ioaddr, false);
39063915

3916+
/* Powerdown Serdes if there is */
3917+
if (priv->plat->serdes_powerdown)
3918+
priv->plat->serdes_powerdown(dev, priv->plat->bsp_priv);
3919+
39073920
netif_carrier_off(dev);
39083921

39093922
stmmac_release_ptp(priv);
@@ -7293,14 +7306,6 @@ int stmmac_dvr_probe(struct device *device,
72937306
goto error_netdev_register;
72947307
}
72957308

7296-
if (priv->plat->serdes_powerup) {
7297-
ret = priv->plat->serdes_powerup(ndev,
7298-
priv->plat->bsp_priv);
7299-
7300-
if (ret < 0)
7301-
goto error_serdes_powerup;
7302-
}
7303-
73047309
#ifdef CONFIG_DEBUG_FS
73057310
stmmac_init_fs(ndev);
73067311
#endif
@@ -7315,8 +7320,6 @@ int stmmac_dvr_probe(struct device *device,
73157320

73167321
return ret;
73177322

7318-
error_serdes_powerup:
7319-
unregister_netdev(ndev);
73207323
error_netdev_register:
73217324
phylink_destroy(priv->phylink);
73227325
error_xpcs_setup:

0 commit comments

Comments
 (0)