]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: stmmac: work around sporadic tx issue on link-up
authorHeiner Kallweit <hkallweit1@gmail.com>
Wed, 24 Aug 2022 20:34:49 +0000 (22:34 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 31 Aug 2022 15:18:11 +0000 (17:18 +0200)
[ Upstream commit a3a57bf07de23fe1ff779e0fdf710aa581c3ff73 ]

This is a follow-up to the discussion in [0]. It seems to me that
at least the IP version used on Amlogic SoC's sometimes has a problem
if register MAC_CTRL_REG is written whilst the chip is still processing
a previous write. But that's just a guess.
Adding a delay between two writes to this register helps, but we can
also simply omit the offending second write. This patch uses the second
approach and is based on a suggestion from Qi Duan.
Benefit of this approach is that we can save few register writes, also
on not affected chip versions.

[0] https://www.spinics.net/lists/netdev/msg831526.html

Fixes: bfab27a146ed ("stmmac: add the experimental PCI support")
Suggested-by: Qi Duan <qi.duan@amlogic.com>
Suggested-by: Jerome Brunet <jbrunet@baylibre.com>
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Link: https://lore.kernel.org/r/e99857ce-bd90-5093-ca8c-8cd480b5a0a2@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

index caa4bfc4c1d62effb20b08de3e7d495743d9eb53..9b6138b11776656a91e3fa0c293c5d13177fda7c 100644 (file)
@@ -258,14 +258,18 @@ EXPORT_SYMBOL_GPL(stmmac_set_mac_addr);
 /* Enable disable MAC RX/TX */
 void stmmac_set_mac(void __iomem *ioaddr, bool enable)
 {
-       u32 value = readl(ioaddr + MAC_CTRL_REG);
+       u32 old_val, value;
+
+       old_val = readl(ioaddr + MAC_CTRL_REG);
+       value = old_val;
 
        if (enable)
                value |= MAC_ENABLE_RX | MAC_ENABLE_TX;
        else
                value &= ~(MAC_ENABLE_TX | MAC_ENABLE_RX);
 
-       writel(value, ioaddr + MAC_CTRL_REG);
+       if (value != old_val)
+               writel(value, ioaddr + MAC_CTRL_REG);
 }
 
 void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
index c5f33630e7718384fc0a0a63b36e5ca7dea5f549..78f11dabca056fba493ff0089101f3670f13961a 100644 (file)
@@ -983,10 +983,10 @@ static void stmmac_mac_link_up(struct phylink_config *config,
                               bool tx_pause, bool rx_pause)
 {
        struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
-       u32 ctrl;
+       u32 old_ctrl, ctrl;
 
-       ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
-       ctrl &= ~priv->hw->link.speed_mask;
+       old_ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
+       ctrl = old_ctrl & ~priv->hw->link.speed_mask;
 
        if (interface == PHY_INTERFACE_MODE_USXGMII) {
                switch (speed) {
@@ -1061,7 +1061,8 @@ static void stmmac_mac_link_up(struct phylink_config *config,
        if (tx_pause && rx_pause)
                stmmac_mac_flow_ctrl(priv, duplex);
 
-       writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
+       if (ctrl != old_ctrl)
+               writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
 
        stmmac_mac_set(priv, priv->ioaddr, true);
        if (phy && priv->dma_cap.eee) {