1 // SPDX-License-Identifier: GPL-2.0
2 /* Realtek SMI library helpers for the RTL8366x variants
3 * RTL8366RB and RTL8366S
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;
47 "setting VLAN%d 4k members: 0x%02x, untagged: 0x%02x\n",
50 /* Update the 4K table */
51 ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
55 vlan4k.member |= member;
56 vlan4k.untag |= untag;
58 ret = smi->ops->set_vlan_4k(smi, &vlan4k);
63 "resulting VLAN%d 4k members: 0x%02x, untagged: 0x%02x\n",
64 vid, vlan4k.member, vlan4k.untag);
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;
70 ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
74 if (vid == vlanmc.vid) {
75 /* update the MC entry */
76 vlanmc.member |= member;
77 vlanmc.untag |= untag;
80 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
83 "resulting VLAN%d MC members: 0x%02x, untagged: 0x%02x\n",
84 vid, vlanmc.member, vlanmc.untag);
92 EXPORT_SYMBOL_GPL(rtl8366_set_vlan);
94 int rtl8366_get_pvid(struct realtek_smi *smi, int port, int *val)
96 struct rtl8366_vlan_mc vlanmc;
100 ret = smi->ops->get_mc_index(smi, port, &index);
104 ret = smi->ops->get_vlan_mc(smi, index, &vlanmc);
111 EXPORT_SYMBOL_GPL(rtl8366_get_pvid);
113 int rtl8366_set_pvid(struct realtek_smi *smi, unsigned int port,
116 struct rtl8366_vlan_mc vlanmc;
117 struct rtl8366_vlan_4k vlan4k;
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);
127 if (vid == vlanmc.vid) {
128 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
132 ret = smi->ops->set_mc_index(smi, port, i);
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);
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);
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);
157 ret = smi->ops->set_mc_index(smi, port, i);
162 /* MC table is full, try to find an unused entry and replace it */
163 for (i = 0; i < smi->num_vlan_mc; i++) {
166 ret = rtl8366_mc_is_used(smi, i, &used);
171 /* Update the entry from the 4K table */
172 ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
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);
184 ret = smi->ops->set_mc_index(smi, port, i);
190 "all VLAN member configurations are in use\n");
194 EXPORT_SYMBOL_GPL(rtl8366_set_pvid);
196 int rtl8366_enable_vlan4k(struct realtek_smi *smi, bool enable)
200 /* To enable 4k VLAN, ordinary VLAN must be enabled first,
201 * but if we disable 4k VLAN it is fine to leave ordinary
205 /* Make sure VLAN is ON */
206 ret = smi->ops->enable_vlan(smi, true);
210 smi->vlan_enabled = true;
213 ret = smi->ops->enable_vlan4k(smi, enable);
217 smi->vlan4k_enabled = enable;
220 EXPORT_SYMBOL_GPL(rtl8366_enable_vlan4k);
222 int rtl8366_enable_vlan(struct realtek_smi *smi, bool enable)
226 ret = smi->ops->enable_vlan(smi, enable);
230 smi->vlan_enabled = enable;
232 /* If we turn VLAN off, make sure that we turn off
233 * 4k VLAN as well, if that happened to be on.
236 smi->vlan4k_enabled = false;
237 ret = smi->ops->enable_vlan4k(smi, false);
242 EXPORT_SYMBOL_GPL(rtl8366_enable_vlan);
244 int rtl8366_reset_vlan(struct realtek_smi *smi)
246 struct rtl8366_vlan_mc vlanmc;
250 rtl8366_enable_vlan(smi, false);
251 rtl8366_enable_vlan4k(smi, false);
253 /* Clear the 16 VLAN member configurations */
259 for (i = 0; i < smi->num_vlan_mc; i++) {
260 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
267 EXPORT_SYMBOL_GPL(rtl8366_reset_vlan);
269 int rtl8366_init_vlan(struct realtek_smi *smi)
274 ret = rtl8366_reset_vlan(smi);
278 /* Loop over the available ports, for each port, associate
279 * it with the VLAN (port+1)
281 for (port = 0; port < smi->num_ports; port++) {
284 if (port == smi->cpu_port)
285 /* For the CPU port, make all ports members of this
288 mask = GENMASK((int)smi->num_ports - 1, 0);
290 /* For all other ports, enable itself plus the
293 mask = BIT(port) | BIT(smi->cpu_port);
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).
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);
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));
313 return rtl8366_enable_vlan(smi, true);
315 EXPORT_SYMBOL_GPL(rtl8366_init_vlan);
317 int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
319 struct realtek_smi *smi = ds->priv;
320 struct rtl8366_vlan_4k vlan4k;
323 /* Use VLAN nr port + 1 since VLAN0 is not valid */
324 if (!smi->ops->is_vlan_valid(smi, port + 1))
327 dev_info(smi->dev, "%s filtering on port %d\n",
328 vlan_filtering ? "enable" : "disable",
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.
335 ret = smi->ops->get_vlan_4k(smi, port + 1, &vlan4k);
339 /* Just set the filter to FID 1 for now then */
340 ret = rtl8366_set_vlan(smi, port + 1,
349 EXPORT_SYMBOL_GPL(rtl8366_vlan_filtering);
351 int rtl8366_vlan_prepare(struct dsa_switch *ds, int port,
352 const struct switchdev_obj_port_vlan *vlan)
354 struct realtek_smi *smi = ds->priv;
358 for (vid = vlan->vid_begin; vid < vlan->vid_end; vid++)
359 if (!smi->ops->is_vlan_valid(smi, vid))
362 dev_info(smi->dev, "prepare VLANs %04x..%04x\n",
363 vlan->vid_begin, vlan->vid_end);
365 /* Enable VLAN in the hardware
366 * FIXME: what's with this 4k business?
367 * Just rtl8366_enable_vlan() seems inconclusive.
369 ret = rtl8366_enable_vlan4k(smi, true);
375 EXPORT_SYMBOL_GPL(rtl8366_vlan_prepare);
377 void rtl8366_vlan_add(struct dsa_switch *ds, int port,
378 const struct switchdev_obj_port_vlan *vlan)
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;
388 for (vid = vlan->vid_begin; vid < vlan->vid_end; vid++)
389 if (!smi->ops->is_vlan_valid(smi, vid))
392 dev_info(smi->dev, "add VLAN on port %d, %s, %s\n",
394 untagged ? "untagged" : "tagged",
395 pvid ? " PVID" : "no PVID");
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");
400 for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
403 dev_info(smi->dev, "add VLAN %04x\n", vid);
409 /* To ensure that we have a valid MC entry for this VLAN,
410 * initialize the port VLAN ID here.
412 ret = rtl8366_get_pvid(smi, port, &pvid_val);
414 dev_err(smi->dev, "could not lookup PVID for port %d\n",
419 ret = rtl8366_set_pvid(smi, port, vid);
424 ret = rtl8366_set_vlan(smi, vid, member, untag, 0);
427 "failed to set up VLAN %04x",
431 EXPORT_SYMBOL_GPL(rtl8366_vlan_add);
433 int rtl8366_vlan_del(struct dsa_switch *ds, int port,
434 const struct switchdev_obj_port_vlan *vlan)
436 struct realtek_smi *smi = ds->priv;
440 dev_info(smi->dev, "del VLAN on port %d\n", port);
442 for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
445 dev_info(smi->dev, "del VLAN %04x\n", vid);
447 for (i = 0; i < smi->num_vlan_mc; i++) {
448 struct rtl8366_vlan_mc vlanmc;
450 ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
454 if (vid == vlanmc.vid) {
455 /* clear VLAN member configurations */
462 ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
465 "failed to remove VLAN %04x\n",
476 EXPORT_SYMBOL_GPL(rtl8366_vlan_del);
478 void rtl8366_get_strings(struct dsa_switch *ds, int port, u32 stringset,
481 struct realtek_smi *smi = ds->priv;
482 struct rtl8366_mib_counter *mib;
485 if (port >= smi->num_ports)
488 for (i = 0; i < smi->num_mib_counters; i++) {
489 mib = &smi->mib_counters[i];
490 strncpy(data + i * ETH_GSTRING_LEN,
491 mib->name, ETH_GSTRING_LEN);
494 EXPORT_SYMBOL_GPL(rtl8366_get_strings);
496 int rtl8366_get_sset_count(struct dsa_switch *ds, int port, int sset)
498 struct realtek_smi *smi = ds->priv;
500 /* We only support SS_STATS */
501 if (sset != ETH_SS_STATS)
503 if (port >= smi->num_ports)
506 return smi->num_mib_counters;
508 EXPORT_SYMBOL_GPL(rtl8366_get_sset_count);
510 void rtl8366_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
512 struct realtek_smi *smi = ds->priv;
516 if (port >= smi->num_ports)
519 for (i = 0; i < smi->num_mib_counters; i++) {
520 struct rtl8366_mib_counter *mib;
523 mib = &smi->mib_counters[i];
524 ret = smi->ops->get_mib_counter(smi, port, mib, &mibvalue);
526 dev_err(smi->dev, "error reading MIB counter %s\n",
532 EXPORT_SYMBOL_GPL(rtl8366_get_ethtool_stats);