1 /*- 2 * Copyright (c) 2015 Semihalf 3 * Copyright (c) 2015 Stormshield 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/param.h> 32 #include <sys/bus.h> 33 #include <sys/errno.h> 34 #include <sys/kernel.h> 35 #include <sys/kthread.h> 36 #include <sys/module.h> 37 #include <sys/socket.h> 38 #include <sys/sockio.h> 39 40 #include <net/if.h> 41 #include <net/if_media.h> 42 #include <net/if_types.h> 43 44 #include <dev/etherswitch/etherswitch.h> 45 #include <dev/mii/mii.h> 46 #include <dev/mii/miivar.h> 47 48 #include <dev/fdt/fdt_common.h> 49 #include <dev/ofw/ofw_bus.h> 50 51 #include "e6000swreg.h" 52 #include "etherswitch_if.h" 53 #include "miibus_if.h" 54 #include "mdio_if.h" 55 56 MALLOC_DECLARE(M_E6000SW); 57 MALLOC_DEFINE(M_E6000SW, "e6000sw", "e6000sw switch"); 58 59 #define E6000SW_LOCK(_sc) sx_xlock(&(_sc)->sx) 60 #define E6000SW_UNLOCK(_sc) sx_unlock(&(_sc)->sx) 61 #define E6000SW_LOCK_ASSERT(_sc, _what) sx_assert(&(_sc)->sx, (_what)) 62 #define E6000SW_TRYLOCK(_sc) sx_tryxlock(&(_sc)->sx) 63 64 typedef struct e6000sw_softc { 65 device_t dev; 66 phandle_t node; 67 68 struct sx sx; 69 struct ifnet *ifp[E6000SW_MAX_PORTS]; 70 char *ifname[E6000SW_MAX_PORTS]; 71 device_t miibus[E6000SW_MAX_PORTS]; 72 struct proc *kproc; 73 74 uint32_t cpuports_mask; 75 uint32_t fixed_mask; 76 int sw_addr; 77 int num_ports; 78 boolean_t multi_chip; 79 80 int vid[E6000SW_NUM_VGROUPS]; 81 int members[E6000SW_NUM_VGROUPS]; 82 int vgroup[E6000SW_MAX_PORTS]; 83 } e6000sw_softc_t; 84 85 static etherswitch_info_t etherswitch_info = { 86 .es_nports = 0, 87 .es_nvlangroups = E6000SW_NUM_VGROUPS, 88 .es_name = "Marvell 6000 series switch" 89 }; 90 91 static void e6000sw_identify(driver_t *, device_t); 92 static int e6000sw_probe(device_t); 93 static int e6000sw_attach(device_t); 94 static int e6000sw_detach(device_t); 95 static int e6000sw_readphy(device_t, int, int); 96 static int e6000sw_writephy(device_t, int, int, int); 97 static etherswitch_info_t* e6000sw_getinfo(device_t); 98 static void e6000sw_lock(device_t); 99 static void e6000sw_unlock(device_t); 100 static int e6000sw_getport(device_t, etherswitch_port_t *); 101 static int e6000sw_setport(device_t, etherswitch_port_t *); 102 static int e6000sw_readreg_wrapper(device_t, int); 103 static int e6000sw_writereg_wrapper(device_t, int, int); 104 static int e6000sw_readphy_wrapper(device_t, int, int); 105 static int e6000sw_writephy_wrapper(device_t, int, int, int); 106 static int e6000sw_getvgroup_wrapper(device_t, etherswitch_vlangroup_t *); 107 static int e6000sw_setvgroup_wrapper(device_t, etherswitch_vlangroup_t *); 108 static int e6000sw_setvgroup(device_t, etherswitch_vlangroup_t *); 109 static int e6000sw_getvgroup(device_t, etherswitch_vlangroup_t *); 110 static void e6000sw_setup(device_t, e6000sw_softc_t *); 111 static void e6000sw_port_vlan_conf(e6000sw_softc_t *); 112 static void e6000sw_tick(void *); 113 static void e6000sw_set_atustat(device_t, e6000sw_softc_t *, int, int); 114 static int e6000sw_atu_flush(device_t, e6000sw_softc_t *, int); 115 static __inline void e6000sw_writereg(e6000sw_softc_t *, int, int, int); 116 static __inline uint32_t e6000sw_readreg(e6000sw_softc_t *, int, int); 117 static int e6000sw_ifmedia_upd(struct ifnet *); 118 static void e6000sw_ifmedia_sts(struct ifnet *, struct ifmediareq *); 119 static int e6000sw_atu_mac_table(device_t, e6000sw_softc_t *, struct atu_opt *, 120 int); 121 static int e6000sw_get_pvid(e6000sw_softc_t *, int, int *); 122 static int e6000sw_set_pvid(e6000sw_softc_t *, int, int); 123 static __inline bool e6000sw_is_cpuport(e6000sw_softc_t *, int); 124 static __inline bool e6000sw_is_fixedport(e6000sw_softc_t *, int); 125 static __inline bool e6000sw_is_phyport(e6000sw_softc_t *, int); 126 static __inline struct mii_data *e6000sw_miiforphy(e6000sw_softc_t *, 127 unsigned int); 128 129 static device_method_t e6000sw_methods[] = { 130 /* device interface */ 131 DEVMETHOD(device_identify, e6000sw_identify), 132 DEVMETHOD(device_probe, e6000sw_probe), 133 DEVMETHOD(device_attach, e6000sw_attach), 134 DEVMETHOD(device_detach, e6000sw_detach), 135 136 /* bus interface */ 137 DEVMETHOD(bus_add_child, device_add_child_ordered), 138 139 /* mii interface */ 140 DEVMETHOD(miibus_readreg, e6000sw_readphy), 141 DEVMETHOD(miibus_writereg, e6000sw_writephy), 142 143 /* etherswitch interface */ 144 DEVMETHOD(etherswitch_getinfo, e6000sw_getinfo), 145 DEVMETHOD(etherswitch_lock, e6000sw_lock), 146 DEVMETHOD(etherswitch_unlock, e6000sw_unlock), 147 DEVMETHOD(etherswitch_getport, e6000sw_getport), 148 DEVMETHOD(etherswitch_setport, e6000sw_setport), 149 DEVMETHOD(etherswitch_readreg, e6000sw_readreg_wrapper), 150 DEVMETHOD(etherswitch_writereg, e6000sw_writereg_wrapper), 151 DEVMETHOD(etherswitch_readphyreg, e6000sw_readphy_wrapper), 152 DEVMETHOD(etherswitch_writephyreg, e6000sw_writephy_wrapper), 153 DEVMETHOD(etherswitch_setvgroup, e6000sw_setvgroup_wrapper), 154 DEVMETHOD(etherswitch_getvgroup, e6000sw_getvgroup_wrapper), 155 156 DEVMETHOD_END 157 }; 158 159 static devclass_t e6000sw_devclass; 160 161 DEFINE_CLASS_0(e6000sw, e6000sw_driver, e6000sw_methods, 162 sizeof(e6000sw_softc_t)); 163 164 DRIVER_MODULE(e6000sw, mdio, e6000sw_driver, e6000sw_devclass, 0, 0); 165 DRIVER_MODULE(etherswitch, e6000sw, etherswitch_driver, etherswitch_devclass, 0, 166 0); 167 DRIVER_MODULE(miibus, e6000sw, miibus_driver, miibus_devclass, 0, 0); 168 MODULE_DEPEND(e6000sw, mdio, 1, 1, 1); 169 170 #define SMI_CMD 0 171 #define SMI_CMD_BUSY (1 << 15) 172 #define SMI_CMD_OP_READ ((2 << 10) | SMI_CMD_BUSY | (1 << 12)) 173 #define SMI_CMD_OP_WRITE ((1 << 10) | SMI_CMD_BUSY | (1 << 12)) 174 #define SMI_DATA 1 175 176 #define MDIO_READ(dev, addr, reg) \ 177 MDIO_READREG(device_get_parent(dev), (addr), (reg)) 178 #define MDIO_WRITE(dev, addr, reg, val) \ 179 MDIO_WRITEREG(device_get_parent(dev), (addr), (reg), (val)) 180 181 static void 182 e6000sw_identify(driver_t *driver, device_t parent) 183 { 184 185 if (device_find_child(parent, "e6000sw", -1) == NULL) 186 BUS_ADD_CHILD(parent, 0, "e6000sw", -1); 187 } 188 189 static int 190 e6000sw_probe(device_t dev) 191 { 192 e6000sw_softc_t *sc; 193 const char *description; 194 phandle_t dsa_node, switch_node; 195 uint32_t id; 196 197 dsa_node = fdt_find_compatible(OF_finddevice("/"), 198 "marvell,dsa", 0); 199 switch_node = OF_child(dsa_node); 200 201 if (switch_node == 0) 202 return (ENXIO); 203 204 sc = device_get_softc(dev); 205 bzero(sc, sizeof(e6000sw_softc_t)); 206 sc->dev = dev; 207 sc->node = switch_node; 208 209 if (OF_getencprop(sc->node, "reg", &sc->sw_addr, 210 sizeof(sc->sw_addr)) < 0) 211 return (ENXIO); 212 if (sc->sw_addr != 0 && (sc->sw_addr % 2) == 0) 213 sc->multi_chip = true; 214 215 /* Lock is necessary due to assertions. */ 216 sx_init(&sc->sx, "e6000sw"); 217 E6000SW_LOCK(sc); 218 id = e6000sw_readreg(sc, REG_PORT(0), SWITCH_ID); 219 E6000SW_UNLOCK(sc); 220 221 switch (id & 0xfff0) { 222 case 0x3520: 223 description = "Marvell 88E6352"; 224 break; 225 case 0x1720: 226 description = "Marvell 88E6172"; 227 break; 228 case 0x1760: 229 description = "Marvell 88E6176"; 230 break; 231 default: 232 sx_destroy(&sc->sx); 233 device_printf(dev, "Unrecognized device, id 0x%x.\n", id); 234 return (ENXIO); 235 } 236 237 device_set_desc(dev, description); 238 239 return (BUS_PROBE_DEFAULT); 240 } 241 242 static int 243 e6000sw_parse_child_fdt(device_t dev, phandle_t child, uint32_t *fixed_mask, 244 uint32_t *cpu_mask, int *pport, int *pvlangroup) 245 { 246 char portlabel[100]; 247 uint32_t port, vlangroup; 248 boolean_t fixed_link; 249 250 if (fixed_mask == NULL || cpu_mask == NULL || pport == NULL) 251 return (ENXIO); 252 253 OF_getprop(child, "label", (void *)portlabel, 100); 254 OF_getencprop(child, "reg", (void *)&port, sizeof(port)); 255 256 if (OF_getencprop(child, "vlangroup", (void *)&vlangroup, 257 sizeof(vlangroup)) > 0) { 258 if (vlangroup >= E6000SW_NUM_VGROUPS) 259 return (ENXIO); 260 *pvlangroup = vlangroup; 261 } else { 262 *pvlangroup = -1; 263 } 264 265 if (port >= E6000SW_MAX_PORTS) 266 return (ENXIO); 267 *pport = port; 268 269 if (strncmp(portlabel, "cpu", 3) == 0) { 270 device_printf(dev, "CPU port at %d\n", port); 271 *cpu_mask |= (1 << port); 272 return (0); 273 } 274 275 fixed_link = OF_child(child); 276 if (fixed_link) { 277 *fixed_mask |= (1 << port); 278 device_printf(dev, "fixed port at %d\n", port); 279 } else { 280 device_printf(dev, "PHY at port %d\n", port); 281 } 282 283 return (0); 284 } 285 286 static int 287 e6000sw_init_interface(e6000sw_softc_t *sc, int port) 288 { 289 char name[IFNAMSIZ]; 290 291 snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->dev)); 292 293 sc->ifp[port] = if_alloc(IFT_ETHER); 294 if (sc->ifp[port] == NULL) 295 return (ENOMEM); 296 sc->ifp[port]->if_softc = sc; 297 sc->ifp[port]->if_flags |= IFF_UP | IFF_BROADCAST | 298 IFF_DRV_RUNNING | IFF_SIMPLEX; 299 sc->ifname[port] = malloc(strlen(name) + 1, M_E6000SW, M_NOWAIT); 300 if (sc->ifname[port] == NULL) { 301 if_free(sc->ifp[port]); 302 return (ENOMEM); 303 } 304 memcpy(sc->ifname[port], name, strlen(name) + 1); 305 if_initname(sc->ifp[port], sc->ifname[port], port); 306 307 return (0); 308 } 309 310 static int 311 e6000sw_attach_miibus(e6000sw_softc_t *sc, int port) 312 { 313 int err; 314 315 err = mii_attach(sc->dev, &sc->miibus[port], sc->ifp[port], 316 e6000sw_ifmedia_upd, e6000sw_ifmedia_sts, BMSR_DEFCAPMASK, 317 port, MII_OFFSET_ANY, 0); 318 if (err != 0) 319 return (err); 320 321 return (0); 322 } 323 324 static int 325 e6000sw_attach(device_t dev) 326 { 327 e6000sw_softc_t *sc; 328 phandle_t child; 329 int err, port, vlangroup; 330 int member_ports[E6000SW_NUM_VGROUPS]; 331 etherswitch_vlangroup_t vg; 332 333 err = 0; 334 sc = device_get_softc(dev); 335 336 if (sc->multi_chip) 337 device_printf(dev, "multi-chip addressing mode\n"); 338 else 339 device_printf(dev, "single-chip addressing mode\n"); 340 341 E6000SW_LOCK(sc); 342 e6000sw_setup(dev, sc); 343 bzero(member_ports, sizeof(member_ports)); 344 345 for (child = OF_child(sc->node); child != 0; child = OF_peer(child)) { 346 err = e6000sw_parse_child_fdt(dev, child, &sc->fixed_mask, 347 &sc->cpuports_mask, &port, &vlangroup); 348 if (err != 0) { 349 device_printf(sc->dev, "failed to parse DTS\n"); 350 goto out_fail; 351 } 352 353 if (vlangroup != -1) 354 member_ports[vlangroup] |= (1 << port); 355 356 sc->num_ports++; 357 358 err = e6000sw_init_interface(sc, port); 359 if (err != 0) { 360 device_printf(sc->dev, "failed to init interface\n"); 361 goto out_fail; 362 } 363 364 /* Don't attach miibus at CPU/fixed ports */ 365 if (!e6000sw_is_phyport(sc, port)) 366 continue; 367 368 err = e6000sw_attach_miibus(sc, port); 369 if (err != 0) { 370 device_printf(sc->dev, "failed to attach miibus\n"); 371 goto out_fail; 372 } 373 } 374 375 etherswitch_info.es_nports = sc->num_ports; 376 for (port = 0; port < sc->num_ports; port++) 377 sc->vgroup[port] = E6000SW_PORT_NO_VGROUP; 378 379 /* Set VLAN configuration */ 380 e6000sw_port_vlan_conf(sc); 381 382 /* Set vlangroups */ 383 for (vlangroup = 0; vlangroup < E6000SW_NUM_VGROUPS; vlangroup++) 384 if (member_ports[vlangroup] != 0) { 385 vg.es_vlangroup = vg.es_vid = vlangroup; 386 vg.es_member_ports = vg.es_untagged_ports = 387 member_ports[vlangroup]; 388 e6000sw_setvgroup(dev, &vg); 389 } 390 391 E6000SW_UNLOCK(sc); 392 393 bus_generic_probe(dev); 394 bus_generic_attach(dev); 395 396 kproc_create(e6000sw_tick, sc, &sc->kproc, 0, 0, "e6000sw tick kproc"); 397 398 return (0); 399 400 out_fail: 401 E6000SW_UNLOCK(sc); 402 e6000sw_detach(dev); 403 404 return (err); 405 } 406 407 static __inline int 408 e6000sw_poll_done(e6000sw_softc_t *sc) 409 { 410 int i; 411 412 for (i = 0; i < E6000SW_SMI_TIMEOUT; i++) { 413 414 if ((e6000sw_readreg(sc, REG_GLOBAL2, SMI_PHY_CMD_REG) & 415 (1 << PHY_CMD_SMI_BUSY)) == 0) 416 return (0); 417 418 pause("e6000sw PHY poll", hz/1000); 419 } 420 421 return (ETIMEDOUT); 422 } 423 424 /* 425 * PHY registers are paged. Put page index in reg 22 (accessible from every 426 * page), then access specific register. 427 */ 428 static int 429 e6000sw_readphy(device_t dev, int phy, int reg) 430 { 431 e6000sw_softc_t *sc; 432 uint32_t val; 433 int err; 434 435 sc = device_get_softc(dev); 436 if (!e6000sw_is_phyport(sc, phy) || reg >= E6000SW_NUM_PHY_REGS) { 437 device_printf(dev, "Wrong register address.\n"); 438 return (EINVAL); 439 } 440 441 E6000SW_LOCK_ASSERT(sc, SA_XLOCKED); 442 443 err = e6000sw_poll_done(sc); 444 if (err != 0) { 445 device_printf(dev, "Timeout while waiting for switch\n"); 446 return (err); 447 } 448 449 val = 1 << PHY_CMD_SMI_BUSY; 450 val |= PHY_CMD_MODE_MDIO << PHY_CMD_MODE; 451 val |= PHY_CMD_OPCODE_READ << PHY_CMD_OPCODE; 452 val |= (reg << PHY_CMD_REG_ADDR) & PHY_CMD_REG_ADDR_MASK; 453 val |= (phy << PHY_CMD_DEV_ADDR) & PHY_CMD_DEV_ADDR_MASK; 454 e6000sw_writereg(sc, REG_GLOBAL2, SMI_PHY_CMD_REG, val); 455 456 err = e6000sw_poll_done(sc); 457 if (err != 0) { 458 device_printf(dev, "Timeout while waiting for switch\n"); 459 return (err); 460 } 461 462 val = e6000sw_readreg(sc, REG_GLOBAL2, SMI_PHY_DATA_REG); 463 464 return (val & PHY_DATA_MASK); 465 } 466 467 static int 468 e6000sw_writephy(device_t dev, int phy, int reg, int data) 469 { 470 e6000sw_softc_t *sc; 471 uint32_t val; 472 int err; 473 474 sc = device_get_softc(dev); 475 if (!e6000sw_is_phyport(sc, phy) || reg >= E6000SW_NUM_PHY_REGS) { 476 device_printf(dev, "Wrong register address.\n"); 477 return (EINVAL); 478 } 479 480 E6000SW_LOCK_ASSERT(sc, SA_XLOCKED); 481 482 err = e6000sw_poll_done(sc); 483 if (err != 0) { 484 device_printf(dev, "Timeout while waiting for switch\n"); 485 return (err); 486 } 487 488 val = 1 << PHY_CMD_SMI_BUSY; 489 val |= PHY_CMD_MODE_MDIO << PHY_CMD_MODE; 490 val |= PHY_CMD_OPCODE_WRITE << PHY_CMD_OPCODE; 491 val |= (reg << PHY_CMD_REG_ADDR) & PHY_CMD_REG_ADDR_MASK; 492 val |= (phy << PHY_CMD_DEV_ADDR) & PHY_CMD_DEV_ADDR_MASK; 493 e6000sw_writereg(sc, REG_GLOBAL2, SMI_PHY_DATA_REG, 494 data & PHY_DATA_MASK); 495 e6000sw_writereg(sc, REG_GLOBAL2, SMI_PHY_CMD_REG, val); 496 497 err = e6000sw_poll_done(sc); 498 if (err != 0) 499 device_printf(dev, "Timeout while waiting for switch\n"); 500 501 return (err); 502 } 503 504 static int 505 e6000sw_detach(device_t dev) 506 { 507 int phy; 508 e6000sw_softc_t *sc; 509 510 sc = device_get_softc(dev); 511 bus_generic_detach(dev); 512 sx_destroy(&sc->sx); 513 for (phy = 0; phy < sc->num_ports; phy++) { 514 if (sc->miibus[phy] != NULL) 515 device_delete_child(dev, sc->miibus[phy]); 516 if (sc->ifp[phy] != NULL) 517 if_free(sc->ifp[phy]); 518 if (sc->ifname[phy] != NULL) 519 free(sc->ifname[phy], M_E6000SW); 520 } 521 522 return (0); 523 } 524 525 static etherswitch_info_t* 526 e6000sw_getinfo(device_t dev) 527 { 528 529 return (ðerswitch_info); 530 } 531 532 static void 533 e6000sw_lock(device_t dev) 534 { 535 struct e6000sw_softc *sc; 536 537 sc = device_get_softc(dev); 538 539 E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); 540 E6000SW_LOCK(sc); 541 } 542 543 static void 544 e6000sw_unlock(device_t dev) 545 { 546 struct e6000sw_softc *sc; 547 548 sc = device_get_softc(dev); 549 550 E6000SW_LOCK_ASSERT(sc, SA_XLOCKED); 551 E6000SW_UNLOCK(sc); 552 } 553 554 static int 555 e6000sw_getport(device_t dev, etherswitch_port_t *p) 556 { 557 struct mii_data *mii; 558 int err; 559 struct ifmediareq *ifmr; 560 561 e6000sw_softc_t *sc = device_get_softc(dev); 562 E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); 563 564 if (p->es_port >= sc->num_ports || p->es_port < 0) 565 return (EINVAL); 566 567 err = 0; 568 E6000SW_LOCK(sc); 569 e6000sw_get_pvid(sc, p->es_port, &p->es_pvid); 570 571 if (e6000sw_is_cpuport(sc, p->es_port)) { 572 p->es_flags |= ETHERSWITCH_PORT_CPU; 573 ifmr = &p->es_ifmr; 574 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; 575 ifmr->ifm_count = 0; 576 ifmr->ifm_current = ifmr->ifm_active = 577 IFM_ETHER | IFM_1000_T | IFM_FDX; 578 ifmr->ifm_mask = 0; 579 } else if (e6000sw_is_fixedport(sc, p->es_port)) { 580 ifmr = &p->es_ifmr; 581 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; 582 ifmr->ifm_count = 0; 583 ifmr->ifm_current = ifmr->ifm_active = 584 IFM_ETHER | IFM_1000_T | IFM_FDX; 585 ifmr->ifm_mask = 0; 586 } else { 587 mii = e6000sw_miiforphy(sc, p->es_port); 588 err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, 589 &mii->mii_media, SIOCGIFMEDIA); 590 } 591 E6000SW_UNLOCK(sc); 592 593 return (err); 594 } 595 596 static int 597 e6000sw_setport(device_t dev, etherswitch_port_t *p) 598 { 599 e6000sw_softc_t *sc; 600 int err; 601 struct mii_data *mii; 602 603 sc = device_get_softc(dev); 604 E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); 605 606 if (p->es_port >= sc->num_ports || p->es_port < 0) 607 return (EINVAL); 608 609 err = 0; 610 E6000SW_LOCK(sc); 611 if (p->es_pvid != 0) 612 e6000sw_set_pvid(sc, p->es_port, p->es_pvid); 613 if (!e6000sw_is_cpuport(sc, p->es_port)) { 614 mii = e6000sw_miiforphy(sc, p->es_port); 615 err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, &mii->mii_media, 616 SIOCSIFMEDIA); 617 } 618 E6000SW_UNLOCK(sc); 619 620 return (err); 621 } 622 623 /* 624 * Registers in this switch are divided into sections, specified in 625 * documentation. So as to access any of them, section index and reg index 626 * is necessary. etherswitchcfg uses only one variable, so indexes were 627 * compressed into addr_reg: 32 * section_index + reg_index. 628 */ 629 static int 630 e6000sw_readreg_wrapper(device_t dev, int addr_reg) 631 { 632 633 if ((addr_reg > (REG_GLOBAL2 * 32 + REG_NUM_MAX)) || 634 (addr_reg < (REG_PORT(0) * 32))) { 635 device_printf(dev, "Wrong register address.\n"); 636 return (EINVAL); 637 } 638 639 return (e6000sw_readreg(device_get_softc(dev), addr_reg / 32, 640 addr_reg % 32)); 641 } 642 643 static int 644 e6000sw_writereg_wrapper(device_t dev, int addr_reg, int val) 645 { 646 647 if ((addr_reg > (REG_GLOBAL2 * 32 + REG_NUM_MAX)) || 648 (addr_reg < (REG_PORT(0) * 32))) { 649 device_printf(dev, "Wrong register address.\n"); 650 return (EINVAL); 651 } 652 e6000sw_writereg(device_get_softc(dev), addr_reg / 5, 653 addr_reg % 32, val); 654 655 return (0); 656 } 657 658 /* 659 * These wrappers are necessary because PHY accesses from etherswitchcfg 660 * need to be synchronized with locks, while miibus PHY accesses do not. 661 */ 662 static int 663 e6000sw_readphy_wrapper(device_t dev, int phy, int reg) 664 { 665 e6000sw_softc_t *sc; 666 int ret; 667 668 sc = device_get_softc(dev); 669 E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); 670 671 E6000SW_LOCK(sc); 672 ret = e6000sw_readphy(dev, phy, reg); 673 E6000SW_UNLOCK(sc); 674 675 return (ret); 676 } 677 678 static int 679 e6000sw_writephy_wrapper(device_t dev, int phy, int reg, int data) 680 { 681 e6000sw_softc_t *sc; 682 int ret; 683 684 sc = device_get_softc(dev); 685 E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); 686 687 E6000SW_LOCK(sc); 688 ret = e6000sw_writephy(dev, phy, reg, data); 689 E6000SW_UNLOCK(sc); 690 691 return (ret); 692 } 693 694 /* 695 * setvgroup/getvgroup called from etherswitchfcg need to be locked, 696 * while internal calls do not. 697 */ 698 static int 699 e6000sw_setvgroup_wrapper(device_t dev, etherswitch_vlangroup_t *vg) 700 { 701 e6000sw_softc_t *sc; 702 int ret; 703 704 sc = device_get_softc(dev); 705 E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); 706 707 E6000SW_LOCK(sc); 708 ret = e6000sw_setvgroup(dev, vg); 709 E6000SW_UNLOCK(sc); 710 711 return (ret); 712 } 713 714 static int 715 e6000sw_getvgroup_wrapper(device_t dev, etherswitch_vlangroup_t *vg) 716 { 717 e6000sw_softc_t *sc; 718 int ret; 719 720 sc = device_get_softc(dev); 721 E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); 722 723 E6000SW_LOCK(sc); 724 ret = e6000sw_getvgroup(dev, vg); 725 E6000SW_UNLOCK(sc); 726 727 return (ret); 728 } 729 730 static __inline void 731 e6000sw_flush_port(e6000sw_softc_t *sc, int port) 732 { 733 uint32_t reg; 734 735 reg = e6000sw_readreg(sc, REG_PORT(port), PORT_VLAN_MAP); 736 reg &= ~PORT_VLAN_MAP_TABLE_MASK; 737 reg &= ~PORT_VLAN_MAP_FID_MASK; 738 e6000sw_writereg(sc, REG_PORT(port), PORT_VLAN_MAP, reg); 739 if (sc->vgroup[port] != E6000SW_PORT_NO_VGROUP) { 740 /* 741 * If port belonged somewhere, owner-group 742 * should have its entry removed. 743 */ 744 sc->members[sc->vgroup[port]] &= ~(1 << port); 745 sc->vgroup[port] = E6000SW_PORT_NO_VGROUP; 746 } 747 } 748 749 static __inline void 750 e6000sw_port_assign_vgroup(e6000sw_softc_t *sc, int port, int fid, int vgroup, 751 int members) 752 { 753 uint32_t reg; 754 755 reg = e6000sw_readreg(sc, REG_PORT(port), PORT_VLAN_MAP); 756 reg &= ~PORT_VLAN_MAP_TABLE_MASK; 757 reg &= ~PORT_VLAN_MAP_FID_MASK; 758 reg |= members & ~(1 << port); 759 reg |= (fid << PORT_VLAN_MAP_FID) & PORT_VLAN_MAP_FID_MASK; 760 e6000sw_writereg(sc, REG_PORT(port), PORT_VLAN_MAP, reg); 761 sc->vgroup[port] = vgroup; 762 } 763 764 static int 765 e6000sw_setvgroup(device_t dev, etherswitch_vlangroup_t *vg) 766 { 767 e6000sw_softc_t *sc; 768 int port, fid; 769 770 sc = device_get_softc(dev); 771 E6000SW_LOCK_ASSERT(sc, SA_XLOCKED); 772 773 if (vg->es_vlangroup >= E6000SW_NUM_VGROUPS) 774 return (EINVAL); 775 if (vg->es_member_ports != vg->es_untagged_ports) { 776 device_printf(dev, "Tagged ports not supported.\n"); 777 return (EINVAL); 778 } 779 780 vg->es_untagged_ports &= PORT_VLAN_MAP_TABLE_MASK; 781 fid = vg->es_vlangroup + 1; 782 for (port = 0; port < sc->num_ports; port++) { 783 if ((sc->members[vg->es_vlangroup] & (1 << port)) || 784 (vg->es_untagged_ports & (1 << port))) 785 e6000sw_flush_port(sc, port); 786 if (vg->es_untagged_ports & (1 << port)) 787 e6000sw_port_assign_vgroup(sc, port, fid, 788 vg->es_vlangroup, vg->es_untagged_ports); 789 } 790 sc->vid[vg->es_vlangroup] = vg->es_vid; 791 sc->members[vg->es_vlangroup] = vg->es_untagged_ports; 792 793 return (0); 794 } 795 796 static int 797 e6000sw_getvgroup(device_t dev, etherswitch_vlangroup_t *vg) 798 { 799 e6000sw_softc_t *sc; 800 801 sc = device_get_softc(dev); 802 E6000SW_LOCK_ASSERT(sc, SA_XLOCKED); 803 804 if (vg->es_vlangroup >= E6000SW_NUM_VGROUPS) 805 return (EINVAL); 806 vg->es_untagged_ports = vg->es_member_ports = 807 sc->members[vg->es_vlangroup]; 808 vg->es_vid = ETHERSWITCH_VID_VALID; 809 810 return (0); 811 } 812 813 static __inline struct mii_data* 814 e6000sw_miiforphy(e6000sw_softc_t *sc, unsigned int phy) 815 { 816 817 if (!e6000sw_is_phyport(sc, phy)) 818 return (NULL); 819 820 return (device_get_softc(sc->miibus[phy])); 821 } 822 823 static int 824 e6000sw_ifmedia_upd(struct ifnet *ifp) 825 { 826 e6000sw_softc_t *sc; 827 struct mii_data *mii; 828 829 sc = ifp->if_softc; 830 mii = e6000sw_miiforphy(sc, ifp->if_dunit); 831 if (mii == NULL) 832 return (ENXIO); 833 mii_mediachg(mii); 834 835 return (0); 836 } 837 838 static void 839 e6000sw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 840 { 841 e6000sw_softc_t *sc; 842 struct mii_data *mii; 843 844 sc = ifp->if_softc; 845 mii = e6000sw_miiforphy(sc, ifp->if_dunit); 846 847 if (mii == NULL) 848 return; 849 850 mii_pollstat(mii); 851 ifmr->ifm_active = mii->mii_media_active; 852 ifmr->ifm_status = mii->mii_media_status; 853 } 854 855 static int 856 e6000sw_smi_waitready(e6000sw_softc_t *sc, int phy) 857 { 858 int i; 859 860 for (i = 0; i < E6000SW_SMI_TIMEOUT; i++) { 861 if ((MDIO_READ(sc->dev, phy, SMI_CMD) & SMI_CMD_BUSY) == 0) 862 return (0); 863 DELAY(1); 864 } 865 866 return (1); 867 } 868 869 static __inline uint32_t 870 e6000sw_readreg(e6000sw_softc_t *sc, int addr, int reg) 871 { 872 873 E6000SW_LOCK_ASSERT(sc, SA_XLOCKED); 874 875 if (!sc->multi_chip) 876 return (MDIO_READ(sc->dev, addr, reg) & 0xffff); 877 878 if (e6000sw_smi_waitready(sc, sc->sw_addr)) { 879 printf("e6000sw: readreg timeout\n"); 880 return (0xffff); 881 } 882 MDIO_WRITE(sc->dev, sc->sw_addr, SMI_CMD, 883 SMI_CMD_OP_READ | (addr << 5) | reg); 884 if (e6000sw_smi_waitready(sc, sc->sw_addr)) { 885 printf("e6000sw: readreg timeout\n"); 886 return (0xffff); 887 } 888 889 return (MDIO_READ(sc->dev, sc->sw_addr, SMI_DATA) & 0xffff); 890 } 891 892 static __inline void 893 e6000sw_writereg(e6000sw_softc_t *sc, int addr, int reg, int val) 894 { 895 896 E6000SW_LOCK_ASSERT(sc, SA_XLOCKED); 897 898 if (!sc->multi_chip) { 899 MDIO_WRITE(sc->dev, addr, reg, val); 900 return; 901 } 902 903 if (e6000sw_smi_waitready(sc, sc->sw_addr)) { 904 printf("e6000sw: readreg timeout\n"); 905 return; 906 } 907 MDIO_WRITE(sc->dev, sc->sw_addr, SMI_DATA, val); 908 MDIO_WRITE(sc->dev, sc->sw_addr, SMI_CMD, 909 SMI_CMD_OP_WRITE | (addr << 5) | reg); 910 if (e6000sw_smi_waitready(sc, sc->sw_addr)) { 911 printf("e6000sw: readreg timeout\n"); 912 return; 913 } 914 } 915 916 static __inline bool 917 e6000sw_is_cpuport(e6000sw_softc_t *sc, int port) 918 { 919 920 return ((sc->cpuports_mask & (1 << port)) ? true : false); 921 } 922 923 static __inline bool 924 e6000sw_is_fixedport(e6000sw_softc_t *sc, int port) 925 { 926 927 return ((sc->fixed_mask & (1 << port)) ? true : false); 928 } 929 930 static __inline bool 931 e6000sw_is_phyport(e6000sw_softc_t *sc, int port) 932 { 933 uint32_t phy_mask; 934 phy_mask = ~(sc->fixed_mask | sc->cpuports_mask); 935 936 return ((phy_mask & (1 << port)) ? true : false); 937 } 938 939 static __inline int 940 e6000sw_set_pvid(e6000sw_softc_t *sc, int port, int pvid) 941 { 942 943 e6000sw_writereg(sc, REG_PORT(port), PORT_VID, pvid & 944 PORT_VID_DEF_VID_MASK); 945 946 return (0); 947 } 948 949 static __inline int 950 e6000sw_get_pvid(e6000sw_softc_t *sc, int port, int *pvid) 951 { 952 953 if (pvid == NULL) 954 return (ENXIO); 955 956 *pvid = e6000sw_readreg(sc, REG_PORT(port), PORT_VID) & 957 PORT_VID_DEF_VID_MASK; 958 959 return (0); 960 } 961 962 /* 963 * Convert port status to ifmedia. 964 */ 965 static void 966 e6000sw_update_ifmedia(uint16_t portstatus, u_int *media_status, u_int *media_active) 967 { 968 *media_active = IFM_ETHER; 969 *media_status = IFM_AVALID; 970 971 if ((portstatus & PORT_STATUS_LINK_MASK) != 0) 972 *media_status |= IFM_ACTIVE; 973 else { 974 *media_active |= IFM_NONE; 975 return; 976 } 977 978 switch (portstatus & PORT_STATUS_SPEED_MASK) { 979 case PORT_STATUS_SPEED_10: 980 *media_active |= IFM_10_T; 981 break; 982 case PORT_STATUS_SPEED_100: 983 *media_active |= IFM_100_TX; 984 break; 985 case PORT_STATUS_SPEED_1000: 986 *media_active |= IFM_1000_T; 987 break; 988 } 989 990 if ((portstatus & PORT_STATUS_DUPLEX_MASK) == 0) 991 *media_active |= IFM_FDX; 992 else 993 *media_active |= IFM_HDX; 994 } 995 996 static void 997 e6000sw_tick (void *arg) 998 { 999 e6000sw_softc_t *sc; 1000 struct mii_data *mii; 1001 struct mii_softc *miisc; 1002 uint16_t portstatus; 1003 int port; 1004 1005 sc = arg; 1006 1007 E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); 1008 1009 for (;;) { 1010 E6000SW_LOCK(sc); 1011 for (port = 0; port < sc->num_ports; port++) { 1012 /* Tick only on PHY ports */ 1013 if (!e6000sw_is_phyport(sc, port)) 1014 continue; 1015 1016 mii = e6000sw_miiforphy(sc, port); 1017 if (mii == NULL) 1018 continue; 1019 1020 portstatus = e6000sw_readreg(sc, REG_PORT(port), 1021 PORT_STATUS); 1022 1023 e6000sw_update_ifmedia(portstatus, 1024 &mii->mii_media_status, &mii->mii_media_active); 1025 1026 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) { 1027 if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) 1028 != miisc->mii_inst) 1029 continue; 1030 mii_phy_update(miisc, MII_POLLSTAT); 1031 } 1032 } 1033 E6000SW_UNLOCK(sc); 1034 pause("e6000sw tick", 1000); 1035 } 1036 } 1037 1038 static void 1039 e6000sw_setup(device_t dev, e6000sw_softc_t *sc) 1040 { 1041 uint16_t atu_ctrl, atu_age; 1042 1043 /* Set aging time */ 1044 e6000sw_writereg(sc, REG_GLOBAL, ATU_CONTROL, 1045 (E6000SW_DEFAULT_AGETIME << ATU_CONTROL_AGETIME) | 1046 (1 << ATU_CONTROL_LEARN2ALL)); 1047 1048 /* Send all with specific mac address to cpu port */ 1049 e6000sw_writereg(sc, REG_GLOBAL2, MGMT_EN_2x, MGMT_EN_ALL); 1050 e6000sw_writereg(sc, REG_GLOBAL2, MGMT_EN_0x, MGMT_EN_ALL); 1051 1052 /* Disable Remote Management */ 1053 e6000sw_writereg(sc, REG_GLOBAL, SWITCH_GLOBAL_CONTROL2, 0); 1054 1055 /* Disable loopback filter and flow control messages */ 1056 e6000sw_writereg(sc, REG_GLOBAL2, SWITCH_MGMT, 1057 SWITCH_MGMT_PRI_MASK | 1058 (1 << SWITCH_MGMT_RSVD2CPU) | 1059 SWITCH_MGMT_FC_PRI_MASK | 1060 (1 << SWITCH_MGMT_FORCEFLOW)); 1061 1062 e6000sw_atu_flush(dev, sc, NO_OPERATION); 1063 e6000sw_atu_mac_table(dev, sc, NULL, NO_OPERATION); 1064 e6000sw_set_atustat(dev, sc, 0, COUNT_ALL); 1065 1066 /* Set ATU AgeTime to 15 seconds */ 1067 atu_age = 1; 1068 1069 atu_ctrl = e6000sw_readreg(sc, REG_GLOBAL, ATU_CONTROL); 1070 1071 /* Set new AgeTime field */ 1072 atu_ctrl &= ~ATU_CONTROL_AGETIME_MASK; 1073 e6000sw_writereg(sc, REG_GLOBAL, ATU_CONTROL, atu_ctrl | 1074 (atu_age << ATU_CONTROL_AGETIME)); 1075 } 1076 1077 static void 1078 e6000sw_port_vlan_conf(e6000sw_softc_t *sc) 1079 { 1080 int port, ret; 1081 device_t dev; 1082 1083 dev = sc->dev; 1084 /* Disable all ports */ 1085 for (port = 0; port < sc->num_ports; port++) { 1086 ret = e6000sw_readreg(sc, REG_PORT(port), PORT_CONTROL); 1087 e6000sw_writereg(sc, REG_PORT(port), PORT_CONTROL, 1088 (ret & ~PORT_CONTROL_ENABLE)); 1089 } 1090 1091 /* Set port priority */ 1092 for (port = 0; port < sc->num_ports; port++) { 1093 ret = e6000sw_readreg(sc, REG_PORT(port), PORT_VID); 1094 ret &= ~PORT_VID_PRIORITY_MASK; 1095 e6000sw_writereg(sc, REG_PORT(port), PORT_VID, ret); 1096 } 1097 1098 /* Set VID map */ 1099 for (port = 0; port < sc->num_ports; port++) { 1100 ret = e6000sw_readreg(sc, REG_PORT(port), PORT_VID); 1101 ret &= ~PORT_VID_DEF_VID_MASK; 1102 ret |= (port + 1); 1103 e6000sw_writereg(sc, REG_PORT(port), PORT_VID, ret); 1104 } 1105 1106 /* Enable all ports */ 1107 for (port = 0; port < sc->num_ports; port++) { 1108 ret = e6000sw_readreg(sc, REG_PORT(port), PORT_CONTROL); 1109 e6000sw_writereg(sc, REG_PORT(port), PORT_CONTROL, (ret | 1110 PORT_CONTROL_ENABLE)); 1111 } 1112 } 1113 1114 static void 1115 e6000sw_set_atustat(device_t dev, e6000sw_softc_t *sc, int bin, int flag) 1116 { 1117 uint16_t ret; 1118 1119 ret = e6000sw_readreg(sc, REG_GLOBAL2, ATU_STATS); 1120 e6000sw_writereg(sc, REG_GLOBAL2, ATU_STATS, (bin << ATU_STATS_BIN ) | 1121 (flag << ATU_STATS_FLAG)); 1122 } 1123 1124 static int 1125 e6000sw_atu_mac_table(device_t dev, e6000sw_softc_t *sc, struct atu_opt *atu, 1126 int flag) 1127 { 1128 uint16_t ret_opt; 1129 uint16_t ret_data; 1130 int retries; 1131 1132 if (flag == NO_OPERATION) 1133 return (0); 1134 else if ((flag & (LOAD_FROM_FIB | PURGE_FROM_FIB | GET_NEXT_IN_FIB | 1135 GET_VIOLATION_DATA | CLEAR_VIOLATION_DATA)) == 0) { 1136 device_printf(dev, "Wrong Opcode for ATU operation\n"); 1137 return (EINVAL); 1138 } 1139 1140 ret_opt = e6000sw_readreg(sc, REG_GLOBAL, ATU_OPERATION); 1141 1142 if (ret_opt & ATU_UNIT_BUSY) { 1143 device_printf(dev, "ATU unit is busy, cannot access" 1144 "register\n"); 1145 return (EBUSY); 1146 } else { 1147 if(flag & LOAD_FROM_FIB) { 1148 ret_data = e6000sw_readreg(sc, REG_GLOBAL, ATU_DATA); 1149 e6000sw_writereg(sc, REG_GLOBAL2, ATU_DATA, (ret_data & 1150 ~ENTRY_STATE)); 1151 } 1152 e6000sw_writereg(sc, REG_GLOBAL, ATU_MAC_ADDR01, atu->mac_01); 1153 e6000sw_writereg(sc, REG_GLOBAL, ATU_MAC_ADDR23, atu->mac_23); 1154 e6000sw_writereg(sc, REG_GLOBAL, ATU_MAC_ADDR45, atu->mac_45); 1155 e6000sw_writereg(sc, REG_GLOBAL, ATU_FID, atu->fid); 1156 1157 e6000sw_writereg(sc, REG_GLOBAL, ATU_OPERATION, (ret_opt | 1158 ATU_UNIT_BUSY | flag)); 1159 1160 retries = E6000SW_RETRIES; 1161 while (--retries & (e6000sw_readreg(sc, REG_GLOBAL, 1162 ATU_OPERATION) & ATU_UNIT_BUSY)) 1163 DELAY(1); 1164 1165 if (retries == 0) 1166 device_printf(dev, "Timeout while flushing\n"); 1167 else if (flag & GET_NEXT_IN_FIB) { 1168 atu->mac_01 = e6000sw_readreg(sc, REG_GLOBAL, 1169 ATU_MAC_ADDR01); 1170 atu->mac_23 = e6000sw_readreg(sc, REG_GLOBAL, 1171 ATU_MAC_ADDR23); 1172 atu->mac_45 = e6000sw_readreg(sc, REG_GLOBAL, 1173 ATU_MAC_ADDR45); 1174 } 1175 } 1176 1177 return (0); 1178 } 1179 1180 static int 1181 e6000sw_atu_flush(device_t dev, e6000sw_softc_t *sc, int flag) 1182 { 1183 uint16_t ret; 1184 int retries; 1185 1186 if (flag == NO_OPERATION) 1187 return (0); 1188 1189 ret = e6000sw_readreg(sc, REG_GLOBAL, ATU_OPERATION); 1190 if (ret & ATU_UNIT_BUSY) { 1191 device_printf(dev, "Atu unit is busy, cannot flush\n"); 1192 return (EBUSY); 1193 } else { 1194 e6000sw_writereg(sc, REG_GLOBAL, ATU_OPERATION, (ret | 1195 ATU_UNIT_BUSY | flag)); 1196 retries = E6000SW_RETRIES; 1197 while (--retries & (e6000sw_readreg(sc, REG_GLOBAL, 1198 ATU_OPERATION) & ATU_UNIT_BUSY)) 1199 DELAY(1); 1200 1201 if (retries == 0) 1202 device_printf(dev, "Timeout while flushing\n"); 1203 } 1204 1205 return (0); 1206 } 1207