Skip to content

Commit 5ec5582

Browse files
Joakim Zhangdavem330
Joakim Zhang
authored andcommitted
net: stmmac: add clocks management for gmac driver
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. Reviewed-by: Andrew Lunn <[email protected]> Signed-off-by: Joakim Zhang <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 91de5ac commit 5ec5582

File tree

4 files changed

+174
-37
lines changed

4 files changed

+174
-37
lines changed

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

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

276277
#if IS_ENABLED(CONFIG_STMMAC_SELFTESTS)
277278
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) (ns_to_ktime((x) * NSEC_PER_USEC))
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
@@ -2896,6 +2919,12 @@ static int stmmac_open(struct net_device *dev)
28962919
u32 chan;
28972920
int ret;
28982921

2922+
ret = pm_runtime_get_sync(priv->device);
2923+
if (ret < 0) {
2924+
pm_runtime_put_noidle(priv->device);
2925+
return ret;
2926+
}
2927+
28992928
if (priv->hw->pcs != STMMAC_PCS_TBI &&
29002929
priv->hw->pcs != STMMAC_PCS_RTBI &&
29012930
priv->hw->xpcs_args.an_mode != DW_AN_C73) {
@@ -2904,7 +2933,7 @@ static int stmmac_open(struct net_device *dev)
29042933
netdev_err(priv->dev,
29052934
"%s: Cannot attach to PHY (error: %d)\n",
29062935
__func__, ret);
2907-
return ret;
2936+
goto init_phy_error;
29082937
}
29092938
}
29102939

@@ -3020,6 +3049,8 @@ static int stmmac_open(struct net_device *dev)
30203049
free_dma_desc_resources(priv);
30213050
dma_desc_error:
30223051
phylink_disconnect_phy(priv->phylink);
3052+
init_phy_error:
3053+
pm_runtime_put(priv->device);
30233054
return ret;
30243055
}
30253056

@@ -3070,6 +3101,8 @@ static int stmmac_release(struct net_device *dev)
30703101

30713102
stmmac_release_ptp(priv);
30723103

3104+
pm_runtime_put(priv->device);
3105+
30733106
return 0;
30743107
}
30753108

@@ -4706,6 +4739,12 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
47064739
bool is_double = false;
47074740
int ret;
47084741

4742+
ret = pm_runtime_get_sync(priv->device);
4743+
if (ret < 0) {
4744+
pm_runtime_put_noidle(priv->device);
4745+
return ret;
4746+
}
4747+
47094748
if (be16_to_cpu(proto) == ETH_P_8021AD)
47104749
is_double = true;
47114750

@@ -4739,10 +4778,15 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
47394778
if (priv->hw->num_vlan) {
47404779
ret = stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
47414780
if (ret)
4742-
return ret;
4781+
goto del_vlan_error;
47434782
}
47444783

4745-
return stmmac_vlan_update(priv, is_double);
4784+
ret = stmmac_vlan_update(priv, is_double);
4785+
4786+
del_vlan_error:
4787+
pm_runtime_put(priv->device);
4788+
4789+
return ret;
47464790
}
47474791

47484792
static const struct net_device_ops stmmac_netdev_ops = {
@@ -5181,6 +5225,10 @@ int stmmac_dvr_probe(struct device *device,
51815225

51825226
stmmac_check_pcs_mode(priv);
51835227

5228+
pm_runtime_get_noresume(device);
5229+
pm_runtime_set_active(device);
5230+
pm_runtime_enable(device);
5231+
51845232
if (priv->hw->pcs != STMMAC_PCS_TBI &&
51855233
priv->hw->pcs != STMMAC_PCS_RTBI) {
51865234
/* MDIO bus Registration */
@@ -5218,6 +5266,11 @@ int stmmac_dvr_probe(struct device *device,
52185266
stmmac_init_fs(ndev);
52195267
#endif
52205268

5269+
/* Let pm_runtime_put() disable the clocks.
5270+
* If CONFIG_PM is not enabled, the clocks will stay powered.
5271+
*/
5272+
pm_runtime_put(device);
5273+
52215274
return ret;
52225275

52235276
error_serdes_powerup:
@@ -5232,6 +5285,7 @@ int stmmac_dvr_probe(struct device *device,
52325285
stmmac_napi_del(ndev);
52335286
error_hw_init:
52345287
destroy_workqueue(priv->wq);
5288+
stmmac_bus_clks_config(priv, false);
52355289

52365290
return ret;
52375291
}
@@ -5267,8 +5321,8 @@ int stmmac_dvr_remove(struct device *dev)
52675321
phylink_destroy(priv->phylink);
52685322
if (priv->plat->stmmac_rst)
52695323
reset_control_assert(priv->plat->stmmac_rst);
5270-
clk_disable_unprepare(priv->plat->pclk);
5271-
clk_disable_unprepare(priv->plat->stmmac_clk);
5324+
pm_runtime_put(dev);
5325+
pm_runtime_disable(dev);
52725326
if (priv->hw->pcs != STMMAC_PCS_TBI &&
52735327
priv->hw->pcs != STMMAC_PCS_RTBI)
52745328
stmmac_mdio_unregister(ndev);
@@ -5291,6 +5345,7 @@ int stmmac_suspend(struct device *dev)
52915345
struct net_device *ndev = dev_get_drvdata(dev);
52925346
struct stmmac_priv *priv = netdev_priv(ndev);
52935347
u32 chan;
5348+
int ret;
52945349

52955350
if (!ndev || !netif_running(ndev))
52965351
return 0;
@@ -5334,8 +5389,9 @@ int stmmac_suspend(struct device *dev)
53345389
pinctrl_pm_select_sleep_state(priv->device);
53355390
/* Disable clock in case of PWM is off */
53365391
clk_disable_unprepare(priv->plat->clk_ptp_ref);
5337-
clk_disable_unprepare(priv->plat->pclk);
5338-
clk_disable_unprepare(priv->plat->stmmac_clk);
5392+
ret = pm_runtime_force_suspend(dev);
5393+
if (ret)
5394+
return ret;
53395395
}
53405396
mutex_unlock(&priv->lock);
53415397

@@ -5401,8 +5457,9 @@ int stmmac_resume(struct device *dev)
54015457
} else {
54025458
pinctrl_pm_select_default_state(priv->device);
54035459
/* enable the clk previously disabled */
5404-
clk_prepare_enable(priv->plat->stmmac_clk);
5405-
clk_prepare_enable(priv->plat->pclk);
5460+
ret = pm_runtime_force_resume(dev);
5461+
if (ret)
5462+
return ret;
54065463
if (priv->plat->clk_ptp_ref)
54075464
clk_prepare_enable(priv->plat->clk_ptp_ref);
54085465
/* reset the phy so that it's ready */

0 commit comments

Comments
 (0)