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