Loading...
1// SPDX-License-Identifier: GPL-2.0
2/* Realtek SMI library helpers for the RTL8366x variants
3 * RTL8366RB and RTL8366S
4 *
5 * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
6 * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
7 * Copyright (C) 2010 Antti Seppälä <a.seppala@gmail.com>
8 * Copyright (C) 2010 Roman Yeryomin <roman@advem.lv>
9 * Copyright (C) 2011 Colin Leitner <colin.leitner@googlemail.com>
10 */
11#include <linux/if_bridge.h>
12#include <net/dsa.h>
13
14#include "realtek-smi-core.h"
15
16int 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}
37EXPORT_SYMBOL_GPL(rtl8366_mc_is_used);
38
39int 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 /* Update the 4K table */
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 /* Try to find an existing MC entry for this VID */
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 /* update the MC entry */
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}
79EXPORT_SYMBOL_GPL(rtl8366_set_vlan);
80
81int 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}
98EXPORT_SYMBOL_GPL(rtl8366_get_pvid);
99
100int 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 /* Try to find an existing MC entry for this VID */
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 /* We have no MC entry for this VID, try to find an empty one */
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 /* Update the entry from the 4K table */
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 /* MC table is full, try to find an unused entry and replace it */
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 /* Update the entry from the 4K table */
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}
181EXPORT_SYMBOL_GPL(rtl8366_set_pvid);
182
183int rtl8366_enable_vlan4k(struct realtek_smi *smi, bool enable)
184{
185 int ret;
186
187 /* To enable 4k VLAN, ordinary VLAN must be enabled first,
188 * but if we disable 4k VLAN it is fine to leave ordinary
189 * VLAN enabled.
190 */
191 if (enable) {
192 /* Make sure VLAN is ON */
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}
207EXPORT_SYMBOL_GPL(rtl8366_enable_vlan4k);
208
209int 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 /* If we turn VLAN off, make sure that we turn off
220 * 4k VLAN as well, if that happened to be on.
221 */
222 if (!enable) {
223 smi->vlan4k_enabled = false;
224 ret = smi->ops->enable_vlan4k(smi, false);
225 }
226
227 return ret;
228}
229EXPORT_SYMBOL_GPL(rtl8366_enable_vlan);
230
231int 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 /* Clear the 16 VLAN member configurations */
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}
254EXPORT_SYMBOL_GPL(rtl8366_reset_vlan);
255
256int 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 /* Loop over the available ports, for each port, associate
266 * it with the VLAN (port+1)
267 */
268 for (port = 0; port < smi->num_ports; port++) {
269 u32 mask;
270
271 if (port == smi->cpu_port)
272 /* For the CPU port, make all ports members of this
273 * VLAN.
274 */
275 mask = GENMASK(smi->num_ports - 1, 0);
276 else
277 /* For all other ports, enable itself plus the
278 * CPU port.
279 */
280 mask = BIT(port) | BIT(smi->cpu_port);
281
282 /* For each port, set the port as member of VLAN (port+1)
283 * and untagged, except for the CPU port: the CPU port (5) is
284 * member of VLAN 6 and so are ALL the other ports as well.
285 * Use filter 0 (no filter).
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}
302EXPORT_SYMBOL_GPL(rtl8366_init_vlan);
303
304int 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 /* Use VLAN nr port + 1 since VLAN0 is not valid */
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 /* TODO:
319 * The hardware support filter ID (FID) 0..7, I have no clue how to
320 * support this in the driver when the callback only says on/off.
321 */
322 ret = smi->ops->get_vlan_4k(smi, port + 1, &vlan4k);
323 if (ret)
324 return ret;
325
326 /* Just set the filter to FID 1 for now then */
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}
336EXPORT_SYMBOL_GPL(rtl8366_vlan_filtering);
337
338int 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 /* Enable VLAN in the hardware
353 * FIXME: what's with this 4k business?
354 * Just rtl8366_enable_vlan() seems inconclusive.
355 */
356 ret = rtl8366_enable_vlan4k(smi, true);
357 if (ret)
358 return ret;
359
360 return 0;
361}
362EXPORT_SYMBOL_GPL(rtl8366_vlan_prepare);
363
364void 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 /* To ensure that we have a valid MC entry for this VLAN,
397 * initialize the port VLAN ID here.
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}
418EXPORT_SYMBOL_GPL(rtl8366_vlan_add);
419
420int 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 /* clear VLAN member configurations */
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}
463EXPORT_SYMBOL_GPL(rtl8366_vlan_del);
464
465void 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}
481EXPORT_SYMBOL_GPL(rtl8366_get_strings);
482
483int rtl8366_get_sset_count(struct dsa_switch *ds, int port, int sset)
484{
485 struct realtek_smi *smi = ds->priv;
486
487 /* We only support SS_STATS */
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}
495EXPORT_SYMBOL_GPL(rtl8366_get_sset_count);
496
497void 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}
519EXPORT_SYMBOL_GPL(rtl8366_get_ethtool_stats);
1// SPDX-License-Identifier: GPL-2.0
2/* Realtek SMI library helpers for the RTL8366x variants
3 * RTL8366RB and RTL8366S
4 *
5 * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
6 * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
7 * Copyright (C) 2010 Antti Seppälä <a.seppala@gmail.com>
8 * Copyright (C) 2010 Roman Yeryomin <roman@advem.lv>
9 * Copyright (C) 2011 Colin Leitner <colin.leitner@googlemail.com>
10 */
11#include <linux/if_bridge.h>
12#include <net/dsa.h>
13
14#include "realtek-smi-core.h"
15
16int 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}
37EXPORT_SYMBOL_GPL(rtl8366_mc_is_used);
38
39int 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 dev_dbg(smi->dev,
47 "setting VLAN%d 4k members: 0x%02x, untagged: 0x%02x\n",
48 vid, member, untag);
49
50 /* Update the 4K table */
51 ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
52 if (ret)
53 return ret;
54
55 vlan4k.member |= member;
56 vlan4k.untag |= untag;
57 vlan4k.fid = fid;
58 ret = smi->ops->set_vlan_4k(smi, &vlan4k);
59 if (ret)
60 return ret;
61
62 dev_dbg(smi->dev,
63 "resulting VLAN%d 4k members: 0x%02x, untagged: 0x%02x\n",
64 vid, vlan4k.member, vlan4k.untag);
65
66 /* Try to find an existing MC entry for this VID */
67 for (i = 0; i < smi->num_vlan_mc; i++) {
68 struct rtl8366_vlan_mc vlanmc;
69
70 ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
71 if (ret)
72 return ret;
73
74 if (vid == vlanmc.vid) {
75 /* update the MC entry */
76 vlanmc.member |= member;
77 vlanmc.untag |= untag;
78 vlanmc.fid = fid;
79
80 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
81
82 dev_dbg(smi->dev,
83 "resulting VLAN%d MC members: 0x%02x, untagged: 0x%02x\n",
84 vid, vlanmc.member, vlanmc.untag);
85
86 break;
87 }
88 }
89
90 return ret;
91}
92EXPORT_SYMBOL_GPL(rtl8366_set_vlan);
93
94int rtl8366_get_pvid(struct realtek_smi *smi, int port, int *val)
95{
96 struct rtl8366_vlan_mc vlanmc;
97 int ret;
98 int index;
99
100 ret = smi->ops->get_mc_index(smi, port, &index);
101 if (ret)
102 return ret;
103
104 ret = smi->ops->get_vlan_mc(smi, index, &vlanmc);
105 if (ret)
106 return ret;
107
108 *val = vlanmc.vid;
109 return 0;
110}
111EXPORT_SYMBOL_GPL(rtl8366_get_pvid);
112
113int rtl8366_set_pvid(struct realtek_smi *smi, unsigned int port,
114 unsigned int vid)
115{
116 struct rtl8366_vlan_mc vlanmc;
117 struct rtl8366_vlan_4k vlan4k;
118 int ret;
119 int i;
120
121 /* Try to find an existing MC entry for this VID */
122 for (i = 0; i < smi->num_vlan_mc; i++) {
123 ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
124 if (ret)
125 return ret;
126
127 if (vid == vlanmc.vid) {
128 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
129 if (ret)
130 return ret;
131
132 ret = smi->ops->set_mc_index(smi, port, i);
133 return ret;
134 }
135 }
136
137 /* We have no MC entry for this VID, try to find an empty one */
138 for (i = 0; i < smi->num_vlan_mc; i++) {
139 ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
140 if (ret)
141 return ret;
142
143 if (vlanmc.vid == 0 && vlanmc.member == 0) {
144 /* Update the entry from the 4K table */
145 ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
146 if (ret)
147 return ret;
148
149 vlanmc.vid = vid;
150 vlanmc.member = vlan4k.member;
151 vlanmc.untag = vlan4k.untag;
152 vlanmc.fid = vlan4k.fid;
153 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
154 if (ret)
155 return ret;
156
157 ret = smi->ops->set_mc_index(smi, port, i);
158 return ret;
159 }
160 }
161
162 /* MC table is full, try to find an unused entry and replace it */
163 for (i = 0; i < smi->num_vlan_mc; i++) {
164 int used;
165
166 ret = rtl8366_mc_is_used(smi, i, &used);
167 if (ret)
168 return ret;
169
170 if (!used) {
171 /* Update the entry from the 4K table */
172 ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
173 if (ret)
174 return ret;
175
176 vlanmc.vid = vid;
177 vlanmc.member = vlan4k.member;
178 vlanmc.untag = vlan4k.untag;
179 vlanmc.fid = vlan4k.fid;
180 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
181 if (ret)
182 return ret;
183
184 ret = smi->ops->set_mc_index(smi, port, i);
185 return ret;
186 }
187 }
188
189 dev_err(smi->dev,
190 "all VLAN member configurations are in use\n");
191
192 return -ENOSPC;
193}
194EXPORT_SYMBOL_GPL(rtl8366_set_pvid);
195
196int rtl8366_enable_vlan4k(struct realtek_smi *smi, bool enable)
197{
198 int ret;
199
200 /* To enable 4k VLAN, ordinary VLAN must be enabled first,
201 * but if we disable 4k VLAN it is fine to leave ordinary
202 * VLAN enabled.
203 */
204 if (enable) {
205 /* Make sure VLAN is ON */
206 ret = smi->ops->enable_vlan(smi, true);
207 if (ret)
208 return ret;
209
210 smi->vlan_enabled = true;
211 }
212
213 ret = smi->ops->enable_vlan4k(smi, enable);
214 if (ret)
215 return ret;
216
217 smi->vlan4k_enabled = enable;
218 return 0;
219}
220EXPORT_SYMBOL_GPL(rtl8366_enable_vlan4k);
221
222int rtl8366_enable_vlan(struct realtek_smi *smi, bool enable)
223{
224 int ret;
225
226 ret = smi->ops->enable_vlan(smi, enable);
227 if (ret)
228 return ret;
229
230 smi->vlan_enabled = enable;
231
232 /* If we turn VLAN off, make sure that we turn off
233 * 4k VLAN as well, if that happened to be on.
234 */
235 if (!enable) {
236 smi->vlan4k_enabled = false;
237 ret = smi->ops->enable_vlan4k(smi, false);
238 }
239
240 return ret;
241}
242EXPORT_SYMBOL_GPL(rtl8366_enable_vlan);
243
244int rtl8366_reset_vlan(struct realtek_smi *smi)
245{
246 struct rtl8366_vlan_mc vlanmc;
247 int ret;
248 int i;
249
250 rtl8366_enable_vlan(smi, false);
251 rtl8366_enable_vlan4k(smi, false);
252
253 /* Clear the 16 VLAN member configurations */
254 vlanmc.vid = 0;
255 vlanmc.priority = 0;
256 vlanmc.member = 0;
257 vlanmc.untag = 0;
258 vlanmc.fid = 0;
259 for (i = 0; i < smi->num_vlan_mc; i++) {
260 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
261 if (ret)
262 return ret;
263 }
264
265 return 0;
266}
267EXPORT_SYMBOL_GPL(rtl8366_reset_vlan);
268
269int rtl8366_init_vlan(struct realtek_smi *smi)
270{
271 int port;
272 int ret;
273
274 ret = rtl8366_reset_vlan(smi);
275 if (ret)
276 return ret;
277
278 /* Loop over the available ports, for each port, associate
279 * it with the VLAN (port+1)
280 */
281 for (port = 0; port < smi->num_ports; port++) {
282 u32 mask;
283
284 if (port == smi->cpu_port)
285 /* For the CPU port, make all ports members of this
286 * VLAN.
287 */
288 mask = GENMASK((int)smi->num_ports - 1, 0);
289 else
290 /* For all other ports, enable itself plus the
291 * CPU port.
292 */
293 mask = BIT(port) | BIT(smi->cpu_port);
294
295 /* For each port, set the port as member of VLAN (port+1)
296 * and untagged, except for the CPU port: the CPU port (5) is
297 * member of VLAN 6 and so are ALL the other ports as well.
298 * Use filter 0 (no filter).
299 */
300 dev_info(smi->dev, "VLAN%d port mask for port %d, %08x\n",
301 (port + 1), port, mask);
302 ret = rtl8366_set_vlan(smi, (port + 1), mask, mask, 0);
303 if (ret)
304 return ret;
305
306 dev_info(smi->dev, "VLAN%d port %d, PVID set to %d\n",
307 (port + 1), port, (port + 1));
308 ret = rtl8366_set_pvid(smi, port, (port + 1));
309 if (ret)
310 return ret;
311 }
312
313 return rtl8366_enable_vlan(smi, true);
314}
315EXPORT_SYMBOL_GPL(rtl8366_init_vlan);
316
317int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
318{
319 struct realtek_smi *smi = ds->priv;
320 struct rtl8366_vlan_4k vlan4k;
321 int ret;
322
323 /* Use VLAN nr port + 1 since VLAN0 is not valid */
324 if (!smi->ops->is_vlan_valid(smi, port + 1))
325 return -EINVAL;
326
327 dev_info(smi->dev, "%s filtering on port %d\n",
328 vlan_filtering ? "enable" : "disable",
329 port);
330
331 /* TODO:
332 * The hardware support filter ID (FID) 0..7, I have no clue how to
333 * support this in the driver when the callback only says on/off.
334 */
335 ret = smi->ops->get_vlan_4k(smi, port + 1, &vlan4k);
336 if (ret)
337 return ret;
338
339 /* Just set the filter to FID 1 for now then */
340 ret = rtl8366_set_vlan(smi, port + 1,
341 vlan4k.member,
342 vlan4k.untag,
343 1);
344 if (ret)
345 return ret;
346
347 return 0;
348}
349EXPORT_SYMBOL_GPL(rtl8366_vlan_filtering);
350
351int rtl8366_vlan_prepare(struct dsa_switch *ds, int port,
352 const struct switchdev_obj_port_vlan *vlan)
353{
354 struct realtek_smi *smi = ds->priv;
355 u16 vid;
356 int ret;
357
358 for (vid = vlan->vid_begin; vid < vlan->vid_end; vid++)
359 if (!smi->ops->is_vlan_valid(smi, vid))
360 return -EINVAL;
361
362 dev_info(smi->dev, "prepare VLANs %04x..%04x\n",
363 vlan->vid_begin, vlan->vid_end);
364
365 /* Enable VLAN in the hardware
366 * FIXME: what's with this 4k business?
367 * Just rtl8366_enable_vlan() seems inconclusive.
368 */
369 ret = rtl8366_enable_vlan4k(smi, true);
370 if (ret)
371 return ret;
372
373 return 0;
374}
375EXPORT_SYMBOL_GPL(rtl8366_vlan_prepare);
376
377void rtl8366_vlan_add(struct dsa_switch *ds, int port,
378 const struct switchdev_obj_port_vlan *vlan)
379{
380 bool untagged = !!(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
381 bool pvid = !!(vlan->flags & BRIDGE_VLAN_INFO_PVID);
382 struct realtek_smi *smi = ds->priv;
383 u32 member = 0;
384 u32 untag = 0;
385 u16 vid;
386 int ret;
387
388 for (vid = vlan->vid_begin; vid < vlan->vid_end; vid++)
389 if (!smi->ops->is_vlan_valid(smi, vid))
390 return;
391
392 dev_info(smi->dev, "add VLAN on port %d, %s, %s\n",
393 port,
394 untagged ? "untagged" : "tagged",
395 pvid ? " PVID" : "no PVID");
396
397 if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
398 dev_err(smi->dev, "port is DSA or CPU port\n");
399
400 for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
401 int pvid_val = 0;
402
403 dev_info(smi->dev, "add VLAN %04x\n", vid);
404 member |= BIT(port);
405
406 if (untagged)
407 untag |= BIT(port);
408
409 /* To ensure that we have a valid MC entry for this VLAN,
410 * initialize the port VLAN ID here.
411 */
412 ret = rtl8366_get_pvid(smi, port, &pvid_val);
413 if (ret < 0) {
414 dev_err(smi->dev, "could not lookup PVID for port %d\n",
415 port);
416 return;
417 }
418 if (pvid_val == 0) {
419 ret = rtl8366_set_pvid(smi, port, vid);
420 if (ret < 0)
421 return;
422 }
423
424 ret = rtl8366_set_vlan(smi, vid, member, untag, 0);
425 if (ret)
426 dev_err(smi->dev,
427 "failed to set up VLAN %04x",
428 vid);
429 }
430}
431EXPORT_SYMBOL_GPL(rtl8366_vlan_add);
432
433int rtl8366_vlan_del(struct dsa_switch *ds, int port,
434 const struct switchdev_obj_port_vlan *vlan)
435{
436 struct realtek_smi *smi = ds->priv;
437 u16 vid;
438 int ret;
439
440 dev_info(smi->dev, "del VLAN on port %d\n", port);
441
442 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
443 int i;
444
445 dev_info(smi->dev, "del VLAN %04x\n", vid);
446
447 for (i = 0; i < smi->num_vlan_mc; i++) {
448 struct rtl8366_vlan_mc vlanmc;
449
450 ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
451 if (ret)
452 return ret;
453
454 if (vid == vlanmc.vid) {
455 /* Remove this port from the VLAN */
456 vlanmc.member &= ~BIT(port);
457 vlanmc.untag &= ~BIT(port);
458 /*
459 * If no ports are members of this VLAN
460 * anymore then clear the whole member
461 * config so it can be reused.
462 */
463 if (!vlanmc.member && vlanmc.untag) {
464 vlanmc.vid = 0;
465 vlanmc.priority = 0;
466 vlanmc.fid = 0;
467 }
468 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
469 if (ret) {
470 dev_err(smi->dev,
471 "failed to remove VLAN %04x\n",
472 vid);
473 return ret;
474 }
475 break;
476 }
477 }
478 }
479
480 return 0;
481}
482EXPORT_SYMBOL_GPL(rtl8366_vlan_del);
483
484void rtl8366_get_strings(struct dsa_switch *ds, int port, u32 stringset,
485 uint8_t *data)
486{
487 struct realtek_smi *smi = ds->priv;
488 struct rtl8366_mib_counter *mib;
489 int i;
490
491 if (port >= smi->num_ports)
492 return;
493
494 for (i = 0; i < smi->num_mib_counters; i++) {
495 mib = &smi->mib_counters[i];
496 strncpy(data + i * ETH_GSTRING_LEN,
497 mib->name, ETH_GSTRING_LEN);
498 }
499}
500EXPORT_SYMBOL_GPL(rtl8366_get_strings);
501
502int rtl8366_get_sset_count(struct dsa_switch *ds, int port, int sset)
503{
504 struct realtek_smi *smi = ds->priv;
505
506 /* We only support SS_STATS */
507 if (sset != ETH_SS_STATS)
508 return 0;
509 if (port >= smi->num_ports)
510 return -EINVAL;
511
512 return smi->num_mib_counters;
513}
514EXPORT_SYMBOL_GPL(rtl8366_get_sset_count);
515
516void rtl8366_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
517{
518 struct realtek_smi *smi = ds->priv;
519 int i;
520 int ret;
521
522 if (port >= smi->num_ports)
523 return;
524
525 for (i = 0; i < smi->num_mib_counters; i++) {
526 struct rtl8366_mib_counter *mib;
527 u64 mibvalue = 0;
528
529 mib = &smi->mib_counters[i];
530 ret = smi->ops->get_mib_counter(smi, port, mib, &mibvalue);
531 if (ret) {
532 dev_err(smi->dev, "error reading MIB counter %s\n",
533 mib->name);
534 }
535 data[i] = mibvalue;
536 }
537}
538EXPORT_SYMBOL_GPL(rtl8366_get_ethtool_stats);