1 From 412e1775f413c944b8c51bdadb675be957d83dc8 Mon Sep 17 00:00:00 2001
2 Message-ID: <412e1775f413c944b8c51bdadb675be957d83dc8.1728674648.git.mschiffer@universe-factory.net>
3 In-Reply-To: <e85d3e6fea05c8ae21a40809a3c6b7adc97411c7.1728674648.git.mschiffer@universe-factory.net>
4 References: <e85d3e6fea05c8ae21a40809a3c6b7adc97411c7.1728674648.git.mschiffer@universe-factory.net>
5 From: Matthias Schiffer <mschiffer@universe-factory.net>
6 Date: Thu, 20 Jun 2024 19:25:49 +0200
7 Subject: [PATCH] net: dsa: qca8k: factor out bridge join/leave logic
9 Most of the logic in qca8k_port_bridge_join() and qca8k_port_bridge_leave()
10 is the same. Refactor to reduce duplication and prepare for reusing the
11 code for implementing bridge port isolation.
13 dsa_port_offloads_bridge_dev() is used instead of
14 dsa_port_offloads_bridge(), passing the bridge in as a struct netdevice *,
15 as we won't have a struct dsa_bridge in qca8k_port_bridge_flags().
17 The error handling is changed slightly in the bridge leave case,
18 returning early and emitting an error message when a regmap access fails.
19 This shouldn't matter in practice, as there isn't much we can do if
20 communication with the switch breaks down in the middle of reconfiguration.
22 Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
23 Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
24 Signed-off-by: David S. Miller <davem@davemloft.net>
26 drivers/net/dsa/qca/qca8k-common.c | 101 ++++++++++++++---------------
27 1 file changed, 50 insertions(+), 51 deletions(-)
29 --- a/drivers/net/dsa/qca/qca8k-common.c
30 +++ b/drivers/net/dsa/qca/qca8k-common.c
31 @@ -615,6 +615,49 @@ void qca8k_port_stp_state_set(struct dsa
32 qca8k_port_configure_learning(ds, port, learning);
35 +static int qca8k_update_port_member(struct qca8k_priv *priv, int port,
36 + const struct net_device *bridge_dev,
39 + struct dsa_port *dp = dsa_to_port(priv->ds, port), *other_dp;
40 + u32 port_mask = BIT(dp->cpu_dp->index);
43 + for (i = 0; i < QCA8K_NUM_PORTS; i++) {
46 + if (dsa_is_cpu_port(priv->ds, i))
49 + other_dp = dsa_to_port(priv->ds, i);
50 + if (!dsa_port_offloads_bridge_dev(other_dp, bridge_dev))
53 + /* Add/remove this port to/from the portvlan mask of the other
54 + * ports in the bridge
57 + port_mask |= BIT(i);
58 + ret = regmap_set_bits(priv->regmap,
59 + QCA8K_PORT_LOOKUP_CTRL(i),
62 + ret = regmap_clear_bits(priv->regmap,
63 + QCA8K_PORT_LOOKUP_CTRL(i),
71 + /* Add/remove all other ports to/from this port's portvlan mask */
72 + ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
73 + QCA8K_PORT_LOOKUP_MEMBER, port_mask);
78 int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port,
79 struct switchdev_brport_flags flags,
80 struct netlink_ext_ack *extack)
81 @@ -647,65 +690,21 @@ int qca8k_port_bridge_join(struct dsa_sw
82 struct netlink_ext_ack *extack)
84 struct qca8k_priv *priv = ds->priv;
85 - int port_mask, cpu_port;
88 - cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
89 - port_mask = BIT(cpu_port);
91 - for (i = 0; i < QCA8K_NUM_PORTS; i++) {
94 - if (dsa_is_cpu_port(ds, i))
96 - if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
98 - /* Add this port to the portvlan mask of the other ports
101 - ret = regmap_set_bits(priv->regmap,
102 - QCA8K_PORT_LOOKUP_CTRL(i),
106 - port_mask |= BIT(i);
109 - /* Add all other ports to this ports portvlan mask */
110 - ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
111 - QCA8K_PORT_LOOKUP_MEMBER, port_mask);
114 + return qca8k_update_port_member(priv, port, bridge.dev, true);
117 void qca8k_port_bridge_leave(struct dsa_switch *ds, int port,
118 struct dsa_bridge bridge)
120 struct qca8k_priv *priv = ds->priv;
123 - cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
125 - for (i = 0; i < QCA8K_NUM_PORTS; i++) {
128 - if (dsa_is_cpu_port(ds, i))
130 - if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
132 - /* Remove this port to the portvlan mask of the other ports
135 - regmap_clear_bits(priv->regmap,
136 - QCA8K_PORT_LOOKUP_CTRL(i),
141 - /* Set the cpu port to be the only one in the portvlan mask of
144 - qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
145 - QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port));
146 + err = qca8k_update_port_member(priv, port, bridge.dev, false);
149 + "Failed to update switch config for bridge leave: %d\n",
153 void qca8k_port_fast_age(struct dsa_switch *ds, int port)