c1336d4a92164dd408c91212063a55ed70622fff
[openwrt/staging/blogic.git] /
1 From 742d37a84d3f7bb60d9b2d9ada9ad4e599f65ebf Mon Sep 17 00:00:00 2001
2 From: Christian Marangi <ansuelsmth@gmail.com>
3 Date: Wed, 27 Jul 2022 13:35:20 +0200
4 Subject: [PATCH 11/14] net: dsa: qca8k: move port mirror functions to common
5 code
6
7 The same port mirror functions are used by drivers based on qca8k family
8 switch. Move them to common code to make them accessible also by other
9 drivers.
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 | 91 +++++++++++++++++++++++++++++
17 drivers/net/dsa/qca/qca8k.h | 7 +++
18 3 files changed, 98 insertions(+), 93 deletions(-)
19
20 --- a/drivers/net/dsa/qca/qca8k-8xxx.c
21 +++ b/drivers/net/dsa/qca/qca8k-8xxx.c
22 @@ -1838,99 +1838,6 @@ exit:
23 }
24
25 static int
26 -qca8k_port_mirror_add(struct dsa_switch *ds, int port,
27 - struct dsa_mall_mirror_tc_entry *mirror,
28 - bool ingress)
29 -{
30 - struct qca8k_priv *priv = ds->priv;
31 - int monitor_port, ret;
32 - u32 reg, val;
33 -
34 - /* Check for existent entry */
35 - if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port))
36 - return -EEXIST;
37 -
38 - ret = regmap_read(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0, &val);
39 - if (ret)
40 - return ret;
41 -
42 - /* QCA83xx can have only one port set to mirror mode.
43 - * Check that the correct port is requested and return error otherwise.
44 - * When no mirror port is set, the values is set to 0xF
45 - */
46 - monitor_port = FIELD_GET(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
47 - if (monitor_port != 0xF && monitor_port != mirror->to_local_port)
48 - return -EEXIST;
49 -
50 - /* Set the monitor port */
51 - val = FIELD_PREP(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM,
52 - mirror->to_local_port);
53 - ret = regmap_update_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
54 - QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
55 - if (ret)
56 - return ret;
57 -
58 - if (ingress) {
59 - reg = QCA8K_PORT_LOOKUP_CTRL(port);
60 - val = QCA8K_PORT_LOOKUP_ING_MIRROR_EN;
61 - } else {
62 - reg = QCA8K_REG_PORT_HOL_CTRL1(port);
63 - val = QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN;
64 - }
65 -
66 - ret = regmap_update_bits(priv->regmap, reg, val, val);
67 - if (ret)
68 - return ret;
69 -
70 - /* Track mirror port for tx and rx to decide when the
71 - * mirror port has to be disabled.
72 - */
73 - if (ingress)
74 - priv->mirror_rx |= BIT(port);
75 - else
76 - priv->mirror_tx |= BIT(port);
77 -
78 - return 0;
79 -}
80 -
81 -static void
82 -qca8k_port_mirror_del(struct dsa_switch *ds, int port,
83 - struct dsa_mall_mirror_tc_entry *mirror)
84 -{
85 - struct qca8k_priv *priv = ds->priv;
86 - u32 reg, val;
87 - int ret;
88 -
89 - if (mirror->ingress) {
90 - reg = QCA8K_PORT_LOOKUP_CTRL(port);
91 - val = QCA8K_PORT_LOOKUP_ING_MIRROR_EN;
92 - } else {
93 - reg = QCA8K_REG_PORT_HOL_CTRL1(port);
94 - val = QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN;
95 - }
96 -
97 - ret = regmap_clear_bits(priv->regmap, reg, val);
98 - if (ret)
99 - goto err;
100 -
101 - if (mirror->ingress)
102 - priv->mirror_rx &= ~BIT(port);
103 - else
104 - priv->mirror_tx &= ~BIT(port);
105 -
106 - /* No port set to send packet to mirror port. Disable mirror port */
107 - if (!priv->mirror_rx && !priv->mirror_tx) {
108 - val = FIELD_PREP(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, 0xF);
109 - ret = regmap_update_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
110 - QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
111 - if (ret)
112 - goto err;
113 - }
114 -err:
115 - dev_err(priv->dev, "Failed to del mirror port from %d", port);
116 -}
117 -
118 -static int
119 qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
120 struct netlink_ext_ack *extack)
121 {
122 --- a/drivers/net/dsa/qca/qca8k-common.c
123 +++ b/drivers/net/dsa/qca/qca8k-common.c
124 @@ -741,3 +741,94 @@ int qca8k_port_mdb_del(struct dsa_switch
125
126 return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid);
127 }
128 +
129 +int qca8k_port_mirror_add(struct dsa_switch *ds, int port,
130 + struct dsa_mall_mirror_tc_entry *mirror,
131 + bool ingress)
132 +{
133 + struct qca8k_priv *priv = ds->priv;
134 + int monitor_port, ret;
135 + u32 reg, val;
136 +
137 + /* Check for existent entry */
138 + if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port))
139 + return -EEXIST;
140 +
141 + ret = regmap_read(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0, &val);
142 + if (ret)
143 + return ret;
144 +
145 + /* QCA83xx can have only one port set to mirror mode.
146 + * Check that the correct port is requested and return error otherwise.
147 + * When no mirror port is set, the values is set to 0xF
148 + */
149 + monitor_port = FIELD_GET(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
150 + if (monitor_port != 0xF && monitor_port != mirror->to_local_port)
151 + return -EEXIST;
152 +
153 + /* Set the monitor port */
154 + val = FIELD_PREP(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM,
155 + mirror->to_local_port);
156 + ret = regmap_update_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
157 + QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
158 + if (ret)
159 + return ret;
160 +
161 + if (ingress) {
162 + reg = QCA8K_PORT_LOOKUP_CTRL(port);
163 + val = QCA8K_PORT_LOOKUP_ING_MIRROR_EN;
164 + } else {
165 + reg = QCA8K_REG_PORT_HOL_CTRL1(port);
166 + val = QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN;
167 + }
168 +
169 + ret = regmap_update_bits(priv->regmap, reg, val, val);
170 + if (ret)
171 + return ret;
172 +
173 + /* Track mirror port for tx and rx to decide when the
174 + * mirror port has to be disabled.
175 + */
176 + if (ingress)
177 + priv->mirror_rx |= BIT(port);
178 + else
179 + priv->mirror_tx |= BIT(port);
180 +
181 + return 0;
182 +}
183 +
184 +void qca8k_port_mirror_del(struct dsa_switch *ds, int port,
185 + struct dsa_mall_mirror_tc_entry *mirror)
186 +{
187 + struct qca8k_priv *priv = ds->priv;
188 + u32 reg, val;
189 + int ret;
190 +
191 + if (mirror->ingress) {
192 + reg = QCA8K_PORT_LOOKUP_CTRL(port);
193 + val = QCA8K_PORT_LOOKUP_ING_MIRROR_EN;
194 + } else {
195 + reg = QCA8K_REG_PORT_HOL_CTRL1(port);
196 + val = QCA8K_PORT_HOL_CTRL1_EG_MIRROR_EN;
197 + }
198 +
199 + ret = regmap_clear_bits(priv->regmap, reg, val);
200 + if (ret)
201 + goto err;
202 +
203 + if (mirror->ingress)
204 + priv->mirror_rx &= ~BIT(port);
205 + else
206 + priv->mirror_tx &= ~BIT(port);
207 +
208 + /* No port set to send packet to mirror port. Disable mirror port */
209 + if (!priv->mirror_rx && !priv->mirror_tx) {
210 + val = FIELD_PREP(QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, 0xF);
211 + ret = regmap_update_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0,
212 + QCA8K_GLOBAL_FW_CTRL0_MIRROR_PORT_NUM, val);
213 + if (ret)
214 + goto err;
215 + }
216 +err:
217 + dev_err(priv->dev, "Failed to del mirror port from %d", port);
218 +}
219 --- a/drivers/net/dsa/qca/qca8k.h
220 +++ b/drivers/net/dsa/qca/qca8k.h
221 @@ -480,4 +480,11 @@ int qca8k_port_mdb_add(struct dsa_switch
222 int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
223 const struct switchdev_obj_port_mdb *mdb);
224
225 +/* Common port mirror function */
226 +int qca8k_port_mirror_add(struct dsa_switch *ds, int port,
227 + struct dsa_mall_mirror_tc_entry *mirror,
228 + bool ingress);
229 +void qca8k_port_mirror_del(struct dsa_switch *ds, int port,
230 + struct dsa_mall_mirror_tc_entry *mirror);
231 +
232 #endif /* __QCA8K_H */