Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / net / dsa / rtl8366.c
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
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         /* 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 }
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         /* 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 }
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         /* 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 }
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         /* 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 }
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         /* 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 }
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         /* 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 }
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         /* 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 }
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         /* 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 }
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                 /* 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 }
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                                 /* 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 }
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         /* 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 }
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);