Commit a3a57bf0 authored by Heiner Kallweit's avatar Heiner Kallweit Committed by Jakub Kicinski

net: stmmac: work around sporadic tx issue on link-up

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: bfab27a1 ("stmmac: add the experimental PCI support")
Suggested-by: default avatarQi Duan <qi.duan@amlogic.com>
Suggested-by: default avatarJerome Brunet <jbrunet@baylibre.com>
Signed-off-by: default avatarHeiner Kallweit <hkallweit1@gmail.com>
Link: https://lore.kernel.org/r/e99857ce-bd90-5093-ca8c-8cd480b5a0a2@gmail.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent ef332fe1
...@@ -258,14 +258,18 @@ EXPORT_SYMBOL_GPL(stmmac_set_mac_addr); ...@@ -258,14 +258,18 @@ EXPORT_SYMBOL_GPL(stmmac_set_mac_addr);
/* Enable disable MAC RX/TX */ /* Enable disable MAC RX/TX */
void stmmac_set_mac(void __iomem *ioaddr, bool enable) 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) if (enable)
value |= MAC_ENABLE_RX | MAC_ENABLE_TX; value |= MAC_ENABLE_RX | MAC_ENABLE_TX;
else else
value &= ~(MAC_ENABLE_TX | MAC_ENABLE_RX); 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, void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
......
...@@ -986,10 +986,10 @@ static void stmmac_mac_link_up(struct phylink_config *config, ...@@ -986,10 +986,10 @@ static void stmmac_mac_link_up(struct phylink_config *config,
bool tx_pause, bool rx_pause) bool tx_pause, bool rx_pause)
{ {
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev)); struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
u32 ctrl; u32 old_ctrl, ctrl;
ctrl = readl(priv->ioaddr + MAC_CTRL_REG); old_ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
ctrl &= ~priv->hw->link.speed_mask; ctrl = old_ctrl & ~priv->hw->link.speed_mask;
if (interface == PHY_INTERFACE_MODE_USXGMII) { if (interface == PHY_INTERFACE_MODE_USXGMII) {
switch (speed) { switch (speed) {
...@@ -1064,7 +1064,8 @@ static void stmmac_mac_link_up(struct phylink_config *config, ...@@ -1064,7 +1064,8 @@ static void stmmac_mac_link_up(struct phylink_config *config,
if (tx_pause && rx_pause) if (tx_pause && rx_pause)
stmmac_mac_flow_ctrl(priv, duplex); 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); stmmac_mac_set(priv, priv->ioaddr, true);
if (phy && priv->dma_cap.eee) { if (phy && priv->dma_cap.eee) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment