From e5ed29f1560338c634ef8b68e7fc8501a715c251 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 31 Aug 2026 16:39:26 +0100 Subject: [PATCH] net: dsa: mt7530: implement port_change_conduit op 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, AN7583 and EN7528 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 Acked-by: Chester A. Unal Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/cfc6a478a384a7f309f08d9f76be8fd029c1f202.1788190568.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski --- 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 84e0e888f2d0..28f94cd25b95 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -3249,6 +3249,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, @@ -3361,6 +3398,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,