Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.5-rc6 519 lines 12 kB view raw
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);