]> git.ipfire.org Git - thirdparty/openwrt.git/blob
fdb7e7b8b6d480b28ee73ad19a76713691bdca6b
[thirdparty/openwrt.git] /
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
8
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.
12
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().
16
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.
21
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>
25 ---
26 drivers/net/dsa/qca/qca8k-common.c | 101 ++++++++++++++---------------
27 1 file changed, 50 insertions(+), 51 deletions(-)
28
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);
33 }
34
35 +static int qca8k_update_port_member(struct qca8k_priv *priv, int port,
36 + const struct net_device *bridge_dev,
37 + bool join)
38 +{
39 + struct dsa_port *dp = dsa_to_port(priv->ds, port), *other_dp;
40 + u32 port_mask = BIT(dp->cpu_dp->index);
41 + int i, ret;
42 +
43 + for (i = 0; i < QCA8K_NUM_PORTS; i++) {
44 + if (i == port)
45 + continue;
46 + if (dsa_is_cpu_port(priv->ds, i))
47 + continue;
48 +
49 + other_dp = dsa_to_port(priv->ds, i);
50 + if (!dsa_port_offloads_bridge_dev(other_dp, bridge_dev))
51 + continue;
52 +
53 + /* Add/remove this port to/from the portvlan mask of the other
54 + * ports in the bridge
55 + */
56 + if (join) {
57 + port_mask |= BIT(i);
58 + ret = regmap_set_bits(priv->regmap,
59 + QCA8K_PORT_LOOKUP_CTRL(i),
60 + BIT(port));
61 + } else {
62 + ret = regmap_clear_bits(priv->regmap,
63 + QCA8K_PORT_LOOKUP_CTRL(i),
64 + BIT(port));
65 + }
66 +
67 + if (ret)
68 + return ret;
69 + }
70 +
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);
74 +
75 + return ret;
76 +}
77 +
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)
83 {
84 struct qca8k_priv *priv = ds->priv;
85 - int port_mask, cpu_port;
86 - int i, ret;
87 -
88 - cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
89 - port_mask = BIT(cpu_port);
90
91 - for (i = 0; i < QCA8K_NUM_PORTS; i++) {
92 - if (i == port)
93 - continue;
94 - if (dsa_is_cpu_port(ds, i))
95 - continue;
96 - if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
97 - continue;
98 - /* Add this port to the portvlan mask of the other ports
99 - * in the bridge
100 - */
101 - ret = regmap_set_bits(priv->regmap,
102 - QCA8K_PORT_LOOKUP_CTRL(i),
103 - BIT(port));
104 - if (ret)
105 - return ret;
106 - port_mask |= BIT(i);
107 - }
108 -
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);
112 -
113 - return ret;
114 + return qca8k_update_port_member(priv, port, bridge.dev, true);
115 }
116
117 void qca8k_port_bridge_leave(struct dsa_switch *ds, int port,
118 struct dsa_bridge bridge)
119 {
120 struct qca8k_priv *priv = ds->priv;
121 - int cpu_port, i;
122 -
123 - cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
124 -
125 - for (i = 0; i < QCA8K_NUM_PORTS; i++) {
126 - if (i == port)
127 - continue;
128 - if (dsa_is_cpu_port(ds, i))
129 - continue;
130 - if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
131 - continue;
132 - /* Remove this port to the portvlan mask of the other ports
133 - * in the bridge
134 - */
135 - regmap_clear_bits(priv->regmap,
136 - QCA8K_PORT_LOOKUP_CTRL(i),
137 - BIT(port));
138 - }
139 + int err;
140
141 - /* Set the cpu port to be the only one in the portvlan mask of
142 - * this port
143 - */
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);
147 + if (err)
148 + dev_err(priv->dev,
149 + "Failed to update switch config for bridge leave: %d\n",
150 + err);
151 }
152
153 void qca8k_port_fast_age(struct dsa_switch *ds, int port)