This source file includes following definitions.
- rtl8366_mc_is_used
- rtl8366_set_vlan
- rtl8366_get_pvid
- rtl8366_set_pvid
- rtl8366_enable_vlan4k
- rtl8366_enable_vlan
- rtl8366_reset_vlan
- rtl8366_init_vlan
- rtl8366_vlan_filtering
- rtl8366_vlan_prepare
- rtl8366_vlan_add
- rtl8366_vlan_del
- rtl8366_get_strings
- rtl8366_get_sset_count
- rtl8366_get_ethtool_stats
1
2
3
4
5
6
7
8
9
10
11 #include <linux/if_bridge.h>
12 #include <net/dsa.h>
13
14 #include "realtek-smi-core.h"
15
16 int rtl8366_mc_is_used(struct realtek_smi *smi, int mc_index, int *used)
17 {
18 int ret;
19 int i;
20
21 *used = 0;
22 for (i = 0; i < smi->num_ports; i++) {
23 int index = 0;
24
25 ret = smi->ops->get_mc_index(smi, i, &index);
26 if (ret)
27 return ret;
28
29 if (mc_index == index) {
30 *used = 1;
31 break;
32 }
33 }
34
35 return 0;
36 }
37 EXPORT_SYMBOL_GPL(rtl8366_mc_is_used);
38
39 int rtl8366_set_vlan(struct realtek_smi *smi, int vid, u32 member,
40 u32 untag, u32 fid)
41 {
42 struct rtl8366_vlan_4k vlan4k;
43 int ret;
44 int i;
45
46
47 ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
48 if (ret)
49 return ret;
50
51 vlan4k.member = member;
52 vlan4k.untag = untag;
53 vlan4k.fid = fid;
54 ret = smi->ops->set_vlan_4k(smi, &vlan4k);
55 if (ret)
56 return ret;
57
58
59 for (i = 0; i < smi->num_vlan_mc; i++) {
60 struct rtl8366_vlan_mc vlanmc;
61
62 ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
63 if (ret)
64 return ret;
65
66 if (vid == vlanmc.vid) {
67
68 vlanmc.member = member;
69 vlanmc.untag = untag;
70 vlanmc.fid = fid;
71
72 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
73 break;
74 }
75 }
76
77 return ret;
78 }
79 EXPORT_SYMBOL_GPL(rtl8366_set_vlan);
80
81 int rtl8366_get_pvid(struct realtek_smi *smi, int port, int *val)
82 {
83 struct rtl8366_vlan_mc vlanmc;
84 int ret;
85 int index;
86
87 ret = smi->ops->get_mc_index(smi, port, &index);
88 if (ret)
89 return ret;
90
91 ret = smi->ops->get_vlan_mc(smi, index, &vlanmc);
92 if (ret)
93 return ret;
94
95 *val = vlanmc.vid;
96 return 0;
97 }
98 EXPORT_SYMBOL_GPL(rtl8366_get_pvid);
99
100 int rtl8366_set_pvid(struct realtek_smi *smi, unsigned int port,
101 unsigned int vid)
102 {
103 struct rtl8366_vlan_mc vlanmc;
104 struct rtl8366_vlan_4k vlan4k;
105 int ret;
106 int i;
107
108
109 for (i = 0; i < smi->num_vlan_mc; i++) {
110 ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
111 if (ret)
112 return ret;
113
114 if (vid == vlanmc.vid) {
115 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
116 if (ret)
117 return ret;
118
119 ret = smi->ops->set_mc_index(smi, port, i);
120 return ret;
121 }
122 }
123
124
125 for (i = 0; i < smi->num_vlan_mc; i++) {
126 ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
127 if (ret)
128 return ret;
129
130 if (vlanmc.vid == 0 && vlanmc.member == 0) {
131
132 ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
133 if (ret)
134 return ret;
135
136 vlanmc.vid = vid;
137 vlanmc.member = vlan4k.member;
138 vlanmc.untag = vlan4k.untag;
139 vlanmc.fid = vlan4k.fid;
140 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
141 if (ret)
142 return ret;
143
144 ret = smi->ops->set_mc_index(smi, port, i);
145 return ret;
146 }
147 }
148
149
150 for (i = 0; i < smi->num_vlan_mc; i++) {
151 int used;
152
153 ret = rtl8366_mc_is_used(smi, i, &used);
154 if (ret)
155 return ret;
156
157 if (!used) {
158
159 ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
160 if (ret)
161 return ret;
162
163 vlanmc.vid = vid;
164 vlanmc.member = vlan4k.member;
165 vlanmc.untag = vlan4k.untag;
166 vlanmc.fid = vlan4k.fid;
167 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
168 if (ret)
169 return ret;
170
171 ret = smi->ops->set_mc_index(smi, port, i);
172 return ret;
173 }
174 }
175
176 dev_err(smi->dev,
177 "all VLAN member configurations are in use\n");
178
179 return -ENOSPC;
180 }
181 EXPORT_SYMBOL_GPL(rtl8366_set_pvid);
182
183 int rtl8366_enable_vlan4k(struct realtek_smi *smi, bool enable)
184 {
185 int ret;
186
187
188
189
190
191 if (enable) {
192
193 ret = smi->ops->enable_vlan(smi, true);
194 if (ret)
195 return ret;
196
197 smi->vlan_enabled = true;
198 }
199
200 ret = smi->ops->enable_vlan4k(smi, enable);
201 if (ret)
202 return ret;
203
204 smi->vlan4k_enabled = enable;
205 return 0;
206 }
207 EXPORT_SYMBOL_GPL(rtl8366_enable_vlan4k);
208
209 int rtl8366_enable_vlan(struct realtek_smi *smi, bool enable)
210 {
211 int ret;
212
213 ret = smi->ops->enable_vlan(smi, enable);
214 if (ret)
215 return ret;
216
217 smi->vlan_enabled = enable;
218
219
220
221
222 if (!enable) {
223 smi->vlan4k_enabled = false;
224 ret = smi->ops->enable_vlan4k(smi, false);
225 }
226
227 return ret;
228 }
229 EXPORT_SYMBOL_GPL(rtl8366_enable_vlan);
230
231 int rtl8366_reset_vlan(struct realtek_smi *smi)
232 {
233 struct rtl8366_vlan_mc vlanmc;
234 int ret;
235 int i;
236
237 rtl8366_enable_vlan(smi, false);
238 rtl8366_enable_vlan4k(smi, false);
239
240
241 vlanmc.vid = 0;
242 vlanmc.priority = 0;
243 vlanmc.member = 0;
244 vlanmc.untag = 0;
245 vlanmc.fid = 0;
246 for (i = 0; i < smi->num_vlan_mc; i++) {
247 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
248 if (ret)
249 return ret;
250 }
251
252 return 0;
253 }
254 EXPORT_SYMBOL_GPL(rtl8366_reset_vlan);
255
256 int rtl8366_init_vlan(struct realtek_smi *smi)
257 {
258 int port;
259 int ret;
260
261 ret = rtl8366_reset_vlan(smi);
262 if (ret)
263 return ret;
264
265
266
267
268 for (port = 0; port < smi->num_ports; port++) {
269 u32 mask;
270
271 if (port == smi->cpu_port)
272
273
274
275 mask = GENMASK(smi->num_ports - 1, 0);
276 else
277
278
279
280 mask = BIT(port) | BIT(smi->cpu_port);
281
282
283
284
285
286
287 dev_info(smi->dev, "VLAN%d port mask for port %d, %08x\n",
288 (port + 1), port, mask);
289 ret = rtl8366_set_vlan(smi, (port + 1), mask, mask, 0);
290 if (ret)
291 return ret;
292
293 dev_info(smi->dev, "VLAN%d port %d, PVID set to %d\n",
294 (port + 1), port, (port + 1));
295 ret = rtl8366_set_pvid(smi, port, (port + 1));
296 if (ret)
297 return ret;
298 }
299
300 return rtl8366_enable_vlan(smi, true);
301 }
302 EXPORT_SYMBOL_GPL(rtl8366_init_vlan);
303
304 int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
305 {
306 struct realtek_smi *smi = ds->priv;
307 struct rtl8366_vlan_4k vlan4k;
308 int ret;
309
310
311 if (!smi->ops->is_vlan_valid(smi, port + 1))
312 return -EINVAL;
313
314 dev_info(smi->dev, "%s filtering on port %d\n",
315 vlan_filtering ? "enable" : "disable",
316 port);
317
318
319
320
321
322 ret = smi->ops->get_vlan_4k(smi, port + 1, &vlan4k);
323 if (ret)
324 return ret;
325
326
327 ret = rtl8366_set_vlan(smi, port + 1,
328 vlan4k.member,
329 vlan4k.untag,
330 1);
331 if (ret)
332 return ret;
333
334 return 0;
335 }
336 EXPORT_SYMBOL_GPL(rtl8366_vlan_filtering);
337
338 int rtl8366_vlan_prepare(struct dsa_switch *ds, int port,
339 const struct switchdev_obj_port_vlan *vlan)
340 {
341 struct realtek_smi *smi = ds->priv;
342 u16 vid;
343 int ret;
344
345 for (vid = vlan->vid_begin; vid < vlan->vid_end; vid++)
346 if (!smi->ops->is_vlan_valid(smi, vid))
347 return -EINVAL;
348
349 dev_info(smi->dev, "prepare VLANs %04x..%04x\n",
350 vlan->vid_begin, vlan->vid_end);
351
352
353
354
355
356 ret = rtl8366_enable_vlan4k(smi, true);
357 if (ret)
358 return ret;
359
360 return 0;
361 }
362 EXPORT_SYMBOL_GPL(rtl8366_vlan_prepare);
363
364 void rtl8366_vlan_add(struct dsa_switch *ds, int port,
365 const struct switchdev_obj_port_vlan *vlan)
366 {
367 bool untagged = !!(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
368 bool pvid = !!(vlan->flags & BRIDGE_VLAN_INFO_PVID);
369 struct realtek_smi *smi = ds->priv;
370 u32 member = 0;
371 u32 untag = 0;
372 u16 vid;
373 int ret;
374
375 for (vid = vlan->vid_begin; vid < vlan->vid_end; vid++)
376 if (!smi->ops->is_vlan_valid(smi, vid))
377 return;
378
379 dev_info(smi->dev, "add VLAN on port %d, %s, %s\n",
380 port,
381 untagged ? "untagged" : "tagged",
382 pvid ? " PVID" : "no PVID");
383
384 if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
385 dev_err(smi->dev, "port is DSA or CPU port\n");
386
387 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
388 int pvid_val = 0;
389
390 dev_info(smi->dev, "add VLAN %04x\n", vid);
391 member |= BIT(port);
392
393 if (untagged)
394 untag |= BIT(port);
395
396
397
398
399 ret = rtl8366_get_pvid(smi, port, &pvid_val);
400 if (ret < 0) {
401 dev_err(smi->dev, "could not lookup PVID for port %d\n",
402 port);
403 return;
404 }
405 if (pvid_val == 0) {
406 ret = rtl8366_set_pvid(smi, port, vid);
407 if (ret < 0)
408 return;
409 }
410 }
411
412 ret = rtl8366_set_vlan(smi, port, member, untag, 0);
413 if (ret)
414 dev_err(smi->dev,
415 "failed to set up VLAN %04x",
416 vid);
417 }
418 EXPORT_SYMBOL_GPL(rtl8366_vlan_add);
419
420 int rtl8366_vlan_del(struct dsa_switch *ds, int port,
421 const struct switchdev_obj_port_vlan *vlan)
422 {
423 struct realtek_smi *smi = ds->priv;
424 u16 vid;
425 int ret;
426
427 dev_info(smi->dev, "del VLAN on port %d\n", port);
428
429 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
430 int i;
431
432 dev_info(smi->dev, "del VLAN %04x\n", vid);
433
434 for (i = 0; i < smi->num_vlan_mc; i++) {
435 struct rtl8366_vlan_mc vlanmc;
436
437 ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
438 if (ret)
439 return ret;
440
441 if (vid == vlanmc.vid) {
442
443 vlanmc.vid = 0;
444 vlanmc.priority = 0;
445 vlanmc.member = 0;
446 vlanmc.untag = 0;
447 vlanmc.fid = 0;
448
449 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
450 if (ret) {
451 dev_err(smi->dev,
452 "failed to remove VLAN %04x\n",
453 vid);
454 return ret;
455 }
456 break;
457 }
458 }
459 }
460
461 return 0;
462 }
463 EXPORT_SYMBOL_GPL(rtl8366_vlan_del);
464
465 void rtl8366_get_strings(struct dsa_switch *ds, int port, u32 stringset,
466 uint8_t *data)
467 {
468 struct realtek_smi *smi = ds->priv;
469 struct rtl8366_mib_counter *mib;
470 int i;
471
472 if (port >= smi->num_ports)
473 return;
474
475 for (i = 0; i < smi->num_mib_counters; i++) {
476 mib = &smi->mib_counters[i];
477 strncpy(data + i * ETH_GSTRING_LEN,
478 mib->name, ETH_GSTRING_LEN);
479 }
480 }
481 EXPORT_SYMBOL_GPL(rtl8366_get_strings);
482
483 int rtl8366_get_sset_count(struct dsa_switch *ds, int port, int sset)
484 {
485 struct realtek_smi *smi = ds->priv;
486
487
488 if (sset != ETH_SS_STATS)
489 return 0;
490 if (port >= smi->num_ports)
491 return -EINVAL;
492
493 return smi->num_mib_counters;
494 }
495 EXPORT_SYMBOL_GPL(rtl8366_get_sset_count);
496
497 void rtl8366_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
498 {
499 struct realtek_smi *smi = ds->priv;
500 int i;
501 int ret;
502
503 if (port >= smi->num_ports)
504 return;
505
506 for (i = 0; i < smi->num_mib_counters; i++) {
507 struct rtl8366_mib_counter *mib;
508 u64 mibvalue = 0;
509
510 mib = &smi->mib_counters[i];
511 ret = smi->ops->get_mib_counter(smi, port, mib, &mibvalue);
512 if (ret) {
513 dev_err(smi->dev, "error reading MIB counter %s\n",
514 mib->name);
515 }
516 data[i] = mibvalue;
517 }
518 }
519 EXPORT_SYMBOL_GPL(rtl8366_get_ethtool_stats);