mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 18:13:41 +02:00
Merge branch 'net-stmmac-fix-serdes-power-methods'
Russell King says: ==================== net: stmmac: fix serdes power methods The stmmac serdes powerup/powerdown methods are not guaranteed to be called in a balancing fashion, but these are used to call the generic PHY subsystem's phy_power_up() and phy_power_down() methods which do require balanced calls. This series addresses this by making the stmmac serdes methods balanced. ==================== Link: https://patch.msgid.link/aYHHWm5UkD1JVa7D@shell.armlinux.org.uk Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
15dd03dfeb
|
|
@ -303,6 +303,7 @@ struct stmmac_priv {
|
|||
bool eee_enabled;
|
||||
bool eee_active;
|
||||
bool eee_sw_timer_en;
|
||||
bool legacy_serdes_is_powered;
|
||||
unsigned int mode;
|
||||
unsigned int chain_mode;
|
||||
int extend_desc;
|
||||
|
|
|
|||
|
|
@ -882,6 +882,30 @@ static void stmmac_release_ptp(struct stmmac_priv *priv)
|
|||
clk_disable_unprepare(priv->plat->clk_ptp_ref);
|
||||
}
|
||||
|
||||
static void stmmac_legacy_serdes_power_down(struct stmmac_priv *priv)
|
||||
{
|
||||
if (priv->plat->serdes_powerdown && priv->legacy_serdes_is_powered)
|
||||
priv->plat->serdes_powerdown(priv->dev, priv->plat->bsp_priv);
|
||||
|
||||
priv->legacy_serdes_is_powered = false;
|
||||
}
|
||||
|
||||
static int stmmac_legacy_serdes_power_up(struct stmmac_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!priv->plat->serdes_powerup)
|
||||
return 0;
|
||||
|
||||
ret = priv->plat->serdes_powerup(priv->dev, priv->plat->bsp_priv);
|
||||
if (ret < 0)
|
||||
netdev_err(priv->dev, "SerDes powerup failed\n");
|
||||
else
|
||||
priv->legacy_serdes_is_powered = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* stmmac_mac_flow_ctrl - Configure flow control in all queues
|
||||
* @priv: driver private structure
|
||||
|
|
@ -981,9 +1005,8 @@ static void stmmac_mac_link_up(struct phylink_config *config,
|
|||
u32 old_ctrl, ctrl;
|
||||
int ret;
|
||||
|
||||
if ((priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP) &&
|
||||
priv->plat->serdes_powerup)
|
||||
priv->plat->serdes_powerup(priv->dev, priv->plat->bsp_priv);
|
||||
if (priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP)
|
||||
stmmac_legacy_serdes_power_up(priv);
|
||||
|
||||
old_ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
|
||||
ctrl = old_ctrl & ~priv->hw->link.speed_mask;
|
||||
|
|
@ -4111,16 +4134,6 @@ static int __stmmac_open(struct net_device *dev,
|
|||
|
||||
stmmac_reset_queues_param(priv);
|
||||
|
||||
if (!(priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP) &&
|
||||
priv->plat->serdes_powerup) {
|
||||
ret = priv->plat->serdes_powerup(dev, priv->plat->bsp_priv);
|
||||
if (ret < 0) {
|
||||
netdev_err(priv->dev, "%s: Serdes powerup failed\n",
|
||||
__func__);
|
||||
goto init_error;
|
||||
}
|
||||
}
|
||||
|
||||
ret = stmmac_hw_setup(dev);
|
||||
if (ret < 0) {
|
||||
netdev_err(priv->dev, "%s: Hw setup failed\n", __func__);
|
||||
|
|
@ -4176,9 +4189,15 @@ static int stmmac_open(struct net_device *dev)
|
|||
if (ret)
|
||||
goto err_runtime_pm;
|
||||
|
||||
if (!(priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP)) {
|
||||
ret = stmmac_legacy_serdes_power_up(priv);
|
||||
if (ret < 0)
|
||||
goto err_disconnect_phy;
|
||||
}
|
||||
|
||||
ret = __stmmac_open(dev, dma_conf);
|
||||
if (ret)
|
||||
goto err_disconnect_phy;
|
||||
goto err_serdes;
|
||||
|
||||
kfree(dma_conf);
|
||||
|
||||
|
|
@ -4187,6 +4206,8 @@ static int stmmac_open(struct net_device *dev)
|
|||
|
||||
return ret;
|
||||
|
||||
err_serdes:
|
||||
stmmac_legacy_serdes_power_down(priv);
|
||||
err_disconnect_phy:
|
||||
phylink_disconnect_phy(priv->phylink);
|
||||
err_runtime_pm:
|
||||
|
|
@ -4221,10 +4242,6 @@ static void __stmmac_release(struct net_device *dev)
|
|||
/* Release and free the Rx/Tx resources */
|
||||
free_dma_desc_resources(priv, &priv->dma_conf);
|
||||
|
||||
/* Powerdown Serdes if there is */
|
||||
if (priv->plat->serdes_powerdown)
|
||||
priv->plat->serdes_powerdown(dev, priv->plat->bsp_priv);
|
||||
|
||||
stmmac_release_ptp(priv);
|
||||
|
||||
if (stmmac_fpe_supported(priv))
|
||||
|
|
@ -4250,6 +4267,7 @@ static int stmmac_release(struct net_device *dev)
|
|||
|
||||
__stmmac_release(dev);
|
||||
|
||||
stmmac_legacy_serdes_power_down(priv);
|
||||
phylink_disconnect_phy(priv->phylink);
|
||||
pm_runtime_put(priv->device);
|
||||
|
||||
|
|
@ -8130,8 +8148,7 @@ int stmmac_suspend(struct device *dev)
|
|||
/* Stop TX/RX DMA */
|
||||
stmmac_stop_all_dma(priv);
|
||||
|
||||
if (priv->plat->serdes_powerdown)
|
||||
priv->plat->serdes_powerdown(ndev, priv->plat->bsp_priv);
|
||||
stmmac_legacy_serdes_power_down(priv);
|
||||
|
||||
/* Enable Power down mode by programming the PMT regs */
|
||||
if (priv->wolopts) {
|
||||
|
|
@ -8233,11 +8250,8 @@ int stmmac_resume(struct device *dev)
|
|||
stmmac_mdio_reset(priv->mii);
|
||||
}
|
||||
|
||||
if (!(priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP) &&
|
||||
priv->plat->serdes_powerup) {
|
||||
ret = priv->plat->serdes_powerup(ndev,
|
||||
priv->plat->bsp_priv);
|
||||
|
||||
if (!(priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP)) {
|
||||
ret = stmmac_legacy_serdes_power_up(priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -8259,6 +8273,7 @@ int stmmac_resume(struct device *dev)
|
|||
ret = stmmac_hw_setup(ndev);
|
||||
if (ret < 0) {
|
||||
netdev_err(priv->dev, "%s: Hw setup failed\n", __func__);
|
||||
stmmac_legacy_serdes_power_down(priv);
|
||||
mutex_unlock(&priv->lock);
|
||||
rtnl_unlock();
|
||||
return ret;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user