1 /*- 2 * Copyright (c) 2010-2011 Solarflare Communications, Inc. 3 * All rights reserved. 4 * 5 * This software was developed in part by Philip Paeps under contract for 6 * Solarflare Communications, Inc. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/types.h> 34 #include <sys/limits.h> 35 #include <net/ethernet.h> 36 #include <net/if_dl.h> 37 38 #include "common/efx.h" 39 40 #include "sfxge.h" 41 42 static int 43 sfxge_mac_stat_update(struct sfxge_softc *sc) 44 { 45 struct sfxge_port *port = &sc->port; 46 efsys_mem_t *esmp = &(port->mac_stats.dma_buf); 47 clock_t now; 48 unsigned int count; 49 int rc; 50 51 SFXGE_PORT_LOCK_ASSERT_OWNED(port); 52 53 if (__predict_false(port->init_state != SFXGE_PORT_STARTED)) { 54 rc = 0; 55 goto out; 56 } 57 58 now = ticks; 59 if (now - port->mac_stats.update_time < hz) { 60 rc = 0; 61 goto out; 62 } 63 64 port->mac_stats.update_time = now; 65 66 /* If we're unlucky enough to read statistics wduring the DMA, wait 67 * up to 10ms for it to finish (typically takes <500us) */ 68 for (count = 0; count < 100; ++count) { 69 EFSYS_PROBE1(wait, unsigned int, count); 70 71 /* Synchronize the DMA memory for reading */ 72 bus_dmamap_sync(esmp->esm_tag, esmp->esm_map, 73 BUS_DMASYNC_POSTREAD); 74 75 /* Try to update the cached counters */ 76 if ((rc = efx_mac_stats_update(sc->enp, esmp, 77 port->mac_stats.decode_buf, NULL)) != EAGAIN) 78 goto out; 79 80 DELAY(100); 81 } 82 83 rc = ETIMEDOUT; 84 out: 85 return (rc); 86 } 87 88 uint64_t 89 sfxge_get_counter(struct ifnet *ifp, ift_counter c) 90 { 91 struct sfxge_softc *sc = ifp->if_softc; 92 uint64_t *mac_stats; 93 uint64_t val; 94 95 SFXGE_PORT_LOCK(&sc->port); 96 97 /* Ignore error and use old values */ 98 (void)sfxge_mac_stat_update(sc); 99 100 mac_stats = (uint64_t *)sc->port.mac_stats.decode_buf; 101 102 switch (c) { 103 case IFCOUNTER_IPACKETS: 104 val = mac_stats[EFX_MAC_RX_PKTS]; 105 break; 106 case IFCOUNTER_IERRORS: 107 val = mac_stats[EFX_MAC_RX_ERRORS]; 108 break; 109 case IFCOUNTER_OPACKETS: 110 val = mac_stats[EFX_MAC_TX_PKTS]; 111 break; 112 case IFCOUNTER_OERRORS: 113 val = mac_stats[EFX_MAC_TX_ERRORS]; 114 break; 115 case IFCOUNTER_COLLISIONS: 116 val = mac_stats[EFX_MAC_TX_SGL_COL_PKTS] + 117 mac_stats[EFX_MAC_TX_MULT_COL_PKTS] + 118 mac_stats[EFX_MAC_TX_EX_COL_PKTS] + 119 mac_stats[EFX_MAC_TX_LATE_COL_PKTS]; 120 break; 121 case IFCOUNTER_IBYTES: 122 val = mac_stats[EFX_MAC_RX_OCTETS]; 123 break; 124 case IFCOUNTER_OBYTES: 125 val = mac_stats[EFX_MAC_TX_OCTETS]; 126 break; 127 case IFCOUNTER_OMCASTS: 128 val = mac_stats[EFX_MAC_TX_MULTICST_PKTS] + 129 mac_stats[EFX_MAC_TX_BRDCST_PKTS]; 130 break; 131 case IFCOUNTER_OQDROPS: 132 SFXGE_PORT_UNLOCK(&sc->port); 133 return (sfxge_tx_get_drops(sc)); 134 case IFCOUNTER_IMCASTS: 135 /* if_imcasts is maintained in net/if_ethersubr.c */ 136 case IFCOUNTER_IQDROPS: 137 /* if_iqdrops is maintained in net/if_ethersubr.c */ 138 case IFCOUNTER_NOPROTO: 139 /* if_noproto is maintained in net/if_ethersubr.c */ 140 default: 141 SFXGE_PORT_UNLOCK(&sc->port); 142 return (if_get_counter_default(ifp, c)); 143 } 144 145 SFXGE_PORT_UNLOCK(&sc->port); 146 147 return (val); 148 } 149 150 static int 151 sfxge_mac_stat_handler(SYSCTL_HANDLER_ARGS) 152 { 153 struct sfxge_softc *sc = arg1; 154 unsigned int id = arg2; 155 int rc; 156 uint64_t val; 157 158 SFXGE_PORT_LOCK(&sc->port); 159 if ((rc = sfxge_mac_stat_update(sc)) == 0) 160 val = ((uint64_t *)sc->port.mac_stats.decode_buf)[id]; 161 SFXGE_PORT_UNLOCK(&sc->port); 162 163 if (rc == 0) 164 rc = SYSCTL_OUT(req, &val, sizeof(val)); 165 return (rc); 166 } 167 168 static void 169 sfxge_mac_stat_init(struct sfxge_softc *sc) 170 { 171 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev); 172 struct sysctl_oid_list *stat_list; 173 unsigned int id; 174 const char *name; 175 176 stat_list = SYSCTL_CHILDREN(sc->stats_node); 177 178 /* Initialise the named stats */ 179 for (id = 0; id < EFX_MAC_NSTATS; id++) { 180 name = efx_mac_stat_name(sc->enp, id); 181 SYSCTL_ADD_PROC( 182 ctx, stat_list, 183 OID_AUTO, name, CTLTYPE_U64|CTLFLAG_RD, 184 sc, id, sfxge_mac_stat_handler, "Q", 185 ""); 186 } 187 } 188 189 #ifdef SFXGE_HAVE_PAUSE_MEDIAOPTS 190 191 static unsigned int 192 sfxge_port_wanted_fc(struct sfxge_softc *sc) 193 { 194 struct ifmedia_entry *ifm = sc->media.ifm_cur; 195 196 if (ifm->ifm_media == (IFM_ETHER | IFM_AUTO)) 197 return (EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE); 198 return (((ifm->ifm_media & IFM_ETH_RXPAUSE) ? EFX_FCNTL_RESPOND : 0) | 199 ((ifm->ifm_media & IFM_ETH_TXPAUSE) ? EFX_FCNTL_GENERATE : 0)); 200 } 201 202 static unsigned int 203 sfxge_port_link_fc_ifm(struct sfxge_softc *sc) 204 { 205 unsigned int wanted_fc, link_fc; 206 207 efx_mac_fcntl_get(sc->enp, &wanted_fc, &link_fc); 208 return ((link_fc & EFX_FCNTL_RESPOND) ? IFM_ETH_RXPAUSE : 0) | 209 ((link_fc & EFX_FCNTL_GENERATE) ? IFM_ETH_TXPAUSE : 0); 210 } 211 212 #else /* !SFXGE_HAVE_PAUSE_MEDIAOPTS */ 213 214 static unsigned int 215 sfxge_port_wanted_fc(struct sfxge_softc *sc) 216 { 217 return (sc->port.wanted_fc); 218 } 219 220 static unsigned int 221 sfxge_port_link_fc_ifm(struct sfxge_softc *sc) 222 { 223 return (0); 224 } 225 226 static int 227 sfxge_port_wanted_fc_handler(SYSCTL_HANDLER_ARGS) 228 { 229 struct sfxge_softc *sc; 230 struct sfxge_port *port; 231 unsigned int fcntl; 232 int error; 233 234 sc = arg1; 235 port = &sc->port; 236 237 if (req->newptr != NULL) { 238 if ((error = SYSCTL_IN(req, &fcntl, sizeof(fcntl))) != 0) 239 return (error); 240 241 SFXGE_PORT_LOCK(port); 242 243 if (port->wanted_fc != fcntl) { 244 if (__predict_false(port->init_state == SFXGE_PORT_STARTED)) 245 error = efx_mac_fcntl_set(sc->enp, 246 port->wanted_fc, 247 B_TRUE); 248 if (error == 0) 249 port->wanted_fc = fcntl; 250 } 251 252 SFXGE_PORT_UNLOCK(port); 253 } else { 254 SFXGE_PORT_LOCK(port); 255 fcntl = port->wanted_fc; 256 SFXGE_PORT_UNLOCK(port); 257 258 error = SYSCTL_OUT(req, &fcntl, sizeof(fcntl)); 259 } 260 261 return (error); 262 } 263 264 static int 265 sfxge_port_link_fc_handler(SYSCTL_HANDLER_ARGS) 266 { 267 struct sfxge_softc *sc; 268 struct sfxge_port *port; 269 unsigned int wanted_fc, link_fc; 270 271 sc = arg1; 272 port = &sc->port; 273 274 SFXGE_PORT_LOCK(port); 275 if (__predict_true(port->init_state == SFXGE_PORT_STARTED) && 276 SFXGE_LINK_UP(sc)) 277 efx_mac_fcntl_get(sc->enp, &wanted_fc, &link_fc); 278 else 279 link_fc = 0; 280 SFXGE_PORT_UNLOCK(port); 281 282 return (SYSCTL_OUT(req, &link_fc, sizeof(link_fc))); 283 } 284 285 #endif /* SFXGE_HAVE_PAUSE_MEDIAOPTS */ 286 287 static const uint64_t sfxge_link_baudrate[EFX_LINK_NMODES] = { 288 [EFX_LINK_10HDX] = IF_Mbps(10), 289 [EFX_LINK_10FDX] = IF_Mbps(10), 290 [EFX_LINK_100HDX] = IF_Mbps(100), 291 [EFX_LINK_100FDX] = IF_Mbps(100), 292 [EFX_LINK_1000HDX] = IF_Gbps(1), 293 [EFX_LINK_1000FDX] = IF_Gbps(1), 294 [EFX_LINK_10000FDX] = IF_Gbps(10), 295 }; 296 297 void 298 sfxge_mac_link_update(struct sfxge_softc *sc, efx_link_mode_t mode) 299 { 300 struct sfxge_port *port; 301 int link_state; 302 303 port = &sc->port; 304 305 if (port->link_mode == mode) 306 return; 307 308 port->link_mode = mode; 309 310 /* Push link state update to the OS */ 311 link_state = (port->link_mode != EFX_LINK_DOWN ? 312 LINK_STATE_UP : LINK_STATE_DOWN); 313 sc->ifnet->if_baudrate = sfxge_link_baudrate[port->link_mode]; 314 if_link_state_change(sc->ifnet, link_state); 315 } 316 317 static void 318 sfxge_mac_poll_work(void *arg, int npending) 319 { 320 struct sfxge_softc *sc; 321 efx_nic_t *enp; 322 struct sfxge_port *port; 323 efx_link_mode_t mode; 324 325 sc = (struct sfxge_softc *)arg; 326 enp = sc->enp; 327 port = &sc->port; 328 329 SFXGE_PORT_LOCK(port); 330 331 if (__predict_false(port->init_state != SFXGE_PORT_STARTED)) 332 goto done; 333 334 /* This may sleep waiting for MCDI completion */ 335 (void)efx_port_poll(enp, &mode); 336 sfxge_mac_link_update(sc, mode); 337 338 done: 339 SFXGE_PORT_UNLOCK(port); 340 } 341 342 static int 343 sfxge_mac_filter_set_locked(struct sfxge_softc *sc) 344 { 345 unsigned int bucket[EFX_MAC_HASH_BITS]; 346 struct ifnet *ifp = sc->ifnet; 347 struct ifmultiaddr *ifma; 348 struct sockaddr_dl *sa; 349 efx_nic_t *enp = sc->enp; 350 unsigned int index; 351 int rc; 352 353 /* Set promisc-unicast and broadcast filter bits */ 354 if ((rc = efx_mac_filter_set(enp, !!(ifp->if_flags & IFF_PROMISC), 355 B_TRUE)) != 0) 356 return (rc); 357 358 /* Set multicast hash filter */ 359 if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) { 360 for (index = 0; index < EFX_MAC_HASH_BITS; index++) 361 bucket[index] = 1; 362 } else { 363 /* Broadcast frames also go through the multicast 364 * filter, and the broadcast address hashes to 365 * 0xff. */ 366 bucket[0xff] = 1; 367 368 if_maddr_rlock(ifp); 369 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 370 if (ifma->ifma_addr->sa_family == AF_LINK) { 371 sa = (struct sockaddr_dl *)ifma->ifma_addr; 372 index = ether_crc32_le(LLADDR(sa), 6) & 0xff; 373 bucket[index] = 1; 374 } 375 } 376 if_maddr_runlock(ifp); 377 } 378 return (efx_mac_hash_set(enp, bucket)); 379 } 380 381 int 382 sfxge_mac_filter_set(struct sfxge_softc *sc) 383 { 384 struct sfxge_port *port = &sc->port; 385 int rc; 386 387 SFXGE_PORT_LOCK(port); 388 /* 389 * The function may be called without softc_lock held in the 390 * case of SIOCADDMULTI and SIOCDELMULTI ioctls. ioctl handler 391 * checks IFF_DRV_RUNNING flag which implies port started, but 392 * it is not guaranteed to remain. softc_lock shared lock can't 393 * be held in the case of these ioctls processing, since it 394 * results in failure where kernel complains that non-sleepable 395 * lock is held in sleeping thread. Both problems are repeatable 396 * on LAG with LACP proto bring up. 397 */ 398 if (__predict_true(port->init_state == SFXGE_PORT_STARTED)) 399 rc = sfxge_mac_filter_set_locked(sc); 400 else 401 rc = 0; 402 SFXGE_PORT_UNLOCK(port); 403 return (rc); 404 } 405 406 void 407 sfxge_port_stop(struct sfxge_softc *sc) 408 { 409 struct sfxge_port *port; 410 efx_nic_t *enp; 411 412 port = &sc->port; 413 enp = sc->enp; 414 415 SFXGE_PORT_LOCK(port); 416 417 KASSERT(port->init_state == SFXGE_PORT_STARTED, 418 ("port not started")); 419 420 port->init_state = SFXGE_PORT_INITIALIZED; 421 422 port->mac_stats.update_time = 0; 423 424 /* This may call MCDI */ 425 (void)efx_mac_drain(enp, B_TRUE); 426 427 (void)efx_mac_stats_periodic(enp, &port->mac_stats.dma_buf, 0, B_FALSE); 428 429 port->link_mode = EFX_LINK_UNKNOWN; 430 431 /* Destroy the common code port object. */ 432 efx_port_fini(sc->enp); 433 434 SFXGE_PORT_UNLOCK(port); 435 } 436 437 int 438 sfxge_port_start(struct sfxge_softc *sc) 439 { 440 uint8_t mac_addr[ETHER_ADDR_LEN]; 441 struct ifnet *ifp = sc->ifnet; 442 struct sfxge_port *port; 443 efx_nic_t *enp; 444 size_t pdu; 445 int rc; 446 447 port = &sc->port; 448 enp = sc->enp; 449 450 SFXGE_PORT_LOCK(port); 451 452 KASSERT(port->init_state == SFXGE_PORT_INITIALIZED, 453 ("port not initialized")); 454 455 /* Initialize the port object in the common code. */ 456 if ((rc = efx_port_init(sc->enp)) != 0) 457 goto fail; 458 459 /* Set the SDU */ 460 pdu = EFX_MAC_PDU(ifp->if_mtu); 461 if ((rc = efx_mac_pdu_set(enp, pdu)) != 0) 462 goto fail2; 463 464 if ((rc = efx_mac_fcntl_set(enp, sfxge_port_wanted_fc(sc), B_TRUE)) 465 != 0) 466 goto fail2; 467 468 /* Set the unicast address */ 469 if_addr_rlock(ifp); 470 bcopy(LLADDR((struct sockaddr_dl *)ifp->if_addr->ifa_addr), 471 mac_addr, sizeof(mac_addr)); 472 if_addr_runlock(ifp); 473 if ((rc = efx_mac_addr_set(enp, mac_addr)) != 0) 474 goto fail; 475 476 sfxge_mac_filter_set_locked(sc); 477 478 /* Update MAC stats by DMA every second */ 479 if ((rc = efx_mac_stats_periodic(enp, &port->mac_stats.dma_buf, 480 1000, B_FALSE)) != 0) 481 goto fail2; 482 483 if ((rc = efx_mac_drain(enp, B_FALSE)) != 0) 484 goto fail3; 485 486 if ((rc = efx_phy_adv_cap_set(sc->enp, sc->media.ifm_cur->ifm_data)) 487 != 0) 488 goto fail4; 489 490 port->init_state = SFXGE_PORT_STARTED; 491 492 /* Single poll in case there were missing initial events */ 493 SFXGE_PORT_UNLOCK(port); 494 sfxge_mac_poll_work(sc, 0); 495 496 return (0); 497 498 fail4: 499 (void)efx_mac_drain(enp, B_TRUE); 500 fail3: 501 (void)efx_mac_stats_periodic(enp, &port->mac_stats.dma_buf, 502 0, B_FALSE); 503 fail2: 504 efx_port_fini(sc->enp); 505 fail: 506 SFXGE_PORT_UNLOCK(port); 507 508 return (rc); 509 } 510 511 static int 512 sfxge_phy_stat_update(struct sfxge_softc *sc) 513 { 514 struct sfxge_port *port = &sc->port; 515 efsys_mem_t *esmp = &port->phy_stats.dma_buf; 516 clock_t now; 517 unsigned int count; 518 int rc; 519 520 SFXGE_PORT_LOCK_ASSERT_OWNED(port); 521 522 if (__predict_false(port->init_state != SFXGE_PORT_STARTED)) { 523 rc = 0; 524 goto out; 525 } 526 527 now = ticks; 528 if (now - port->phy_stats.update_time < hz) { 529 rc = 0; 530 goto out; 531 } 532 533 port->phy_stats.update_time = now; 534 535 /* If we're unlucky enough to read statistics wduring the DMA, wait 536 * up to 10ms for it to finish (typically takes <500us) */ 537 for (count = 0; count < 100; ++count) { 538 EFSYS_PROBE1(wait, unsigned int, count); 539 540 /* Synchronize the DMA memory for reading */ 541 bus_dmamap_sync(esmp->esm_tag, esmp->esm_map, 542 BUS_DMASYNC_POSTREAD); 543 544 /* Try to update the cached counters */ 545 if ((rc = efx_phy_stats_update(sc->enp, esmp, 546 port->phy_stats.decode_buf)) != EAGAIN) 547 goto out; 548 549 DELAY(100); 550 } 551 552 rc = ETIMEDOUT; 553 out: 554 return (rc); 555 } 556 557 static int 558 sfxge_phy_stat_handler(SYSCTL_HANDLER_ARGS) 559 { 560 struct sfxge_softc *sc = arg1; 561 unsigned int id = arg2; 562 int rc; 563 uint32_t val; 564 565 SFXGE_PORT_LOCK(&sc->port); 566 if ((rc = sfxge_phy_stat_update(sc)) == 0) 567 val = ((uint32_t *)sc->port.phy_stats.decode_buf)[id]; 568 SFXGE_PORT_UNLOCK(&sc->port); 569 570 if (rc == 0) 571 rc = SYSCTL_OUT(req, &val, sizeof(val)); 572 return (rc); 573 } 574 575 static void 576 sfxge_phy_stat_init(struct sfxge_softc *sc) 577 { 578 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev); 579 struct sysctl_oid_list *stat_list; 580 unsigned int id; 581 const char *name; 582 uint64_t stat_mask = efx_nic_cfg_get(sc->enp)->enc_phy_stat_mask; 583 584 stat_list = SYSCTL_CHILDREN(sc->stats_node); 585 586 /* Initialise the named stats */ 587 for (id = 0; id < EFX_PHY_NSTATS; id++) { 588 if (!(stat_mask & ((uint64_t)1 << id))) 589 continue; 590 name = efx_phy_stat_name(sc->enp, id); 591 SYSCTL_ADD_PROC( 592 ctx, stat_list, 593 OID_AUTO, name, CTLTYPE_UINT|CTLFLAG_RD, 594 sc, id, sfxge_phy_stat_handler, 595 id == EFX_PHY_STAT_OUI ? "IX" : "IU", 596 ""); 597 } 598 } 599 600 void 601 sfxge_port_fini(struct sfxge_softc *sc) 602 { 603 struct sfxge_port *port; 604 efsys_mem_t *esmp; 605 606 port = &sc->port; 607 esmp = &port->mac_stats.dma_buf; 608 609 KASSERT(port->init_state == SFXGE_PORT_INITIALIZED, 610 ("Port not initialized")); 611 612 port->init_state = SFXGE_PORT_UNINITIALIZED; 613 614 port->link_mode = EFX_LINK_UNKNOWN; 615 616 /* Finish with PHY DMA memory */ 617 sfxge_dma_free(&port->phy_stats.dma_buf); 618 free(port->phy_stats.decode_buf, M_SFXGE); 619 620 sfxge_dma_free(esmp); 621 free(port->mac_stats.decode_buf, M_SFXGE); 622 623 SFXGE_PORT_LOCK_DESTROY(port); 624 625 port->sc = NULL; 626 } 627 628 int 629 sfxge_port_init(struct sfxge_softc *sc) 630 { 631 struct sfxge_port *port; 632 struct sysctl_ctx_list *sysctl_ctx; 633 struct sysctl_oid *sysctl_tree; 634 efsys_mem_t *mac_stats_buf, *phy_stats_buf; 635 int rc; 636 637 port = &sc->port; 638 mac_stats_buf = &port->mac_stats.dma_buf; 639 phy_stats_buf = &port->phy_stats.dma_buf; 640 641 KASSERT(port->init_state == SFXGE_PORT_UNINITIALIZED, 642 ("Port already initialized")); 643 644 port->sc = sc; 645 646 SFXGE_PORT_LOCK_INIT(port, device_get_nameunit(sc->dev)); 647 648 port->phy_stats.decode_buf = malloc(EFX_PHY_NSTATS * sizeof(uint32_t), 649 M_SFXGE, M_WAITOK | M_ZERO); 650 if ((rc = sfxge_dma_alloc(sc, EFX_PHY_STATS_SIZE, phy_stats_buf)) != 0) 651 goto fail; 652 sfxge_phy_stat_init(sc); 653 654 sysctl_ctx = device_get_sysctl_ctx(sc->dev); 655 sysctl_tree = device_get_sysctl_tree(sc->dev); 656 657 #ifndef SFXGE_HAVE_PAUSE_MEDIAOPTS 658 /* If flow control cannot be configured or reported through 659 * ifmedia, provide sysctls for it. */ 660 port->wanted_fc = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 661 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 662 "wanted_fc", CTLTYPE_UINT|CTLFLAG_RW, sc, 0, 663 sfxge_port_wanted_fc_handler, "IU", "wanted flow control mode"); 664 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 665 "link_fc", CTLTYPE_UINT|CTLFLAG_RD, sc, 0, 666 sfxge_port_link_fc_handler, "IU", "link flow control mode"); 667 #endif 668 669 port->mac_stats.decode_buf = malloc(EFX_MAC_NSTATS * sizeof(uint64_t), 670 M_SFXGE, M_WAITOK | M_ZERO); 671 if ((rc = sfxge_dma_alloc(sc, EFX_MAC_STATS_SIZE, mac_stats_buf)) != 0) 672 goto fail2; 673 sfxge_mac_stat_init(sc); 674 675 port->init_state = SFXGE_PORT_INITIALIZED; 676 677 return (0); 678 679 fail2: 680 free(port->mac_stats.decode_buf, M_SFXGE); 681 sfxge_dma_free(phy_stats_buf); 682 fail: 683 free(port->phy_stats.decode_buf, M_SFXGE); 684 SFXGE_PORT_LOCK_DESTROY(port); 685 port->sc = NULL; 686 return (rc); 687 } 688 689 static int sfxge_link_mode[EFX_PHY_MEDIA_NTYPES][EFX_LINK_NMODES] = { 690 [EFX_PHY_MEDIA_CX4] = { 691 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_CX4, 692 }, 693 [EFX_PHY_MEDIA_KX4] = { 694 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_KX4, 695 }, 696 [EFX_PHY_MEDIA_XFP] = { 697 /* Don't know the module type, but assume SR for now. */ 698 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_SR, 699 }, 700 [EFX_PHY_MEDIA_SFP_PLUS] = { 701 /* Don't know the module type, but assume SX/SR for now. */ 702 [EFX_LINK_1000FDX] = IFM_ETHER | IFM_FDX | IFM_1000_SX, 703 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_SR, 704 }, 705 [EFX_PHY_MEDIA_BASE_T] = { 706 [EFX_LINK_10HDX] = IFM_ETHER | IFM_HDX | IFM_10_T, 707 [EFX_LINK_10FDX] = IFM_ETHER | IFM_FDX | IFM_10_T, 708 [EFX_LINK_100HDX] = IFM_ETHER | IFM_HDX | IFM_100_TX, 709 [EFX_LINK_100FDX] = IFM_ETHER | IFM_FDX | IFM_100_TX, 710 [EFX_LINK_1000HDX] = IFM_ETHER | IFM_HDX | IFM_1000_T, 711 [EFX_LINK_1000FDX] = IFM_ETHER | IFM_FDX | IFM_1000_T, 712 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_T, 713 }, 714 }; 715 716 static void 717 sfxge_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) 718 { 719 struct sfxge_softc *sc; 720 efx_phy_media_type_t medium_type; 721 efx_link_mode_t mode; 722 723 sc = ifp->if_softc; 724 SFXGE_ADAPTER_LOCK(sc); 725 726 ifmr->ifm_status = IFM_AVALID; 727 ifmr->ifm_active = IFM_ETHER; 728 729 if (SFXGE_RUNNING(sc) && SFXGE_LINK_UP(sc)) { 730 ifmr->ifm_status |= IFM_ACTIVE; 731 732 efx_phy_media_type_get(sc->enp, &medium_type); 733 mode = sc->port.link_mode; 734 ifmr->ifm_active |= sfxge_link_mode[medium_type][mode]; 735 ifmr->ifm_active |= sfxge_port_link_fc_ifm(sc); 736 } 737 738 SFXGE_ADAPTER_UNLOCK(sc); 739 } 740 741 static int 742 sfxge_media_change(struct ifnet *ifp) 743 { 744 struct sfxge_softc *sc; 745 struct ifmedia_entry *ifm; 746 int rc; 747 748 sc = ifp->if_softc; 749 ifm = sc->media.ifm_cur; 750 751 SFXGE_ADAPTER_LOCK(sc); 752 753 if (!SFXGE_RUNNING(sc)) { 754 rc = 0; 755 goto out; 756 } 757 758 rc = efx_mac_fcntl_set(sc->enp, sfxge_port_wanted_fc(sc), B_TRUE); 759 if (rc != 0) 760 goto out; 761 762 rc = efx_phy_adv_cap_set(sc->enp, ifm->ifm_data); 763 out: 764 SFXGE_ADAPTER_UNLOCK(sc); 765 766 return (rc); 767 } 768 769 int sfxge_port_ifmedia_init(struct sfxge_softc *sc) 770 { 771 efx_phy_media_type_t medium_type; 772 uint32_t cap_mask, mode_cap_mask; 773 efx_link_mode_t mode; 774 int mode_ifm, best_mode_ifm = 0; 775 int rc; 776 777 /* We need port state to initialise the ifmedia list. */ 778 if ((rc = efx_nic_init(sc->enp)) != 0) 779 goto out; 780 if ((rc = efx_port_init(sc->enp)) != 0) 781 goto out2; 782 783 /* 784 * Register ifconfig callbacks for querying and setting the 785 * link mode and link status. 786 */ 787 ifmedia_init(&sc->media, IFM_IMASK, sfxge_media_change, 788 sfxge_media_status); 789 790 /* 791 * Map firmware medium type and capabilities to ifmedia types. 792 * ifmedia does not distinguish between forcing the link mode 793 * and disabling auto-negotiation. 1000BASE-T and 10GBASE-T 794 * require AN even if only one link mode is enabled, and for 795 * 100BASE-TX it is useful even if the link mode is forced. 796 * Therefore we never disable auto-negotiation. 797 * 798 * Also enable and advertise flow control by default. 799 */ 800 801 efx_phy_media_type_get(sc->enp, &medium_type); 802 efx_phy_adv_cap_get(sc->enp, EFX_PHY_CAP_PERM, &cap_mask); 803 804 EFX_STATIC_ASSERT(EFX_LINK_10HDX == EFX_PHY_CAP_10HDX + 1); 805 EFX_STATIC_ASSERT(EFX_LINK_10FDX == EFX_PHY_CAP_10FDX + 1); 806 EFX_STATIC_ASSERT(EFX_LINK_100HDX == EFX_PHY_CAP_100HDX + 1); 807 EFX_STATIC_ASSERT(EFX_LINK_100FDX == EFX_PHY_CAP_100FDX + 1); 808 EFX_STATIC_ASSERT(EFX_LINK_1000HDX == EFX_PHY_CAP_1000HDX + 1); 809 EFX_STATIC_ASSERT(EFX_LINK_1000FDX == EFX_PHY_CAP_1000FDX + 1); 810 EFX_STATIC_ASSERT(EFX_LINK_10000FDX == EFX_PHY_CAP_10000FDX + 1); 811 812 for (mode = EFX_LINK_10HDX; mode <= EFX_LINK_10000FDX; mode++) { 813 mode_cap_mask = 1 << (mode - 1); 814 mode_ifm = sfxge_link_mode[medium_type][mode]; 815 816 if ((cap_mask & mode_cap_mask) && mode_ifm) { 817 mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_AN); 818 819 #ifdef SFXGE_HAVE_PAUSE_MEDIAOPTS 820 /* No flow-control */ 821 ifmedia_add(&sc->media, mode_ifm, mode_cap_mask, NULL); 822 823 /* Respond-only. If using AN, we implicitly 824 * offer symmetric as well, but that doesn't 825 * mean we *have* to generate pause frames. 826 */ 827 mode_cap_mask |= cap_mask & ((1 << EFX_PHY_CAP_PAUSE) | 828 (1 << EFX_PHY_CAP_ASYM)); 829 mode_ifm |= IFM_ETH_RXPAUSE; 830 ifmedia_add(&sc->media, mode_ifm, mode_cap_mask, NULL); 831 832 /* Symmetric */ 833 mode_cap_mask &= ~(1 << EFX_PHY_CAP_ASYM); 834 mode_ifm |= IFM_ETH_TXPAUSE; 835 #else /* !SFXGE_HAVE_PAUSE_MEDIAOPTS */ 836 mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_PAUSE); 837 #endif 838 ifmedia_add(&sc->media, mode_ifm, mode_cap_mask, NULL); 839 840 /* Link modes are numbered in order of speed, 841 * so assume the last one available is the best. 842 */ 843 best_mode_ifm = mode_ifm; 844 } 845 } 846 847 if (cap_mask & (1 << EFX_PHY_CAP_AN)) { 848 /* Add autoselect mode. */ 849 mode_ifm = IFM_ETHER | IFM_AUTO; 850 ifmedia_add(&sc->media, mode_ifm, 851 cap_mask & ~(1 << EFX_PHY_CAP_ASYM), NULL); 852 best_mode_ifm = mode_ifm; 853 } 854 855 if (best_mode_ifm != 0) 856 ifmedia_set(&sc->media, best_mode_ifm); 857 858 /* Now discard port state until interface is started. */ 859 efx_port_fini(sc->enp); 860 out2: 861 efx_nic_fini(sc->enp); 862 out: 863 return (rc); 864 } 865