1 // SPDX-License-Identifier: GPL-2.0
2 /* Realtek SMI library helpers for the RTL8366x variants
3 * RTL8366RB and RTL8366S
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>
11 #include <linux/if_bridge.h>
14 #include "realtek-smi-core.h"
16 int rtl8366_mc_is_used(struct realtek_smi
*smi
, int mc_index
, int *used
)
22 for (i
= 0; i
< smi
->num_ports
; i
++) {
25 ret
= smi
->ops
->get_mc_index(smi
, i
, &index
);
29 if (mc_index
== index
) {
37 EXPORT_SYMBOL_GPL(rtl8366_mc_is_used
);
39 int rtl8366_set_vlan(struct realtek_smi
*smi
, int vid
, u32 member
,
42 struct rtl8366_vlan_4k vlan4k
;
46 /* Update the 4K table */
47 ret
= smi
->ops
->get_vlan_4k(smi
, vid
, &vlan4k
);
51 vlan4k
.member
= member
;
54 ret
= smi
->ops
->set_vlan_4k(smi
, &vlan4k
);
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
;
62 ret
= smi
->ops
->get_vlan_mc(smi
, i
, &vlanmc
);
66 if (vid
== vlanmc
.vid
) {
67 /* update the MC entry */
68 vlanmc
.member
= member
;
72 ret
= smi
->ops
->set_vlan_mc(smi
, i
, &vlanmc
);
79 EXPORT_SYMBOL_GPL(rtl8366_set_vlan
);
81 int rtl8366_get_pvid(struct realtek_smi
*smi
, int port
, int *val
)
83 struct rtl8366_vlan_mc vlanmc
;
87 ret
= smi
->ops
->get_mc_index(smi
, port
, &index
);
91 ret
= smi
->ops
->get_vlan_mc(smi
, index
, &vlanmc
);
98 EXPORT_SYMBOL_GPL(rtl8366_get_pvid
);
100 int rtl8366_set_pvid(struct realtek_smi
*smi
, unsigned int port
,
103 struct rtl8366_vlan_mc vlanmc
;
104 struct rtl8366_vlan_4k vlan4k
;
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
);
114 if (vid
== vlanmc
.vid
) {
115 ret
= smi
->ops
->set_vlan_mc(smi
, i
, &vlanmc
);
119 ret
= smi
->ops
->set_mc_index(smi
, port
, i
);
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
);
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
);
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
);
144 ret
= smi
->ops
->set_mc_index(smi
, port
, i
);
149 /* MC table is full, try to find an unused entry and replace it */
150 for (i
= 0; i
< smi
->num_vlan_mc
; i
++) {
153 ret
= rtl8366_mc_is_used(smi
, i
, &used
);
158 /* Update the entry from the 4K table */
159 ret
= smi
->ops
->get_vlan_4k(smi
, vid
, &vlan4k
);
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
);
171 ret
= smi
->ops
->set_mc_index(smi
, port
, i
);
177 "all VLAN member configurations are in use\n");
181 EXPORT_SYMBOL_GPL(rtl8366_set_pvid
);
183 int rtl8366_enable_vlan4k(struct realtek_smi
*smi
, bool enable
)
187 /* To enable 4k VLAN, ordinary VLAN must be enabled first,
188 * but if we disable 4k VLAN it is fine to leave ordinary
192 /* Make sure VLAN is ON */
193 ret
= smi
->ops
->enable_vlan(smi
, true);
197 smi
->vlan_enabled
= true;
200 ret
= smi
->ops
->enable_vlan4k(smi
, enable
);
204 smi
->vlan4k_enabled
= enable
;
207 EXPORT_SYMBOL_GPL(rtl8366_enable_vlan4k
);
209 int rtl8366_enable_vlan(struct realtek_smi
*smi
, bool enable
)
213 ret
= smi
->ops
->enable_vlan(smi
, enable
);
217 smi
->vlan_enabled
= enable
;
219 /* If we turn VLAN off, make sure that we turn off
220 * 4k VLAN as well, if that happened to be on.
223 smi
->vlan4k_enabled
= false;
224 ret
= smi
->ops
->enable_vlan4k(smi
, false);
229 EXPORT_SYMBOL_GPL(rtl8366_enable_vlan
);
231 int rtl8366_reset_vlan(struct realtek_smi
*smi
)
233 struct rtl8366_vlan_mc vlanmc
;
237 rtl8366_enable_vlan(smi
, false);
238 rtl8366_enable_vlan4k(smi
, false);
240 /* Clear the 16 VLAN member configurations */
246 for (i
= 0; i
< smi
->num_vlan_mc
; i
++) {
247 ret
= smi
->ops
->set_vlan_mc(smi
, i
, &vlanmc
);
254 EXPORT_SYMBOL_GPL(rtl8366_reset_vlan
);
256 int rtl8366_init_vlan(struct realtek_smi
*smi
)
261 ret
= rtl8366_reset_vlan(smi
);
265 /* Loop over the available ports, for each port, associate
266 * it with the VLAN (port+1)
268 for (port
= 0; port
< smi
->num_ports
; port
++) {
271 if (port
== smi
->cpu_port
)
272 /* For the CPU port, make all ports members of this
275 mask
= GENMASK(smi
->num_ports
- 1, 0);
277 /* For all other ports, enable itself plus the
280 mask
= BIT(port
) | BIT(smi
->cpu_port
);
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).
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);
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));
300 return rtl8366_enable_vlan(smi
, true);
302 EXPORT_SYMBOL_GPL(rtl8366_init_vlan
);
304 int rtl8366_vlan_filtering(struct dsa_switch
*ds
, int port
, bool vlan_filtering
)
306 struct realtek_smi
*smi
= ds
->priv
;
307 struct rtl8366_vlan_4k vlan4k
;
310 /* Use VLAN nr port + 1 since VLAN0 is not valid */
311 if (!smi
->ops
->is_vlan_valid(smi
, port
+ 1))
314 dev_info(smi
->dev
, "%s filtering on port %d\n",
315 vlan_filtering
? "enable" : "disable",
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.
322 ret
= smi
->ops
->get_vlan_4k(smi
, port
+ 1, &vlan4k
);
326 /* Just set the filter to FID 1 for now then */
327 ret
= rtl8366_set_vlan(smi
, port
+ 1,
336 EXPORT_SYMBOL_GPL(rtl8366_vlan_filtering
);
338 int rtl8366_vlan_prepare(struct dsa_switch
*ds
, int port
,
339 const struct switchdev_obj_port_vlan
*vlan
)
341 struct realtek_smi
*smi
= ds
->priv
;
345 for (vid
= vlan
->vid_begin
; vid
< vlan
->vid_end
; vid
++)
346 if (!smi
->ops
->is_vlan_valid(smi
, vid
))
349 dev_info(smi
->dev
, "prepare VLANs %04x..%04x\n",
350 vlan
->vid_begin
, vlan
->vid_end
);
352 /* Enable VLAN in the hardware
353 * FIXME: what's with this 4k business?
354 * Just rtl8366_enable_vlan() seems inconclusive.
356 ret
= rtl8366_enable_vlan4k(smi
, true);
362 EXPORT_SYMBOL_GPL(rtl8366_vlan_prepare
);
364 void rtl8366_vlan_add(struct dsa_switch
*ds
, int port
,
365 const struct switchdev_obj_port_vlan
*vlan
)
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
;
375 for (vid
= vlan
->vid_begin
; vid
< vlan
->vid_end
; vid
++)
376 if (!smi
->ops
->is_vlan_valid(smi
, vid
))
379 dev_info(smi
->dev
, "add VLAN on port %d, %s, %s\n",
381 untagged
? "untagged" : "tagged",
382 pvid
? " PVID" : "no PVID");
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");
387 for (vid
= vlan
->vid_begin
; vid
<= vlan
->vid_end
; ++vid
) {
390 dev_info(smi
->dev
, "add VLAN %04x\n", vid
);
396 /* To ensure that we have a valid MC entry for this VLAN,
397 * initialize the port VLAN ID here.
399 ret
= rtl8366_get_pvid(smi
, port
, &pvid_val
);
401 dev_err(smi
->dev
, "could not lookup PVID for port %d\n",
406 ret
= rtl8366_set_pvid(smi
, port
, vid
);
412 ret
= rtl8366_set_vlan(smi
, port
, member
, untag
, 0);
415 "failed to set up VLAN %04x",
418 EXPORT_SYMBOL_GPL(rtl8366_vlan_add
);
420 int rtl8366_vlan_del(struct dsa_switch
*ds
, int port
,
421 const struct switchdev_obj_port_vlan
*vlan
)
423 struct realtek_smi
*smi
= ds
->priv
;
427 dev_info(smi
->dev
, "del VLAN on port %d\n", port
);
429 for (vid
= vlan
->vid_begin
; vid
<= vlan
->vid_end
; ++vid
) {
432 dev_info(smi
->dev
, "del VLAN %04x\n", vid
);
434 for (i
= 0; i
< smi
->num_vlan_mc
; i
++) {
435 struct rtl8366_vlan_mc vlanmc
;
437 ret
= smi
->ops
->get_vlan_mc(smi
, i
, &vlanmc
);
441 if (vid
== vlanmc
.vid
) {
442 /* clear VLAN member configurations */
449 ret
= smi
->ops
->set_vlan_mc(smi
, i
, &vlanmc
);
452 "failed to remove VLAN %04x\n",
463 EXPORT_SYMBOL_GPL(rtl8366_vlan_del
);
465 void rtl8366_get_strings(struct dsa_switch
*ds
, int port
, u32 stringset
,
468 struct realtek_smi
*smi
= ds
->priv
;
469 struct rtl8366_mib_counter
*mib
;
472 if (port
>= smi
->num_ports
)
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
);
481 EXPORT_SYMBOL_GPL(rtl8366_get_strings
);
483 int rtl8366_get_sset_count(struct dsa_switch
*ds
, int port
, int sset
)
485 struct realtek_smi
*smi
= ds
->priv
;
487 /* We only support SS_STATS */
488 if (sset
!= ETH_SS_STATS
)
490 if (port
>= smi
->num_ports
)
493 return smi
->num_mib_counters
;
495 EXPORT_SYMBOL_GPL(rtl8366_get_sset_count
);
497 void rtl8366_get_ethtool_stats(struct dsa_switch
*ds
, int port
, uint64_t *data
)
499 struct realtek_smi
*smi
= ds
->priv
;
503 if (port
>= smi
->num_ports
)
506 for (i
= 0; i
< smi
->num_mib_counters
; i
++) {
507 struct rtl8366_mib_counter
*mib
;
510 mib
= &smi
->mib_counters
[i
];
511 ret
= smi
->ops
->get_mib_counter(smi
, port
, mib
, &mibvalue
);
513 dev_err(smi
->dev
, "error reading MIB counter %s\n",
519 EXPORT_SYMBOL_GPL(rtl8366_get_ethtool_stats
);