1 From 23cfc7172e5297d0bee49ac6f6f8248d1cf0820d Mon Sep 17 00:00:00 2001
2 From: Christian Marangi <ansuelsmth@gmail.com>
3 Date: Sun, 30 Jul 2023 09:41:10 +0200
4 Subject: [PATCH 1/4] net: dsa: qca8k: make learning configurable and keep off
7 Address learning should initially be turned off by the driver for port
8 operation in standalone mode, then the DSA core handles changes to it
9 via ds->ops->port_bridge_flags().
11 Currently this is not the case for qca8k where learning is enabled
12 unconditionally in qca8k_setup for every user port.
14 Handle ports configured in standalone mode by making the learning
15 configurable and not enabling it by default.
17 Implement .port_pre_bridge_flags and .port_bridge_flags dsa ops to
18 enable learning for bridge that request it and tweak
19 .port_stp_state_set to correctly disable learning when port is
20 configured in standalone mode.
22 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
23 Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
24 Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
25 Link: https://lore.kernel.org/r/20230730074113.21889-2-ansuelsmth@gmail.com
26 Signed-off-by: Paolo Abeni <pabeni@redhat.com>
28 drivers/net/dsa/qca/qca8k-8xxx.c | 7 +++--
29 drivers/net/dsa/qca/qca8k-common.c | 48 ++++++++++++++++++++++++++++++
30 drivers/net/dsa/qca/qca8k.h | 6 ++++
31 3 files changed, 58 insertions(+), 3 deletions(-)
33 --- a/drivers/net/dsa/qca/qca8k-8xxx.c
34 +++ b/drivers/net/dsa/qca/qca8k-8xxx.c
35 @@ -1883,9 +1883,8 @@ qca8k_setup(struct dsa_switch *ds)
39 - /* Enable ARP Auto-learning by default */
40 - ret = regmap_set_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i),
41 - QCA8K_PORT_LOOKUP_LEARN);
42 + ret = regmap_clear_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(i),
43 + QCA8K_PORT_LOOKUP_LEARN);
47 @@ -1991,6 +1990,8 @@ static const struct dsa_switch_ops qca8k
48 .port_change_mtu = qca8k_port_change_mtu,
49 .port_max_mtu = qca8k_port_max_mtu,
50 .port_stp_state_set = qca8k_port_stp_state_set,
51 + .port_pre_bridge_flags = qca8k_port_pre_bridge_flags,
52 + .port_bridge_flags = qca8k_port_bridge_flags,
53 .port_bridge_join = qca8k_port_bridge_join,
54 .port_bridge_leave = qca8k_port_bridge_leave,
55 .port_fast_age = qca8k_port_fast_age,
56 --- a/drivers/net/dsa/qca/qca8k-common.c
57 +++ b/drivers/net/dsa/qca/qca8k-common.c
58 @@ -565,9 +565,26 @@ int qca8k_get_mac_eee(struct dsa_switch
62 +static int qca8k_port_configure_learning(struct dsa_switch *ds, int port,
65 + struct qca8k_priv *priv = ds->priv;
68 + return regmap_set_bits(priv->regmap,
69 + QCA8K_PORT_LOOKUP_CTRL(port),
70 + QCA8K_PORT_LOOKUP_LEARN);
72 + return regmap_clear_bits(priv->regmap,
73 + QCA8K_PORT_LOOKUP_CTRL(port),
74 + QCA8K_PORT_LOOKUP_LEARN);
77 void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
79 + struct dsa_port *dp = dsa_to_port(ds, port);
80 struct qca8k_priv *priv = ds->priv;
81 + bool learning = false;
85 @@ -582,8 +599,11 @@ void qca8k_port_stp_state_set(struct dsa
87 case BR_STATE_LEARNING:
88 stp_state = QCA8K_PORT_LOOKUP_STATE_LEARNING;
89 + learning = dp->learning;
91 case BR_STATE_FORWARDING:
92 + learning = dp->learning;
95 stp_state = QCA8K_PORT_LOOKUP_STATE_FORWARD;
97 @@ -591,6 +611,34 @@ void qca8k_port_stp_state_set(struct dsa
99 qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
100 QCA8K_PORT_LOOKUP_STATE_MASK, stp_state);
102 + qca8k_port_configure_learning(ds, port, learning);
105 +int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port,
106 + struct switchdev_brport_flags flags,
107 + struct netlink_ext_ack *extack)
109 + if (flags.mask & ~BR_LEARNING)
115 +int qca8k_port_bridge_flags(struct dsa_switch *ds, int port,
116 + struct switchdev_brport_flags flags,
117 + struct netlink_ext_ack *extack)
121 + if (flags.mask & BR_LEARNING) {
122 + ret = qca8k_port_configure_learning(ds, port,
123 + flags.val & BR_LEARNING);
131 int qca8k_port_bridge_join(struct dsa_switch *ds, int port,
132 --- a/drivers/net/dsa/qca/qca8k.h
133 +++ b/drivers/net/dsa/qca/qca8k.h
134 @@ -448,6 +448,12 @@ int qca8k_get_mac_eee(struct dsa_switch
136 /* Common bridge function */
137 void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state);
138 +int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port,
139 + struct switchdev_brport_flags flags,
140 + struct netlink_ext_ack *extack);
141 +int qca8k_port_bridge_flags(struct dsa_switch *ds, int port,
142 + struct switchdev_brport_flags flags,
143 + struct netlink_ext_ack *extack);
144 int qca8k_port_bridge_join(struct dsa_switch *ds, int port,
145 struct dsa_bridge bridge,
146 bool *tx_fwd_offload,