mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
net: dsa: yt921x: Add STP/MST support
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>
This commit is contained in:
committed by
Jakub Kicinski
parent
d973ac83ad
commit
633b1d010c
@@ -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,
|
||||
|
||||
@@ -274,6 +274,13 @@
|
||||
#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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user