From: Yongzhao Chen <yongzhao.derek@gmail.com>
To: netdev@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Florian Fainelli <florian.fainelli@broadcom.com>,
Andrew Lunn <andrew@lunn.ch>, Vladimir Oltean <olteanv@gmail.com>,
Christian Marangi <ansuelsmth@gmail.com>,
Russell King <linux@armlinux.org.uk>,
linux-kernel@vger.kernel.org, Ziyang Huang <hzyitc@outlook.com>
Subject: [RFC PATCH net-next v3 2/5] net: dsa: qca8k: serialize CPU MAC pause during MTU changes
Date: Wed, 23 Sep 2026 23:58:54 +0200 [thread overview]
Message-ID: <20260923215858.1653-3-yongzhao.derek@gmail.com> (raw)
In-Reply-To: <20260923215858.1653-1-yongzhao.derek@gmail.com>
The global maximum frame size must be updated with CPU MACs disabled.
The previous logic only paused ports 0 and 6, leaving an internal PHY
CPU port enabled while modifying the register.
Include enabled internal CPU ports in the pause sequence. Use the
existing reg_mutex to serialize the MTU update against port enable, port
disable, and phylink link-up and link-down transitions. Read and restore
each port's original TXMAC and RXMAC bits, ensuring ports that were down
remain down and preserving LINK_AUTO. Retain existing handling for ports
0 and 6.
Abort before updating the frame size if reading port status or pausing
the MAC fails. Attempt to restore all ports already modified, and report
any restoration failures even if an earlier error occurred.
The standalone qca8k MDIO error-propagation fix is a prerequisite for
this series; that error-handling bug predates this locking change.
Signed-off-by: Yongzhao Chen <yongzhao.derek@gmail.com>
Assisted-by: LLM
---
drivers/net/dsa/qca/qca8k-8xxx.c | 2 +
drivers/net/dsa/qca/qca8k-common.c | 79 ++++++++++++++++++++++++------
2 files changed, 66 insertions(+), 15 deletions(-)
diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
index f9e2eb0b9..d8564001c 100644
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
@@ -1488,7 +1488,9 @@ qca8k_phylink_mac_link_up(struct phylink_config *config,
reg |= QCA8K_PORT_STATUS_TXMAC | QCA8K_PORT_STATUS_RXMAC;
+ mutex_lock(&priv->reg_mutex);
qca8k_write(priv, QCA8K_REG_PORT_STATUS(port), reg);
+ mutex_unlock(&priv->reg_mutex);
}
static struct qca8k_pcs *pcs_to_qca8k_pcs(struct phylink_pcs *pcs)
diff --git a/drivers/net/dsa/qca/qca8k-common.c b/drivers/net/dsa/qca/qca8k-common.c
index 13005f10e..6b32bdd75 100644
--- a/drivers/net/dsa/qca/qca8k-common.c
+++ b/drivers/net/dsa/qca/qca8k-common.c
@@ -463,7 +463,8 @@ int qca8k_mib_init(struct qca8k_priv *priv)
return ret;
}
-void qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable)
+static void qca8k_port_set_status_locked(struct qca8k_priv *priv, int port,
+ int enable)
{
u32 mask = QCA8K_PORT_STATUS_TXMAC | QCA8K_PORT_STATUS_RXMAC;
@@ -477,6 +478,13 @@ void qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable)
regmap_clear_bits(priv->regmap, QCA8K_REG_PORT_STATUS(port), mask);
}
+void qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable)
+{
+ mutex_lock(&priv->reg_mutex);
+ qca8k_port_set_status_locked(priv, port, enable);
+ mutex_unlock(&priv->reg_mutex);
+}
+
void qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset,
uint8_t *data)
{
@@ -751,8 +759,10 @@ int qca8k_port_enable(struct dsa_switch *ds, int port,
{
struct qca8k_priv *priv = ds->priv;
- qca8k_port_set_status(priv, port, 1);
+ mutex_lock(&priv->reg_mutex);
+ qca8k_port_set_status_locked(priv, port, 1);
priv->port_enabled_map |= BIT(port);
+ mutex_unlock(&priv->reg_mutex);
if (dsa_is_user_port(ds, port))
phy_support_asym_pause(phy);
@@ -764,14 +774,20 @@ void qca8k_port_disable(struct dsa_switch *ds, int port)
{
struct qca8k_priv *priv = ds->priv;
- qca8k_port_set_status(priv, port, 0);
+ mutex_lock(&priv->reg_mutex);
+ qca8k_port_set_status_locked(priv, port, 0);
priv->port_enabled_map &= ~BIT(port);
+ mutex_unlock(&priv->reg_mutex);
}
int qca8k_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
{
+ u32 mask = QCA8K_PORT_STATUS_TXMAC | QCA8K_PORT_STATUS_RXMAC;
struct qca8k_priv *priv = ds->priv;
- int ret;
+ u32 status[QCA8K_NUM_PORTS] = { 0 };
+ int ret, restore_ret, i;
+ u32 stopped = 0;
+ u32 ports;
/* We have only have a general MTU setting.
* DSA always set the CPU port's MTU to the largest MTU of the user
@@ -784,25 +800,58 @@ int qca8k_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
/* To change the MAX_FRAME_SIZE the cpu ports must be off or
* the switch panics.
- * Turn off both cpu ports before applying the new value to prevent
- * this.
+ * Include internal PHY CPU ports as well as the two MAC-only ports.
+ * Toggle only MAC enables, preserving the phylink link-control mode.
*/
- if (priv->port_enabled_map & BIT(0))
- qca8k_port_set_status(priv, 0, 0);
+ ports = BIT(0) | BIT(6);
+ for (i = 1; i < 6; i++)
+ if (dsa_is_cpu_port(ds, i))
+ ports |= BIT(i);
- if (priv->port_enabled_map & BIT(6))
- qca8k_port_set_status(priv, 6, 0);
+ mutex_lock(&priv->reg_mutex);
+ ports &= priv->port_enabled_map;
+
+ for (i = 0; i < QCA8K_NUM_PORTS; i++) {
+ if (!(ports & BIT(i)))
+ continue;
+
+ ret = regmap_read(priv->regmap, QCA8K_REG_PORT_STATUS(i),
+ &status[i]);
+ if (ret)
+ goto unlock;
+ }
+
+ for (i = 0; i < QCA8K_NUM_PORTS; i++) {
+ if (!(ports & BIT(i)) || !(status[i] & mask))
+ continue;
+
+ stopped |= BIT(i);
+ ret = regmap_clear_bits(priv->regmap, QCA8K_REG_PORT_STATUS(i),
+ mask);
+ if (ret)
+ goto restore;
+ }
/* Include L2 header / FCS length */
ret = qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, new_mtu +
ETH_HLEN + ETH_FCS_LEN);
- if (priv->port_enabled_map & BIT(0))
- qca8k_port_set_status(priv, 0, 1);
-
- if (priv->port_enabled_map & BIT(6))
- qca8k_port_set_status(priv, 6, 1);
+restore:
+ for (i = 0; i < QCA8K_NUM_PORTS; i++)
+ if (stopped & BIT(i)) {
+ restore_ret = regmap_update_bits(priv->regmap,
+ QCA8K_REG_PORT_STATUS(i),
+ mask, status[i] & mask);
+ if (restore_ret) {
+ dev_err(priv->dev, "failed to restore MAC state on port %d: %d\n",
+ i, restore_ret);
+ if (!ret)
+ ret = restore_ret;
+ }
+ }
+unlock:
+ mutex_unlock(&priv->reg_mutex);
return ret;
}
--
2.43.0
next prev parent reply other threads:[~2026-09-23 21:59 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-23 21:58 [RFC PATCH net-next v3 0/5] net: dsa: qca8k: add a QCA8337 CPU PHY consumer Yongzhao Chen
2026-09-23 21:58 ` [RFC PATCH net-next v3 1/5] net: dsa: pass PHY flags when connecting shared ports Yongzhao Chen
2026-09-23 21:58 ` Yongzhao Chen [this message]
2026-09-23 21:58 ` [RFC PATCH net-next v3 3/5] net: dsa: qca8k: support QCA8337 internal PHY CPU links Yongzhao Chen
2026-09-23 21:58 ` [RFC PATCH net-next v3 4/5] net: dsa: qca8k: flag QCA8337 internal CPU PHYs for SmartSpeed Yongzhao Chen
2026-09-24 2:51 ` Andrew Lunn
2026-09-23 21:58 ` [RFC PATCH net-next v3 5/5] net: phy: qca83xx: disable SmartSpeed before resetting CPU PHYs Yongzhao Chen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260923215858.1653-3-yongzhao.derek@gmail.com \
--to=yongzhao.derek@gmail.com \
--cc=andrew@lunn.ch \
--cc=ansuelsmth@gmail.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=florian.fainelli@broadcom.com \
--cc=hzyitc@outlook.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=netdev@vger.kernel.org \
--cc=olteanv@gmail.com \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®