[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20251030-k1-ethernet-fix-autoneg-v1-1-baa572607ccc@iscas.ac.cn>
Date: Thu, 30 Oct 2025 22:31:44 +0800
From: Vivian Wang <wangruikang@...as.ac.cn>
To: Andrew Lunn <andrew+netdev@...n.ch>,
"David S. Miller" <davem@...emloft.net>, Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>, Paolo Abeni <pabeni@...hat.com>,
Yixun Lan <dlan@...too.org>,
Maxime Chevallier <maxime.chevallier@...tlin.com>,
Vadim Fedorenko <vadim.fedorenko@...ux.dev>,
Troy Mitchell <troy.mitchell@...ux.spacemit.com>
Cc: netdev@...r.kernel.org, linux-riscv@...ts.infradead.org,
spacemit@...ts.linux.dev, linux-kernel@...r.kernel.org,
Vivian Wang <wangruikang@...as.ac.cn>
Subject: [PATCH net] net: spacemit: Implement emac_set_pauseparam properly
emac_set_pauseparam (the set_pauseparam callback) didn't properly update
phydev->advertising. Fix it by changing it to call phy_set_asym_pause.
Also simplify/reorganize related code around this.
Fixes: bfec6d7f2001 ("net: spacemit: Add K1 Ethernet MAC")
Signed-off-by: Vivian Wang <wangruikang@...as.ac.cn>
---
drivers/net/ethernet/spacemit/k1_emac.c | 48 ++++++++++++++-------------------
1 file changed, 20 insertions(+), 28 deletions(-)
diff --git a/drivers/net/ethernet/spacemit/k1_emac.c b/drivers/net/ethernet/spacemit/k1_emac.c
index e1c5faff3b71..61d62c0f028e 100644
--- a/drivers/net/ethernet/spacemit/k1_emac.c
+++ b/drivers/net/ethernet/spacemit/k1_emac.c
@@ -133,7 +133,6 @@ struct emac_priv {
u32 rx_delay;
bool flow_control_autoneg;
- u8 flow_control;
/* Softirq-safe, hold while touching hardware statistics */
spinlock_t stats_lock;
@@ -1039,14 +1038,7 @@ static void emac_set_rx_fc(struct emac_priv *priv, bool enable)
emac_wr(priv, MAC_FC_CONTROL, val);
}
-static void emac_set_fc(struct emac_priv *priv, u8 fc)
-{
- emac_set_tx_fc(priv, fc & FLOW_CTRL_TX);
- emac_set_rx_fc(priv, fc & FLOW_CTRL_RX);
- priv->flow_control = fc;
-}
-
-static void emac_set_fc_autoneg(struct emac_priv *priv)
+static void emac_set_fc(struct emac_priv *priv)
{
struct phy_device *phydev = priv->ndev->phydev;
u32 local_adv, remote_adv;
@@ -1056,17 +1048,18 @@ static void emac_set_fc_autoneg(struct emac_priv *priv)
remote_adv = 0;
- if (phydev->pause)
+ /* Force settings in advertising if autoneg disabled */
+
+ if (!priv->flow_control_autoneg || phydev->pause)
remote_adv |= LPA_PAUSE_CAP;
- if (phydev->asym_pause)
+ if (!priv->flow_control_autoneg || phydev->asym_pause)
remote_adv |= LPA_PAUSE_ASYM;
fc = mii_resolve_flowctrl_fdx(local_adv, remote_adv);
- priv->flow_control_autoneg = true;
-
- emac_set_fc(priv, fc);
+ emac_set_tx_fc(priv, fc & FLOW_CTRL_TX);
+ emac_set_rx_fc(priv, fc & FLOW_CTRL_RX);
}
/*
@@ -1429,31 +1422,28 @@ static void emac_get_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *pause)
{
struct emac_priv *priv = netdev_priv(dev);
+ u32 val = emac_rd(priv, MAC_FC_CONTROL);
pause->autoneg = priv->flow_control_autoneg;
- pause->tx_pause = !!(priv->flow_control & FLOW_CTRL_TX);
- pause->rx_pause = !!(priv->flow_control & FLOW_CTRL_RX);
+ pause->tx_pause = !!(val & MREGBIT_FC_GENERATION_ENABLE);
+ pause->rx_pause = !!(val & MREGBIT_FC_DECODE_ENABLE);
}
static int emac_set_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *pause)
{
struct emac_priv *priv = netdev_priv(dev);
- u8 fc = 0;
+ struct phy_device *phydev = dev->phydev;
- priv->flow_control_autoneg = pause->autoneg;
+ if (!phydev)
+ return -ENODEV;
- if (pause->autoneg) {
- emac_set_fc_autoneg(priv);
- } else {
- if (pause->tx_pause)
- fc |= FLOW_CTRL_TX;
+ if (!phy_validate_pause(phydev, pause))
+ return -EINVAL;
- if (pause->rx_pause)
- fc |= FLOW_CTRL_RX;
+ priv->flow_control_autoneg = pause->autoneg;
- emac_set_fc(priv, fc);
- }
+ phy_set_asym_pause(dev->phydev, pause->rx_pause, pause->tx_pause);
return 0;
}
@@ -1632,7 +1622,7 @@ static void emac_adjust_link(struct net_device *dev)
emac_wr(priv, MAC_GLOBAL_CONTROL, ctrl);
- emac_set_fc_autoneg(priv);
+ emac_set_fc(priv);
}
phy_print_status(phydev);
@@ -2010,6 +2000,8 @@ static int emac_probe(struct platform_device *pdev)
priv->pdev = pdev;
platform_set_drvdata(pdev, priv);
+ priv->flow_control_autoneg = true;
+
ret = emac_config_dt(pdev, priv);
if (ret < 0)
return dev_err_probe(dev, ret, "Configuration failed\n");
---
base-commit: cb6649f6217c0331b885cf787f1d175963e2a1d2
change-id: 20251030-k1-ethernet-fix-autoneg-ae2a92b3c2db
Best regards,
--
Vivian "dramforever" Wang
Powered by blists - more mailing lists