Skip to content

Commit 3afe11b

Browse files
Joakim Zhanggregkh
authored andcommitted
net: stmmac: add clocks management for gmac driver
commit 5ec5582 upstream. This patch intends to add clocks management for stmmac driver: If CONFIG_PM enabled: 1. Keep clocks disabled after driver probed. 2. Enable clocks when up the net device, and disable clocks when down the net device. If CONFIG_PM disabled: Keep clocks always enabled after driver probed. Note: 1. It is fine for ethtool, since the way of implementing ethtool_ops::begin in stmmac is only can be accessed when interface is enabled, so the clocks are ticked. 2. The MDIO bus has a different life cycle to the MAC, need ensure clocks are enabled when _mdio_read/write() need clocks, because these functions can be called while the interface it not opened. Stable backport notes: When run below command to remove ethernet driver on stratix10 platform, there will be warning trace as below: $ cd /sys/class/net/eth0/device/driver/ $ echo ff800000.ethernet > unbind WARNING: CPU: 3 PID: 386 at drivers/clk/clk.c:810 clk_core_unprepare+0x114/0x274 Modules linked in: sch_fq_codel CPU: 3 PID: 386 Comm: sh Tainted: G W 5.10.74-yocto-standard #1 Hardware name: SoCFPGA Stratix 10 SoCDK (DT) pstate: 00000005 (nzcv daif -PAN -UAO -TCO BTYPE=--) pc : clk_core_unprepare+0x114/0x274 lr : clk_core_unprepare+0x114/0x274 sp : ffff800011bdbb10 clk_core_unprepare+0x114/0x274 clk_unprepare+0x38/0x50 stmmac_remove_config_dt+0x40/0x80 stmmac_pltfr_remove+0x64/0x80 platform_drv_remove+0x38/0x60 ... .. el0_sync_handler+0x1a4/0x1b0 el0_sync+0x180/0x1c0 This issue is introduced by introducing upstream commit 8f26910 ("net: stmmac: disable clocks in stmmac_remove_config_dt()") But in latest mainline kernel, there is no this issue. Because this patch improved clocks management for stmmac driver. Therefore, backport it and its fixing patches to stable kernel v5.10. Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net> Cc: stable@vger.kernel.org Signed-off-by: Meng Li <Meng.Li@windriver.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent f27060e commit 3afe11b

4 files changed

Lines changed: 174 additions & 37 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ void stmmac_disable_eee_mode(struct stmmac_priv *priv);
270270
bool stmmac_eee_init(struct stmmac_priv *priv);
271271
int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt);
272272
int stmmac_reinit_ringparam(struct net_device *dev, u32 rx_size, u32 tx_size);
273+
int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled);
273274

274275
#if IS_ENABLED(CONFIG_STMMAC_SELFTESTS)
275276
void stmmac_selftest_run(struct net_device *dev,

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

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <linux/if_vlan.h>
2929
#include <linux/dma-mapping.h>
3030
#include <linux/slab.h>
31+
#include <linux/pm_runtime.h>
3132
#include <linux/prefetch.h>
3233
#include <linux/pinctrl/consumer.h>
3334
#ifdef CONFIG_DEBUG_FS
@@ -113,6 +114,28 @@ static void stmmac_exit_fs(struct net_device *dev);
113114

114115
#define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
115116

117+
int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled)
118+
{
119+
int ret = 0;
120+
121+
if (enabled) {
122+
ret = clk_prepare_enable(priv->plat->stmmac_clk);
123+
if (ret)
124+
return ret;
125+
ret = clk_prepare_enable(priv->plat->pclk);
126+
if (ret) {
127+
clk_disable_unprepare(priv->plat->stmmac_clk);
128+
return ret;
129+
}
130+
} else {
131+
clk_disable_unprepare(priv->plat->stmmac_clk);
132+
clk_disable_unprepare(priv->plat->pclk);
133+
}
134+
135+
return ret;
136+
}
137+
EXPORT_SYMBOL_GPL(stmmac_bus_clks_config);
138+
116139
/**
117140
* stmmac_verify_args - verify the driver parameters.
118141
* Description: it checks the driver parameters and set a default in case of
@@ -2792,6 +2815,12 @@ static int stmmac_open(struct net_device *dev)
27922815
u32 chan;
27932816
int ret;
27942817

2818+
ret = pm_runtime_get_sync(priv->device);
2819+
if (ret < 0) {
2820+
pm_runtime_put_noidle(priv->device);
2821+
return ret;
2822+
}
2823+
27952824
if (priv->hw->pcs != STMMAC_PCS_TBI &&
27962825
priv->hw->pcs != STMMAC_PCS_RTBI &&
27972826
priv->hw->xpcs == NULL) {
@@ -2800,7 +2829,7 @@ static int stmmac_open(struct net_device *dev)
28002829
netdev_err(priv->dev,
28012830
"%s: Cannot attach to PHY (error: %d)\n",
28022831
__func__, ret);
2803-
return ret;
2832+
goto init_phy_error;
28042833
}
28052834
}
28062835

@@ -2915,6 +2944,8 @@ static int stmmac_open(struct net_device *dev)
29152944
free_dma_desc_resources(priv);
29162945
dma_desc_error:
29172946
phylink_disconnect_phy(priv->phylink);
2947+
init_phy_error:
2948+
pm_runtime_put(priv->device);
29182949
return ret;
29192950
}
29202951

@@ -2965,6 +2996,8 @@ static int stmmac_release(struct net_device *dev)
29652996

29662997
stmmac_release_ptp(priv);
29672998

2999+
pm_runtime_put(priv->device);
3000+
29683001
return 0;
29693002
}
29703003

@@ -4616,6 +4649,12 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
46164649
bool is_double = false;
46174650
int ret;
46184651

4652+
ret = pm_runtime_get_sync(priv->device);
4653+
if (ret < 0) {
4654+
pm_runtime_put_noidle(priv->device);
4655+
return ret;
4656+
}
4657+
46194658
if (be16_to_cpu(proto) == ETH_P_8021AD)
46204659
is_double = true;
46214660

@@ -4624,10 +4663,15 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
46244663
if (priv->hw->num_vlan) {
46254664
ret = stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
46264665
if (ret)
4627-
return ret;
4666+
goto del_vlan_error;
46284667
}
46294668

4630-
return stmmac_vlan_update(priv, is_double);
4669+
ret = stmmac_vlan_update(priv, is_double);
4670+
4671+
del_vlan_error:
4672+
pm_runtime_put(priv->device);
4673+
4674+
return ret;
46314675
}
46324676

46334677
static const struct net_device_ops stmmac_netdev_ops = {
@@ -5066,6 +5110,10 @@ int stmmac_dvr_probe(struct device *device,
50665110

50675111
stmmac_check_pcs_mode(priv);
50685112

5113+
pm_runtime_get_noresume(device);
5114+
pm_runtime_set_active(device);
5115+
pm_runtime_enable(device);
5116+
50695117
if (priv->hw->pcs != STMMAC_PCS_TBI &&
50705118
priv->hw->pcs != STMMAC_PCS_RTBI) {
50715119
/* MDIO bus Registration */
@@ -5103,6 +5151,11 @@ int stmmac_dvr_probe(struct device *device,
51035151
stmmac_init_fs(ndev);
51045152
#endif
51055153

5154+
/* Let pm_runtime_put() disable the clocks.
5155+
* If CONFIG_PM is not enabled, the clocks will stay powered.
5156+
*/
5157+
pm_runtime_put(device);
5158+
51065159
return ret;
51075160

51085161
error_serdes_powerup:
@@ -5117,6 +5170,7 @@ int stmmac_dvr_probe(struct device *device,
51175170
stmmac_napi_del(ndev);
51185171
error_hw_init:
51195172
destroy_workqueue(priv->wq);
5173+
stmmac_bus_clks_config(priv, false);
51205174

51215175
return ret;
51225176
}
@@ -5152,8 +5206,8 @@ int stmmac_dvr_remove(struct device *dev)
51525206
phylink_destroy(priv->phylink);
51535207
if (priv->plat->stmmac_rst)
51545208
reset_control_assert(priv->plat->stmmac_rst);
5155-
clk_disable_unprepare(priv->plat->pclk);
5156-
clk_disable_unprepare(priv->plat->stmmac_clk);
5209+
pm_runtime_put(dev);
5210+
pm_runtime_disable(dev);
51575211
if (priv->hw->pcs != STMMAC_PCS_TBI &&
51585212
priv->hw->pcs != STMMAC_PCS_RTBI)
51595213
stmmac_mdio_unregister(ndev);
@@ -5176,6 +5230,7 @@ int stmmac_suspend(struct device *dev)
51765230
struct net_device *ndev = dev_get_drvdata(dev);
51775231
struct stmmac_priv *priv = netdev_priv(ndev);
51785232
u32 chan;
5233+
int ret;
51795234

51805235
if (!ndev || !netif_running(ndev))
51815236
return 0;
@@ -5219,8 +5274,9 @@ int stmmac_suspend(struct device *dev)
52195274
pinctrl_pm_select_sleep_state(priv->device);
52205275
/* Disable clock in case of PWM is off */
52215276
clk_disable_unprepare(priv->plat->clk_ptp_ref);
5222-
clk_disable_unprepare(priv->plat->pclk);
5223-
clk_disable_unprepare(priv->plat->stmmac_clk);
5277+
ret = pm_runtime_force_suspend(dev);
5278+
if (ret)
5279+
return ret;
52245280
}
52255281
mutex_unlock(&priv->lock);
52265282

@@ -5286,8 +5342,9 @@ int stmmac_resume(struct device *dev)
52865342
} else {
52875343
pinctrl_pm_select_default_state(priv->device);
52885344
/* enable the clk previously disabled */
5289-
clk_prepare_enable(priv->plat->stmmac_clk);
5290-
clk_prepare_enable(priv->plat->pclk);
5345+
ret = pm_runtime_force_resume(dev);
5346+
if (ret)
5347+
return ret;
52915348
if (priv->plat->clk_ptp_ref)
52925349
clk_prepare_enable(priv->plat->clk_ptp_ref);
52935350
/* reset the phy so that it's ready */

0 commit comments

Comments
 (0)