diff options
Diffstat (limited to 'drivers/net/dsa/qca/qca8k-common.c')
-rw-r--r-- | drivers/net/dsa/qca/qca8k-common.c | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/drivers/net/dsa/qca/qca8k-common.c b/drivers/net/dsa/qca/qca8k-common.c index 13b8452ce5b2..9243eff8918d 100644 --- a/drivers/net/dsa/qca/qca8k-common.c +++ b/drivers/net/dsa/qca/qca8k-common.c @@ -487,8 +487,7 @@ void qca8k_get_strings(struct dsa_switch *ds, int port, u32 stringset, return; for (i = 0; i < priv->info->mib_count; i++) - strncpy(data + i * ETH_GSTRING_LEN, ar8327_mib[i].name, - ETH_GSTRING_LEN); + ethtool_sprintf(&data, "%s", ar8327_mib[i].name); } void qca8k_get_ethtool_stats(struct dsa_switch *ds, int port, @@ -500,7 +499,7 @@ void qca8k_get_ethtool_stats(struct dsa_switch *ds, int port, u32 hi = 0; int ret; - if (priv->mgmt_master && priv->info->ops->autocast_mib && + if (priv->mgmt_conduit && priv->info->ops->autocast_mib && priv->info->ops->autocast_mib(ds, port, data) > 0) return; @@ -565,9 +564,26 @@ int qca8k_get_mac_eee(struct dsa_switch *ds, int port, return 0; } +static int qca8k_port_configure_learning(struct dsa_switch *ds, int port, + bool learning) +{ + struct qca8k_priv *priv = ds->priv; + + if (learning) + return regmap_set_bits(priv->regmap, + QCA8K_PORT_LOOKUP_CTRL(port), + QCA8K_PORT_LOOKUP_LEARN); + else + return regmap_clear_bits(priv->regmap, + QCA8K_PORT_LOOKUP_CTRL(port), + QCA8K_PORT_LOOKUP_LEARN); +} + void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) { + struct dsa_port *dp = dsa_to_port(ds, port); struct qca8k_priv *priv = ds->priv; + bool learning = false; u32 stp_state; switch (state) { @@ -582,8 +598,11 @@ void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) break; case BR_STATE_LEARNING: stp_state = QCA8K_PORT_LOOKUP_STATE_LEARNING; + learning = dp->learning; break; case BR_STATE_FORWARDING: + learning = dp->learning; + fallthrough; default: stp_state = QCA8K_PORT_LOOKUP_STATE_FORWARD; break; @@ -591,6 +610,34 @@ void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), QCA8K_PORT_LOOKUP_STATE_MASK, stp_state); + + qca8k_port_configure_learning(ds, port, learning); +} + +int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) +{ + if (flags.mask & ~BR_LEARNING) + return -EINVAL; + + return 0; +} + +int qca8k_port_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) +{ + int ret; + + if (flags.mask & BR_LEARNING) { + ret = qca8k_port_configure_learning(ds, port, + flags.val & BR_LEARNING); + if (ret) + return ret; + } + + return 0; } int qca8k_port_bridge_join(struct dsa_switch *ds, int port, @@ -714,7 +761,7 @@ int qca8k_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu) int ret; /* We have only have a general MTU setting. - * DSA always set the CPU port's MTU to the largest MTU of the slave + * DSA always set the CPU port's MTU to the largest MTU of the user * ports. * Setting MTU just for the CPU port is sufficient to correctly set a * value for every port. |