[PATCH net-next v4 8/8] net: dsa: mt7530: implement port_change_conduit op
From: Daniel Golle <daniel@makrotopia.org>
Date: 2026-07-19 17:54:42
Also in:
linux-arm-kernel, linux-mediatek, lkml
Subsystem:
mediatek switch driver, networking drivers, networking [dsa], the rest · Maintainers:
Chester A. Unal, Daniel Golle, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Vladimir Oltean, Linus Torvalds
Allow changing the CPU port affinity of user ports at runtime via the IFLA_DSA_CONDUIT netlink attribute. This updates the port matrix to forward to the new CPU port instead of the old one. Limit the operation to MT7531. There, trapped link-local frames follow the per-port affinity, as the MT7531_CPU_PMAP destination mask is further restricted by the port matrix. A conduit change is hence fully honoured by the hardware, for regular traffic as well as for trapped frames. The MT7530 switch, including the variant embedded in the MT7621 SoC, instead traps frames to the single CPU port set in the CPU_PORT field of the MFC register, regardless of the affinity of the inbound user port. With user ports affine to different CPU ports there is no correct value for that field, so per-port CPU affinity cannot be fully implemented for trapped frames. Routing a WAN port via the second SoC GMAC is conventionally covered by the PHY muxing feature on these switches, which bypasses the switch fabric and does not involve a CPU port at all. The switches on the MT7988, EN7581 and AN7583 SoCs only have a single CPU port, leaving no other conduit to change to. As the op lives in the shared mt7530_switch_ops, populate the extack when rejecting the unsupported variants instead of returning a bare -EOPNOTSUPP. Also reject a conduit that belongs to a different switch in the tree, whose port index has no meaning in the local port matrix. Signed-off-by: Daniel Golle <daniel@makrotopia.org> Acked-by: Chester A. Unal <chester.a.unal@arinc9.com> --- v3: * populate the netlink extack on rejection * refuse a conduit that lives on a different switch drivers/net/dsa/mt7530.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 52b549d7ee22..6fe6783dfe3f 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c@@ -3213,6 +3213,43 @@ static int mt753x_set_mac_eee(struct dsa_switch *ds, int port, return 0; } +static int +mt753x_port_change_conduit(struct dsa_switch *ds, int port, + struct net_device *conduit, + struct netlink_ext_ack *extack) +{ + struct dsa_port *new_cpu_dp = conduit->dsa_ptr; + struct dsa_port *dp = dsa_to_port(ds, port); + struct mt7530_priv *priv = ds->priv; + + if (priv->id != ID_MT7531) { + NL_SET_ERR_MSG_MOD(extack, + "Changing DSA conduit is only supported on MT7531"); + return -EOPNOTSUPP; + } + + if (new_cpu_dp->ds != ds) { + NL_SET_ERR_MSG_MOD(extack, + "Cannot assign a conduit on a different switch"); + return -EOPNOTSUPP; + } + + mutex_lock(&priv->reg_mutex); + + /* dp->cpu_dp still points to the old CPU port */ + priv->ports[port].pm &= ~PCR_MATRIX(BIT(dp->cpu_dp->index)); + priv->ports[port].pm |= PCR_MATRIX(BIT(new_cpu_dp->index)); + if (priv->ports[port].enable) + regmap_update_bits(priv->regmap, MT7530_PCR_P(port), + PCR_MATRIX_MASK, priv->ports[port].pm); + + mutex_unlock(&priv->reg_mutex); + + mt7530_port_fast_age(ds, port); + + return 0; +} + static void mt753x_conduit_state_change(struct dsa_switch *ds, const struct net_device *conduit,
@@ -3324,6 +3361,7 @@ static const struct dsa_switch_ops mt7530_switch_ops = { .setup = mt753x_setup, .teardown = mt753x_teardown, .preferred_default_local_cpu_port = mt753x_preferred_default_local_cpu_port, + .port_change_conduit = mt753x_port_change_conduit, .get_strings = mt7530_get_strings, .get_ethtool_stats = mt7530_get_ethtool_stats, .get_sset_count = mt7530_get_sset_count,
--
2.55.0