123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- From 23cfc7172e5297d0bee49ac6f6f8248d1cf0820d Mon Sep 17 00:00:00 2001
- From: Christian Marangi <[email protected]>
- Date: Sun, 30 Jul 2023 09:41:10 +0200
- Subject: [PATCH 1/4] net: dsa: qca8k: make learning configurable and keep off
- if standalone
- Address learning should initially be turned off by the driver for port
- operation in standalone mode, then the DSA core handles changes to it
- via ds->ops->port_bridge_flags().
- Currently this is not the case for qca8k where learning is enabled
- unconditionally in qca8k_setup for every user port.
- Handle ports configured in standalone mode by making the learning
- configurable and not enabling it by default.
- Implement .port_pre_bridge_flags and .port_bridge_flags dsa ops to
- enable learning for bridge that request it and tweak
- .port_stp_state_set to correctly disable learning when port is
- configured in standalone mode.
- Signed-off-by: Christian Marangi <[email protected]>
- Reviewed-by: Vladimir Oltean <[email protected]>
- Reviewed-by: Florian Fainelli <[email protected]>
- Link: https://lore.kernel.org/r/[email protected]
- Signed-off-by: Paolo Abeni <[email protected]>
- ---
- drivers/net/dsa/qca/qca8k-8xxx.c | 7 +++--
- drivers/net/dsa/qca/qca8k-common.c | 48 ++++++++++++++++++++++++++++++
- drivers/net/dsa/qca/qca8k.h | 6 ++++
- 3 files changed, 58 insertions(+), 3 deletions(-)
- --- a/drivers/net/dsa/qca/qca8k-8xxx.c
- +++ b/drivers/net/dsa/qca/qca8k-8xxx.c
- @@ -1894,9 +1894,8 @@ qca8k_setup(struct dsa_switch *ds)
- if (ret)
- return ret;
-
- - /* Enable ARP Auto-learning by default */
- - ret = regmap_set_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i),
- - QCA8K_PORT_LOOKUP_LEARN);
- + ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i),
- + QCA8K_PORT_LOOKUP_LEARN);
- if (ret)
- return ret;
-
- @@ -2002,6 +2001,8 @@ static const struct dsa_switch_ops qca8k
- .port_change_mtu = qca8k_port_change_mtu,
- .port_max_mtu = qca8k_port_max_mtu,
- .port_stp_state_set = qca8k_port_stp_state_set,
- + .port_pre_bridge_flags = qca8k_port_pre_bridge_flags,
- + .port_bridge_flags = qca8k_port_bridge_flags,
- .port_bridge_join = qca8k_port_bridge_join,
- .port_bridge_leave = qca8k_port_bridge_leave,
- .port_fast_age = qca8k_port_fast_age,
- --- a/drivers/net/dsa/qca/qca8k-common.c
- +++ b/drivers/net/dsa/qca/qca8k-common.c
- @@ -565,9 +565,26 @@ int qca8k_get_mac_eee(struct dsa_switch
- 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 +599,11 @@ void qca8k_port_stp_state_set(struct dsa
- 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 +611,34 @@ void qca8k_port_stp_state_set(struct dsa
-
- 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,
- --- a/drivers/net/dsa/qca/qca8k.h
- +++ b/drivers/net/dsa/qca/qca8k.h
- @@ -448,6 +448,12 @@ int qca8k_get_mac_eee(struct dsa_switch
-
- /* Common bridge function */
- void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state);
- +int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port,
- + struct switchdev_brport_flags flags,
- + struct netlink_ext_ack *extack);
- +int qca8k_port_bridge_flags(struct dsa_switch *ds, int port,
- + struct switchdev_brport_flags flags,
- + struct netlink_ext_ack *extack);
- int qca8k_port_bridge_join(struct dsa_switch *ds, int port,
- struct dsa_bridge bridge,
- bool *tx_fwd_offload,
|