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