]> Gentwo Git Trees - linux/.git/commitdiff
net: dsa: yt921x: Add STP/MST support
authorDavid Yang <mmyangfl@gmail.com>
Mon, 1 Dec 2025 09:42:29 +0000 (17:42 +0800)
committerJakub Kicinski <kuba@kernel.org>
Mon, 1 Dec 2025 23:10:13 +0000 (15:10 -0800)
Support for STP/MST was deferred from the initial submission of the
driver.

Signed-off-by: David Yang <mmyangfl@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20251201094232.3155105-3-mmyangfl@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/dsa/yt921x.c
drivers/net/dsa/yt921x.h

index d5fb17d2b6e0e41147effdf49e2e9500301e1ec8..12e1bd5a106172adccbb63d9a74c4d3f2f168888 100644 (file)
@@ -2098,6 +2098,117 @@ yt921x_dsa_port_bridge_join(struct dsa_switch *ds, int port,
        return res;
 }
 
+static int
+yt921x_dsa_port_mst_state_set(struct dsa_switch *ds, int port,
+                             const struct switchdev_mst_state *st)
+{
+       struct yt921x_priv *priv = to_yt921x_priv(ds);
+       u32 mask;
+       u32 ctrl;
+       int res;
+
+       mask = YT921X_STP_PORTn_M(port);
+       switch (st->state) {
+       case BR_STATE_DISABLED:
+               ctrl = YT921X_STP_PORTn_DISABLED(port);
+               break;
+       case BR_STATE_LISTENING:
+       case BR_STATE_LEARNING:
+               ctrl = YT921X_STP_PORTn_LEARNING(port);
+               break;
+       case BR_STATE_FORWARDING:
+       default:
+               ctrl = YT921X_STP_PORTn_FORWARD(port);
+               break;
+       case BR_STATE_BLOCKING:
+               ctrl = YT921X_STP_PORTn_BLOCKING(port);
+               break;
+       }
+
+       mutex_lock(&priv->reg_lock);
+       res = yt921x_reg_update_bits(priv, YT921X_STPn(st->msti), mask, ctrl);
+       mutex_unlock(&priv->reg_lock);
+
+       return res;
+}
+
+static int
+yt921x_dsa_vlan_msti_set(struct dsa_switch *ds, struct dsa_bridge bridge,
+                        const struct switchdev_vlan_msti *msti)
+{
+       struct yt921x_priv *priv = to_yt921x_priv(ds);
+       u64 mask64;
+       u64 ctrl64;
+       int res;
+
+       if (!msti->vid)
+               return -EINVAL;
+       if (!msti->msti || msti->msti >= YT921X_MSTI_NUM)
+               return -EINVAL;
+
+       mask64 = YT921X_VLAN_CTRL_STP_ID_M;
+       ctrl64 = YT921X_VLAN_CTRL_STP_ID(msti->msti);
+
+       mutex_lock(&priv->reg_lock);
+       res = yt921x_reg64_update_bits(priv, YT921X_VLANn_CTRL(msti->vid),
+                                      mask64, ctrl64);
+       mutex_unlock(&priv->reg_lock);
+
+       return res;
+}
+
+static void
+yt921x_dsa_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
+{
+       struct yt921x_priv *priv = to_yt921x_priv(ds);
+       struct dsa_port *dp = dsa_to_port(ds, port);
+       struct device *dev = to_device(priv);
+       bool learning;
+       u32 mask;
+       u32 ctrl;
+       int res;
+
+       mask = YT921X_STP_PORTn_M(port);
+       learning = false;
+       switch (state) {
+       case BR_STATE_DISABLED:
+               ctrl = YT921X_STP_PORTn_DISABLED(port);
+               break;
+       case BR_STATE_LISTENING:
+               ctrl = YT921X_STP_PORTn_LEARNING(port);
+               break;
+       case BR_STATE_LEARNING:
+               ctrl = YT921X_STP_PORTn_LEARNING(port);
+               learning = dp->learning;
+               break;
+       case BR_STATE_FORWARDING:
+       default:
+               ctrl = YT921X_STP_PORTn_FORWARD(port);
+               learning = dp->learning;
+               break;
+       case BR_STATE_BLOCKING:
+               ctrl = YT921X_STP_PORTn_BLOCKING(port);
+               break;
+       }
+
+       mutex_lock(&priv->reg_lock);
+       do {
+               res = yt921x_reg_update_bits(priv, YT921X_STPn(0), mask, ctrl);
+               if (res)
+                       break;
+
+               mask = YT921X_PORT_LEARN_DIS;
+               ctrl = !learning ? YT921X_PORT_LEARN_DIS : 0;
+               res = yt921x_reg_update_bits(priv, YT921X_PORTn_LEARN(port),
+                                            mask, ctrl);
+       } while (0);
+       mutex_unlock(&priv->reg_lock);
+
+       if (res)
+               dev_err(dev, "Failed to %s port %d: %i\n", "set STP state for",
+                       port, res);
+}
+
 static int yt921x_port_down(struct yt921x_priv *priv, int port)
 {
        u32 mask;
@@ -2783,6 +2894,10 @@ static const struct dsa_switch_ops yt921x_dsa_switch_ops = {
        .port_bridge_flags      = yt921x_dsa_port_bridge_flags,
        .port_bridge_leave      = yt921x_dsa_port_bridge_leave,
        .port_bridge_join       = yt921x_dsa_port_bridge_join,
+       /* mst */
+       .port_mst_state_set     = yt921x_dsa_port_mst_state_set,
+       .vlan_msti_set          = yt921x_dsa_vlan_msti_set,
+       .port_stp_state_set     = yt921x_dsa_port_stp_state_set,
        /* port */
        .get_tag_protocol       = yt921x_dsa_get_tag_protocol,
        .phylink_get_caps       = yt921x_dsa_phylink_get_caps,
index 01ef623946fd6e15e88e3ad9bffedb97204ed2bc..61bb0ab3b09a3882bfb765feb28eadb3cbd8abd5 100644 (file)
 #define  YT921X_VLAN_IGR_FILTER_PORTn(port)    BIT(port)
 #define YT921X_PORTn_ISOLATION(port)   (0x180294 + 4 * (port))
 #define  YT921X_PORT_ISOLATION_BLOCKn(port)    BIT(port)
+#define YT921X_STPn(n)                 (0x18038c + 4 * (n))
+#define  YT921X_STP_PORTn_M(port)              GENMASK(2 * (port) + 1, 2 * (port))
+#define   YT921X_STP_PORTn(port, x)                    ((x) << (2 * (port)))
+#define   YT921X_STP_PORTn_DISABLED(port)              YT921X_STP_PORTn(port, 0)
+#define   YT921X_STP_PORTn_LEARNING(port)              YT921X_STP_PORTn(port, 1)
+#define   YT921X_STP_PORTn_BLOCKING(port)              YT921X_STP_PORTn(port, 2)
+#define   YT921X_STP_PORTn_FORWARD(port)               YT921X_STP_PORTn(port, 3)
 #define YT921X_PORTn_LEARN(port)       (0x1803d0 + 4 * (port))
 #define  YT921X_PORT_LEARN_VID_LEARN_MULTI_EN  BIT(22)
 #define  YT921X_PORT_LEARN_VID_LEARN_MODE      BIT(21)
@@ -449,6 +456,8 @@ enum yt921x_fdb_entry_status {
        YT921X_FDB_ENTRY_STATUS_STATIC = 7,
 };
 
+#define YT921X_MSTI_NUM                16
+
 #define YT9215_MAJOR   0x9002
 #define YT9218_MAJOR   0x9001