mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
net: stmmac: block PHY RXC clock-stop
The DesignWare core requires the receive clock to be running during certain operations. Ensure that we block PHY RXC clock-stop during these operations. This is a best-efforts change - not everywhere can be covered by this because of net's core locking, which means we can't access the MDIO bus to configure the PHY to disable RXC clock-stop in certain areas. These are marked with FIXME comments. Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> Link: https://patch.msgid.link/E1tvO6p-008Vjz-Qy@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
ddf4bd3f73
commit
dd557266cf
@@ -3484,9 +3484,18 @@ static int stmmac_hw_setup(struct net_device *dev, bool ptp_register)
|
|||||||
if (priv->hw->phylink_pcs)
|
if (priv->hw->phylink_pcs)
|
||||||
phylink_pcs_pre_init(priv->phylink, priv->hw->phylink_pcs);
|
phylink_pcs_pre_init(priv->phylink, priv->hw->phylink_pcs);
|
||||||
|
|
||||||
|
/* Note that clk_rx_i must be running for reset to complete. This
|
||||||
|
* clock may also be required when setting the MAC address.
|
||||||
|
*
|
||||||
|
* Block the receive clock stop for LPI mode at the PHY in case
|
||||||
|
* the link is established with EEE mode active.
|
||||||
|
*/
|
||||||
|
phylink_rx_clk_stop_block(priv->phylink);
|
||||||
|
|
||||||
/* DMA initialization and SW reset */
|
/* DMA initialization and SW reset */
|
||||||
ret = stmmac_init_dma_engine(priv);
|
ret = stmmac_init_dma_engine(priv);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
phylink_rx_clk_stop_unblock(priv->phylink);
|
||||||
netdev_err(priv->dev, "%s: DMA engine initialization failed\n",
|
netdev_err(priv->dev, "%s: DMA engine initialization failed\n",
|
||||||
__func__);
|
__func__);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -3494,6 +3503,7 @@ static int stmmac_hw_setup(struct net_device *dev, bool ptp_register)
|
|||||||
|
|
||||||
/* Copy the MAC addr into the HW */
|
/* Copy the MAC addr into the HW */
|
||||||
stmmac_set_umac_addr(priv, priv->hw, dev->dev_addr, 0);
|
stmmac_set_umac_addr(priv, priv->hw, dev->dev_addr, 0);
|
||||||
|
phylink_rx_clk_stop_unblock(priv->phylink);
|
||||||
|
|
||||||
/* PS and related bits will be programmed according to the speed */
|
/* PS and related bits will be programmed according to the speed */
|
||||||
if (priv->hw->pcs) {
|
if (priv->hw->pcs) {
|
||||||
@@ -3604,7 +3614,9 @@ static int stmmac_hw_setup(struct net_device *dev, bool ptp_register)
|
|||||||
/* Start the ball rolling... */
|
/* Start the ball rolling... */
|
||||||
stmmac_start_all_dma(priv);
|
stmmac_start_all_dma(priv);
|
||||||
|
|
||||||
|
phylink_rx_clk_stop_block(priv->phylink);
|
||||||
stmmac_set_hw_vlan_mode(priv, priv->hw);
|
stmmac_set_hw_vlan_mode(priv, priv->hw);
|
||||||
|
phylink_rx_clk_stop_unblock(priv->phylink);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -5888,6 +5900,9 @@ static void stmmac_tx_timeout(struct net_device *dev, unsigned int txqueue)
|
|||||||
* whenever multicast addresses must be enabled/disabled.
|
* whenever multicast addresses must be enabled/disabled.
|
||||||
* Return value:
|
* Return value:
|
||||||
* void.
|
* void.
|
||||||
|
*
|
||||||
|
* FIXME: This may need RXC to be running, but it may be called with BH
|
||||||
|
* disabled, which means we can't call phylink_rx_clk_stop*().
|
||||||
*/
|
*/
|
||||||
static void stmmac_set_rx_mode(struct net_device *dev)
|
static void stmmac_set_rx_mode(struct net_device *dev)
|
||||||
{
|
{
|
||||||
@@ -6020,7 +6035,9 @@ static int stmmac_set_features(struct net_device *netdev,
|
|||||||
else
|
else
|
||||||
priv->hw->hw_vlan_en = false;
|
priv->hw->hw_vlan_en = false;
|
||||||
|
|
||||||
|
phylink_rx_clk_stop_block(priv->phylink);
|
||||||
stmmac_set_hw_vlan_mode(priv, priv->hw);
|
stmmac_set_hw_vlan_mode(priv, priv->hw);
|
||||||
|
phylink_rx_clk_stop_unblock(priv->phylink);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -6304,7 +6321,9 @@ static int stmmac_set_mac_address(struct net_device *ndev, void *addr)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto set_mac_error;
|
goto set_mac_error;
|
||||||
|
|
||||||
|
phylink_rx_clk_stop_block(priv->phylink);
|
||||||
stmmac_set_umac_addr(priv, priv->hw, ndev->dev_addr, 0);
|
stmmac_set_umac_addr(priv, priv->hw, ndev->dev_addr, 0);
|
||||||
|
phylink_rx_clk_stop_unblock(priv->phylink);
|
||||||
|
|
||||||
set_mac_error:
|
set_mac_error:
|
||||||
pm_runtime_put(priv->device);
|
pm_runtime_put(priv->device);
|
||||||
@@ -6660,6 +6679,9 @@ static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
|
|||||||
return stmmac_update_vlan_hash(priv, priv->hw, hash, pmatch, is_double);
|
return stmmac_update_vlan_hash(priv, priv->hw, hash, pmatch, is_double);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: This may need RXC to be running, but it may be called with BH
|
||||||
|
* disabled, which means we can't call phylink_rx_clk_stop*().
|
||||||
|
*/
|
||||||
static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid)
|
static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid)
|
||||||
{
|
{
|
||||||
struct stmmac_priv *priv = netdev_priv(ndev);
|
struct stmmac_priv *priv = netdev_priv(ndev);
|
||||||
@@ -6691,6 +6713,9 @@ err_pm_put:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: This may need RXC to be running, but it may be called with BH
|
||||||
|
* disabled, which means we can't call phylink_rx_clk_stop*().
|
||||||
|
*/
|
||||||
static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vid)
|
static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vid)
|
||||||
{
|
{
|
||||||
struct stmmac_priv *priv = netdev_priv(ndev);
|
struct stmmac_priv *priv = netdev_priv(ndev);
|
||||||
@@ -7951,9 +7976,11 @@ int stmmac_resume(struct device *dev)
|
|||||||
|
|
||||||
stmmac_hw_setup(ndev, false);
|
stmmac_hw_setup(ndev, false);
|
||||||
stmmac_init_coalesce(priv);
|
stmmac_init_coalesce(priv);
|
||||||
|
phylink_rx_clk_stop_block(priv->phylink);
|
||||||
stmmac_set_rx_mode(ndev);
|
stmmac_set_rx_mode(ndev);
|
||||||
|
|
||||||
stmmac_restore_hw_vlan_rx_fltr(priv, ndev, priv->hw);
|
stmmac_restore_hw_vlan_rx_fltr(priv, ndev, priv->hw);
|
||||||
|
phylink_rx_clk_stop_unblock(priv->phylink);
|
||||||
|
|
||||||
stmmac_enable_all_queues(priv);
|
stmmac_enable_all_queues(priv);
|
||||||
stmmac_enable_all_dma_irq(priv);
|
stmmac_enable_all_dma_irq(priv);
|
||||||
|
|||||||
Reference in New Issue
Block a user