kernel: fix mtk_eth_soc throughput regressions on gigabit PHY ports
[openwrt/openwrt.git] / target / linux / generic / backport-5.15 / 771-v6.0-08-net-dsa-qca8k-move-bridge-functions-to-common-code.patch
1 From fd3cae2f3ac190d06e48f43739237e02f9dc51ff Mon Sep 17 00:00:00 2001
2 From: Christian Marangi <ansuelsmth@gmail.com>
3 Date: Wed, 27 Jul 2022 13:35:17 +0200
4 Subject: [PATCH 08/14] net: dsa: qca8k: move bridge functions to common code
5
6 The same bridge functions are used by drivers based on qca8k family
7 switch. Move them to common code to make them accessible also by other
8 drivers.
9 While at it also drop unnecessary qca8k_priv cast for void pointers.
10
11 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
12 Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
13 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
14 ---
15 drivers/net/dsa/qca/qca8k-8xxx.c | 93 ------------------------------
16 drivers/net/dsa/qca/qca8k-common.c | 93 ++++++++++++++++++++++++++++++
17 drivers/net/dsa/qca/qca8k.h | 9 +++
18 3 files changed, 102 insertions(+), 93 deletions(-)
19
20 --- a/drivers/net/dsa/qca/qca8k-8xxx.c
21 +++ b/drivers/net/dsa/qca/qca8k-8xxx.c
22 @@ -2049,97 +2049,6 @@ exit:
23 }
24
25 static void
26 -qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
27 -{
28 - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
29 - u32 stp_state;
30 -
31 - switch (state) {
32 - case BR_STATE_DISABLED:
33 - stp_state = QCA8K_PORT_LOOKUP_STATE_DISABLED;
34 - break;
35 - case BR_STATE_BLOCKING:
36 - stp_state = QCA8K_PORT_LOOKUP_STATE_BLOCKING;
37 - break;
38 - case BR_STATE_LISTENING:
39 - stp_state = QCA8K_PORT_LOOKUP_STATE_LISTENING;
40 - break;
41 - case BR_STATE_LEARNING:
42 - stp_state = QCA8K_PORT_LOOKUP_STATE_LEARNING;
43 - break;
44 - case BR_STATE_FORWARDING:
45 - default:
46 - stp_state = QCA8K_PORT_LOOKUP_STATE_FORWARD;
47 - break;
48 - }
49 -
50 - qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
51 - QCA8K_PORT_LOOKUP_STATE_MASK, stp_state);
52 -}
53 -
54 -static int
55 -qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br)
56 -{
57 - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
58 - int port_mask, cpu_port;
59 - int i, ret;
60 -
61 - cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
62 - port_mask = BIT(cpu_port);
63 -
64 - for (i = 0; i < QCA8K_NUM_PORTS; i++) {
65 - if (dsa_is_cpu_port(ds, i))
66 - continue;
67 - if (dsa_to_port(ds, i)->bridge_dev != br)
68 - continue;
69 - /* Add this port to the portvlan mask of the other ports
70 - * in the bridge
71 - */
72 - ret = regmap_set_bits(priv->regmap,
73 - QCA8K_PORT_LOOKUP_CTRL(i),
74 - BIT(port));
75 - if (ret)
76 - return ret;
77 - if (i != port)
78 - port_mask |= BIT(i);
79 - }
80 -
81 - /* Add all other ports to this ports portvlan mask */
82 - ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
83 - QCA8K_PORT_LOOKUP_MEMBER, port_mask);
84 -
85 - return ret;
86 -}
87 -
88 -static void
89 -qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br)
90 -{
91 - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
92 - int cpu_port, i;
93 -
94 - cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
95 -
96 - for (i = 0; i < QCA8K_NUM_PORTS; i++) {
97 - if (dsa_is_cpu_port(ds, i))
98 - continue;
99 - if (dsa_to_port(ds, i)->bridge_dev != br)
100 - continue;
101 - /* Remove this port to the portvlan mask of the other ports
102 - * in the bridge
103 - */
104 - regmap_clear_bits(priv->regmap,
105 - QCA8K_PORT_LOOKUP_CTRL(i),
106 - BIT(port));
107 - }
108 -
109 - /* Set the cpu port to be the only one in the portvlan mask of
110 - * this port
111 - */
112 - qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
113 - QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port));
114 -}
115 -
116 -static void
117 qca8k_port_fast_age(struct dsa_switch *ds, int port)
118 {
119 struct qca8k_priv *priv = ds->priv;
120 --- a/drivers/net/dsa/qca/qca8k-common.c
121 +++ b/drivers/net/dsa/qca/qca8k-common.c
122 @@ -9,6 +9,7 @@
123 #include <linux/netdevice.h>
124 #include <linux/bitfield.h>
125 #include <net/dsa.h>
126 +#include <linux/if_bridge.h>
127
128 #include "qca8k.h"
129
130 @@ -276,3 +277,93 @@ int qca8k_get_mac_eee(struct dsa_switch
131 /* Nothing to do on the port's MAC */
132 return 0;
133 }
134 +
135 +void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
136 +{
137 + struct qca8k_priv *priv = ds->priv;
138 + u32 stp_state;
139 +
140 + switch (state) {
141 + case BR_STATE_DISABLED:
142 + stp_state = QCA8K_PORT_LOOKUP_STATE_DISABLED;
143 + break;
144 + case BR_STATE_BLOCKING:
145 + stp_state = QCA8K_PORT_LOOKUP_STATE_BLOCKING;
146 + break;
147 + case BR_STATE_LISTENING:
148 + stp_state = QCA8K_PORT_LOOKUP_STATE_LISTENING;
149 + break;
150 + case BR_STATE_LEARNING:
151 + stp_state = QCA8K_PORT_LOOKUP_STATE_LEARNING;
152 + break;
153 + case BR_STATE_FORWARDING:
154 + default:
155 + stp_state = QCA8K_PORT_LOOKUP_STATE_FORWARD;
156 + break;
157 + }
158 +
159 + qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
160 + QCA8K_PORT_LOOKUP_STATE_MASK, stp_state);
161 +}
162 +
163 +int qca8k_port_bridge_join(struct dsa_switch *ds, int port,
164 + struct net_device *br)
165 +{
166 + struct qca8k_priv *priv = ds->priv;
167 + int port_mask, cpu_port;
168 + int i, ret;
169 +
170 + cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
171 + port_mask = BIT(cpu_port);
172 +
173 + for (i = 0; i < QCA8K_NUM_PORTS; i++) {
174 + if (dsa_is_cpu_port(ds, i))
175 + continue;
176 + if (dsa_to_port(ds, i)->bridge_dev != br)
177 + continue;
178 + /* Add this port to the portvlan mask of the other ports
179 + * in the bridge
180 + */
181 + ret = regmap_set_bits(priv->regmap,
182 + QCA8K_PORT_LOOKUP_CTRL(i),
183 + BIT(port));
184 + if (ret)
185 + return ret;
186 + if (i != port)
187 + port_mask |= BIT(i);
188 + }
189 +
190 + /* Add all other ports to this ports portvlan mask */
191 + ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
192 + QCA8K_PORT_LOOKUP_MEMBER, port_mask);
193 +
194 + return ret;
195 +}
196 +
197 +void qca8k_port_bridge_leave(struct dsa_switch *ds, int port,
198 + struct net_device *br)
199 +{
200 + struct qca8k_priv *priv = ds->priv;
201 + int cpu_port, i;
202 +
203 + cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
204 +
205 + for (i = 0; i < QCA8K_NUM_PORTS; i++) {
206 + if (dsa_is_cpu_port(ds, i))
207 + continue;
208 + if (dsa_to_port(ds, i)->bridge_dev != br)
209 + continue;
210 + /* Remove this port to the portvlan mask of the other ports
211 + * in the bridge
212 + */
213 + regmap_clear_bits(priv->regmap,
214 + QCA8K_PORT_LOOKUP_CTRL(i),
215 + BIT(port));
216 + }
217 +
218 + /* Set the cpu port to be the only one in the portvlan mask of
219 + * this port
220 + */
221 + qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
222 + QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port));
223 +}
224 --- a/drivers/net/dsa/qca/qca8k.h
225 +++ b/drivers/net/dsa/qca/qca8k.h
226 @@ -446,4 +446,11 @@ int qca8k_get_sset_count(struct dsa_swit
227 int qca8k_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *eee);
228 int qca8k_get_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e);
229
230 +/* Common bridge function */
231 +void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state);
232 +int qca8k_port_bridge_join(struct dsa_switch *ds, int port,
233 + struct net_device *br);
234 +void qca8k_port_bridge_leave(struct dsa_switch *ds, int port,
235 + struct net_device *br);
236 +
237 #endif /* __QCA8K_H */