1/*- 2 * Copyright (c) 2010-2016 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 are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 27 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * The views and conclusions contained in the software and documentation are 30 * those of the authors and should not be interpreted as representing official 31 * policies, either expressed or implied, of the FreeBSD Project. 32 */ 33 34#include <sys/cdefs.h> 35__FBSDID("$FreeBSD: stable/10/sys/dev/sfxge/sfxge_port.c 312169 2017-01-14 10:59:25Z arybchik $"); 36 37#include <sys/types.h> 38#include <sys/limits.h> 39#include <net/ethernet.h> 40#include <net/if_dl.h> 41 42#include "common/efx.h" 43 44#include "sfxge.h" 45 46#define SFXGE_PARAM_STATS_UPDATE_PERIOD_MS \ 47 SFXGE_PARAM(stats_update_period_ms) 48static int sfxge_stats_update_period_ms = SFXGE_STATS_UPDATE_PERIOD_MS; 49TUNABLE_INT(SFXGE_PARAM_STATS_UPDATE_PERIOD_MS, 50 &sfxge_stats_update_period_ms); 51SYSCTL_INT(_hw_sfxge, OID_AUTO, stats_update_period_ms, CTLFLAG_RDTUN, 52 &sfxge_stats_update_period_ms, 0, 53 "netstat interface statistics update period in milliseconds"); 54 55static int sfxge_phy_cap_mask(struct sfxge_softc *, int, uint32_t *); 56 57static int 58sfxge_mac_stat_update(struct sfxge_softc *sc) 59{ 60 struct sfxge_port *port = &sc->port; 61 efsys_mem_t *esmp = &(port->mac_stats.dma_buf); 62 clock_t now; 63 unsigned int min_ticks; 64 unsigned int count; 65 int rc; 66 67 SFXGE_PORT_LOCK_ASSERT_OWNED(port); 68 69 if (__predict_false(port->init_state != SFXGE_PORT_STARTED)) { 70 rc = 0; 71 goto out; 72 } 73 74 min_ticks = (unsigned int)hz * port->stats_update_period_ms / 1000; 75 76 now = ticks; 77 if ((unsigned int)(now - port->mac_stats.update_time) < min_ticks) { 78 rc = 0; 79 goto out; 80 } 81 82 port->mac_stats.update_time = now; 83 84 /* If we're unlucky enough to read statistics wduring the DMA, wait 85 * up to 10ms for it to finish (typically takes <500us) */ 86 for (count = 0; count < 100; ++count) { 87 EFSYS_PROBE1(wait, unsigned int, count); 88 89 /* Try to update the cached counters */ 90 if ((rc = efx_mac_stats_update(sc->enp, esmp, 91 port->mac_stats.decode_buf, NULL)) != EAGAIN) 92 goto out; 93 94 DELAY(100); 95 } 96 97 rc = ETIMEDOUT; 98out: 99 return (rc); 100} 101 102void 103sfxge_port_update_stats(struct sfxge_softc *sc) 104{ 105 struct ifnet *ifp; 106 uint64_t *mac_stats; 107 108 SFXGE_PORT_LOCK(&sc->port); 109 110 /* Ignore error and use old values */ 111 (void)sfxge_mac_stat_update(sc); 112 113 ifp = sc->ifnet; 114 mac_stats = (uint64_t *)sc->port.mac_stats.decode_buf; 115 116 ifp->if_ipackets = mac_stats[EFX_MAC_RX_PKTS]; 117 ifp->if_ierrors = mac_stats[EFX_MAC_RX_ERRORS]; 118 ifp->if_opackets = mac_stats[EFX_MAC_TX_PKTS]; 119 ifp->if_oerrors = mac_stats[EFX_MAC_TX_ERRORS]; 120 ifp->if_collisions = 121 mac_stats[EFX_MAC_TX_SGL_COL_PKTS] + 122 mac_stats[EFX_MAC_TX_MULT_COL_PKTS] + 123 mac_stats[EFX_MAC_TX_EX_COL_PKTS] + 124 mac_stats[EFX_MAC_TX_LATE_COL_PKTS]; 125 ifp->if_ibytes = mac_stats[EFX_MAC_RX_OCTETS]; 126 ifp->if_obytes = mac_stats[EFX_MAC_TX_OCTETS]; 127 /* if_imcasts is maintained in net/if_ethersubr.c */ 128 ifp->if_omcasts = 129 mac_stats[EFX_MAC_TX_MULTICST_PKTS] + 130 mac_stats[EFX_MAC_TX_BRDCST_PKTS]; 131 /* if_iqdrops is maintained in net/if_ethersubr.c */ 132 /* if_noproto is maintained in net/if_ethersubr.c */ 133 134 SFXGE_PORT_UNLOCK(&sc->port); 135} 136 137static int 138sfxge_mac_stat_handler(SYSCTL_HANDLER_ARGS) 139{ 140 struct sfxge_softc *sc = arg1; 141 unsigned int id = arg2; 142 int rc; 143 uint64_t val; 144 145 SFXGE_PORT_LOCK(&sc->port); 146 if ((rc = sfxge_mac_stat_update(sc)) == 0) 147 val = ((uint64_t *)sc->port.mac_stats.decode_buf)[id]; 148 SFXGE_PORT_UNLOCK(&sc->port); 149 150 if (rc == 0) 151 rc = SYSCTL_OUT(req, &val, sizeof(val)); 152 return (rc); 153} 154 155static void 156sfxge_mac_stat_init(struct sfxge_softc *sc) 157{ 158 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev); 159 struct sysctl_oid_list *stat_list; 160 unsigned int id; 161 const char *name; 162 163 stat_list = SYSCTL_CHILDREN(sc->stats_node); 164 165 /* Initialise the named stats */ 166 for (id = 0; id < EFX_MAC_NSTATS; id++) { 167 name = efx_mac_stat_name(sc->enp, id); 168 SYSCTL_ADD_PROC( 169 ctx, stat_list, 170 OID_AUTO, name, CTLTYPE_U64|CTLFLAG_RD, 171 sc, id, sfxge_mac_stat_handler, "Q", 172 ""); 173 } 174} 175 176#ifdef SFXGE_HAVE_PAUSE_MEDIAOPTS 177 178static unsigned int 179sfxge_port_wanted_fc(struct sfxge_softc *sc) 180{ 181 struct ifmedia_entry *ifm = sc->media.ifm_cur; 182 183 if (ifm->ifm_media == (IFM_ETHER | IFM_AUTO)) 184 return (EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE); 185 return (((ifm->ifm_media & IFM_ETH_RXPAUSE) ? EFX_FCNTL_RESPOND : 0) | 186 ((ifm->ifm_media & IFM_ETH_TXPAUSE) ? EFX_FCNTL_GENERATE : 0)); 187} 188 189static unsigned int 190sfxge_port_link_fc_ifm(struct sfxge_softc *sc) 191{ 192 unsigned int wanted_fc, link_fc; 193 194 efx_mac_fcntl_get(sc->enp, &wanted_fc, &link_fc); 195 return ((link_fc & EFX_FCNTL_RESPOND) ? IFM_ETH_RXPAUSE : 0) | 196 ((link_fc & EFX_FCNTL_GENERATE) ? IFM_ETH_TXPAUSE : 0); 197} 198 199#else /* !SFXGE_HAVE_PAUSE_MEDIAOPTS */ 200 201static unsigned int 202sfxge_port_wanted_fc(struct sfxge_softc *sc) 203{ 204 return (sc->port.wanted_fc); 205} 206 207static unsigned int 208sfxge_port_link_fc_ifm(struct sfxge_softc *sc) 209{ 210 return (0); 211} 212 213static int 214sfxge_port_wanted_fc_handler(SYSCTL_HANDLER_ARGS) 215{ 216 struct sfxge_softc *sc; 217 struct sfxge_port *port; 218 unsigned int fcntl; 219 int error; 220 221 sc = arg1; 222 port = &sc->port; 223 224 if (req->newptr != NULL) { 225 if ((error = SYSCTL_IN(req, &fcntl, sizeof(fcntl))) != 0) 226 return (error); 227 228 SFXGE_PORT_LOCK(port); 229 230 if (port->wanted_fc != fcntl) { 231 if (port->init_state == SFXGE_PORT_STARTED) 232 error = efx_mac_fcntl_set(sc->enp, 233 port->wanted_fc, 234 B_TRUE); 235 if (error == 0) 236 port->wanted_fc = fcntl; 237 } 238 239 SFXGE_PORT_UNLOCK(port); 240 } else { 241 SFXGE_PORT_LOCK(port); 242 fcntl = port->wanted_fc; 243 SFXGE_PORT_UNLOCK(port); 244 245 error = SYSCTL_OUT(req, &fcntl, sizeof(fcntl)); 246 } 247 248 return (error); 249} 250 251static int 252sfxge_port_link_fc_handler(SYSCTL_HANDLER_ARGS) 253{ 254 struct sfxge_softc *sc; 255 struct sfxge_port *port; 256 unsigned int wanted_fc, link_fc; 257 258 sc = arg1; 259 port = &sc->port; 260 261 SFXGE_PORT_LOCK(port); 262 if (__predict_true(port->init_state == SFXGE_PORT_STARTED) && 263 SFXGE_LINK_UP(sc)) 264 efx_mac_fcntl_get(sc->enp, &wanted_fc, &link_fc); 265 else 266 link_fc = 0; 267 SFXGE_PORT_UNLOCK(port); 268 269 return (SYSCTL_OUT(req, &link_fc, sizeof(link_fc))); 270} 271 272#endif /* SFXGE_HAVE_PAUSE_MEDIAOPTS */ 273 274static const uint64_t sfxge_link_baudrate[EFX_LINK_NMODES] = { 275 [EFX_LINK_10HDX] = IF_Mbps(10), 276 [EFX_LINK_10FDX] = IF_Mbps(10), 277 [EFX_LINK_100HDX] = IF_Mbps(100), 278 [EFX_LINK_100FDX] = IF_Mbps(100), 279 [EFX_LINK_1000HDX] = IF_Gbps(1), 280 [EFX_LINK_1000FDX] = IF_Gbps(1), 281 [EFX_LINK_10000FDX] = IF_Gbps(10), 282 [EFX_LINK_40000FDX] = IF_Gbps(40), 283}; 284 285void 286sfxge_mac_link_update(struct sfxge_softc *sc, efx_link_mode_t mode) 287{ 288 struct sfxge_port *port; 289 int link_state; 290 291 port = &sc->port; 292 293 if (port->link_mode == mode) 294 return; 295 296 port->link_mode = mode; 297 298 /* Push link state update to the OS */ 299 link_state = (SFXGE_LINK_UP(sc) ? LINK_STATE_UP : LINK_STATE_DOWN); 300 if_initbaudrate(sc->ifnet, sfxge_link_baudrate[port->link_mode]); 301 if_link_state_change(sc->ifnet, link_state); 302} 303 304static void 305sfxge_mac_poll_work(void *arg, int npending) 306{ 307 struct sfxge_softc *sc; 308 efx_nic_t *enp; 309 struct sfxge_port *port; 310 efx_link_mode_t mode; 311 312 sc = (struct sfxge_softc *)arg; 313 enp = sc->enp; 314 port = &sc->port; 315 316 SFXGE_PORT_LOCK(port); 317 318 if (__predict_false(port->init_state != SFXGE_PORT_STARTED)) 319 goto done; 320 321 /* This may sleep waiting for MCDI completion */ 322 (void)efx_port_poll(enp, &mode); 323 sfxge_mac_link_update(sc, mode); 324 325done: 326 SFXGE_PORT_UNLOCK(port); 327} 328 329static int 330sfxge_mac_multicast_list_set(struct sfxge_softc *sc) 331{ 332 struct ifnet *ifp = sc->ifnet; 333 struct sfxge_port *port = &sc->port; 334 uint8_t *mcast_addr = port->mcast_addrs; 335 struct ifmultiaddr *ifma; 336 struct sockaddr_dl *sa; 337 int rc = 0; 338 339 mtx_assert(&port->lock, MA_OWNED); 340 341 port->mcast_count = 0; 342 if_maddr_rlock(ifp); 343 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 344 if (ifma->ifma_addr->sa_family == AF_LINK) { 345 if (port->mcast_count == EFX_MAC_MULTICAST_LIST_MAX) { 346 device_printf(sc->dev, 347 "Too many multicast addresses\n"); 348 rc = EINVAL; 349 break; 350 } 351 352 sa = (struct sockaddr_dl *)ifma->ifma_addr; 353 memcpy(mcast_addr, LLADDR(sa), EFX_MAC_ADDR_LEN); 354 mcast_addr += EFX_MAC_ADDR_LEN; 355 ++port->mcast_count; 356 } 357 } 358 if_maddr_runlock(ifp); 359 360 if (rc == 0) { 361 rc = efx_mac_multicast_list_set(sc->enp, port->mcast_addrs, 362 port->mcast_count); 363 if (rc != 0) 364 device_printf(sc->dev, 365 "Cannot set multicast address list\n"); 366 } 367 368 return (rc); 369} 370 371static int 372sfxge_mac_filter_set_locked(struct sfxge_softc *sc) 373{ 374 struct ifnet *ifp = sc->ifnet; 375 struct sfxge_port *port = &sc->port; 376 boolean_t all_mulcst; 377 int rc; 378 379 mtx_assert(&port->lock, MA_OWNED); 380 381 all_mulcst = !!(ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)); 382 383 rc = sfxge_mac_multicast_list_set(sc); 384 /* Fallback to all multicast if cannot set multicast list */ 385 if (rc != 0) 386 all_mulcst = B_TRUE; 387 388 rc = efx_mac_filter_set(sc->enp, !!(ifp->if_flags & IFF_PROMISC), 389 (port->mcast_count > 0), all_mulcst, B_TRUE); 390 391 return (rc); 392} 393 394int 395sfxge_mac_filter_set(struct sfxge_softc *sc) 396{ 397 struct sfxge_port *port = &sc->port; 398 int rc; 399 400 SFXGE_PORT_LOCK(port); 401 /* 402 * The function may be called without softc_lock held in the 403 * case of SIOCADDMULTI and SIOCDELMULTI ioctls. ioctl handler 404 * checks IFF_DRV_RUNNING flag which implies port started, but 405 * it is not guaranteed to remain. softc_lock shared lock can't 406 * be held in the case of these ioctls processing, since it 407 * results in failure where kernel complains that non-sleepable 408 * lock is held in sleeping thread. Both problems are repeatable 409 * on LAG with LACP proto bring up. 410 */ 411 if (__predict_true(port->init_state == SFXGE_PORT_STARTED)) 412 rc = sfxge_mac_filter_set_locked(sc); 413 else 414 rc = 0; 415 SFXGE_PORT_UNLOCK(port); 416 return (rc); 417} 418 419void 420sfxge_port_stop(struct sfxge_softc *sc) 421{ 422 struct sfxge_port *port; 423 efx_nic_t *enp; 424 425 port = &sc->port; 426 enp = sc->enp; 427 428 SFXGE_PORT_LOCK(port); 429 430 KASSERT(port->init_state == SFXGE_PORT_STARTED, 431 ("port not started")); 432 433 port->init_state = SFXGE_PORT_INITIALIZED; 434 435 port->mac_stats.update_time = 0; 436 437 /* This may call MCDI */ 438 (void)efx_mac_drain(enp, B_TRUE); 439 440 (void)efx_mac_stats_periodic(enp, &port->mac_stats.dma_buf, 0, B_FALSE); 441 442 port->link_mode = EFX_LINK_UNKNOWN; 443 444 /* Destroy the common code port object. */ 445 efx_port_fini(enp); 446 447 efx_filter_fini(enp); 448 449 SFXGE_PORT_UNLOCK(port); 450} 451 452int 453sfxge_port_start(struct sfxge_softc *sc) 454{ 455 uint8_t mac_addr[ETHER_ADDR_LEN]; 456 struct ifnet *ifp = sc->ifnet; 457 struct sfxge_port *port; 458 efx_nic_t *enp; 459 size_t pdu; 460 int rc; 461 uint32_t phy_cap_mask; 462 463 port = &sc->port; 464 enp = sc->enp; 465 466 SFXGE_PORT_LOCK(port); 467 468 KASSERT(port->init_state == SFXGE_PORT_INITIALIZED, 469 ("port not initialized")); 470 471 /* Initialise the required filtering */ 472 if ((rc = efx_filter_init(enp)) != 0) 473 goto fail_filter_init; 474 475 /* Initialize the port object in the common code. */ 476 if ((rc = efx_port_init(sc->enp)) != 0) 477 goto fail; 478 479 /* Set the SDU */ 480 pdu = EFX_MAC_PDU(ifp->if_mtu); 481 if ((rc = efx_mac_pdu_set(enp, pdu)) != 0) 482 goto fail2; 483 484 if ((rc = efx_mac_fcntl_set(enp, sfxge_port_wanted_fc(sc), B_TRUE)) 485 != 0) 486 goto fail3; 487 488 /* Set the unicast address */ 489 if_addr_rlock(ifp); 490 bcopy(LLADDR((struct sockaddr_dl *)ifp->if_addr->ifa_addr), 491 mac_addr, sizeof(mac_addr)); 492 if_addr_runlock(ifp); 493 if ((rc = efx_mac_addr_set(enp, mac_addr)) != 0) 494 goto fail4; 495 496 sfxge_mac_filter_set_locked(sc); 497 498 /* Update MAC stats by DMA every period */ 499 if ((rc = efx_mac_stats_periodic(enp, &port->mac_stats.dma_buf, 500 port->stats_update_period_ms, 501 B_FALSE)) != 0) 502 goto fail6; 503 504 if ((rc = efx_mac_drain(enp, B_FALSE)) != 0) 505 goto fail8; 506 507 if ((rc = sfxge_phy_cap_mask(sc, sc->media.ifm_cur->ifm_media, 508 &phy_cap_mask)) != 0) 509 goto fail9; 510 511 if ((rc = efx_phy_adv_cap_set(sc->enp, phy_cap_mask)) != 0) 512 goto fail10; 513 514 port->init_state = SFXGE_PORT_STARTED; 515 516 /* Single poll in case there were missing initial events */ 517 SFXGE_PORT_UNLOCK(port); 518 sfxge_mac_poll_work(sc, 0); 519 520 return (0); 521 522fail10: 523fail9: 524 (void)efx_mac_drain(enp, B_TRUE); 525fail8: 526 (void)efx_mac_stats_periodic(enp, &port->mac_stats.dma_buf, 0, B_FALSE); 527fail6: 528fail4: 529fail3: 530 531fail2: 532 efx_port_fini(enp); 533fail: 534 efx_filter_fini(enp); 535fail_filter_init: 536 SFXGE_PORT_UNLOCK(port); 537 538 return (rc); 539} 540 541static int 542sfxge_phy_stat_update(struct sfxge_softc *sc) 543{ 544 struct sfxge_port *port = &sc->port; 545 efsys_mem_t *esmp = &port->phy_stats.dma_buf; 546 clock_t now; 547 unsigned int count; 548 int rc; 549 550 SFXGE_PORT_LOCK_ASSERT_OWNED(port); 551 552 if (__predict_false(port->init_state != SFXGE_PORT_STARTED)) { 553 rc = 0; 554 goto out; 555 } 556 557 now = ticks; 558 if ((unsigned int)(now - port->phy_stats.update_time) < (unsigned int)hz) { 559 rc = 0; 560 goto out; 561 } 562 563 port->phy_stats.update_time = now; 564 565 /* If we're unlucky enough to read statistics wduring the DMA, wait 566 * up to 10ms for it to finish (typically takes <500us) */ 567 for (count = 0; count < 100; ++count) { 568 EFSYS_PROBE1(wait, unsigned int, count); 569 570 /* Synchronize the DMA memory for reading */ 571 bus_dmamap_sync(esmp->esm_tag, esmp->esm_map, 572 BUS_DMASYNC_POSTREAD); 573 574 /* Try to update the cached counters */ 575 if ((rc = efx_phy_stats_update(sc->enp, esmp, 576 port->phy_stats.decode_buf)) != EAGAIN) 577 goto out; 578 579 DELAY(100); 580 } 581 582 rc = ETIMEDOUT; 583out: 584 return (rc); 585} 586 587static int 588sfxge_phy_stat_handler(SYSCTL_HANDLER_ARGS) 589{ 590 struct sfxge_softc *sc = arg1; 591 unsigned int id = arg2; 592 int rc; 593 uint32_t val; 594 595 SFXGE_PORT_LOCK(&sc->port); 596 if ((rc = sfxge_phy_stat_update(sc)) == 0) 597 val = ((uint32_t *)sc->port.phy_stats.decode_buf)[id]; 598 SFXGE_PORT_UNLOCK(&sc->port); 599 600 if (rc == 0) 601 rc = SYSCTL_OUT(req, &val, sizeof(val)); 602 return (rc); 603} 604 605static void 606sfxge_phy_stat_init(struct sfxge_softc *sc) 607{ 608 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev); 609 struct sysctl_oid_list *stat_list; 610 unsigned int id; 611 const char *name; 612 uint64_t stat_mask = efx_nic_cfg_get(sc->enp)->enc_phy_stat_mask; 613 614 stat_list = SYSCTL_CHILDREN(sc->stats_node); 615 616 /* Initialise the named stats */ 617 for (id = 0; id < EFX_PHY_NSTATS; id++) { 618 if (!(stat_mask & ((uint64_t)1 << id))) 619 continue; 620 name = efx_phy_stat_name(sc->enp, id); 621 SYSCTL_ADD_PROC( 622 ctx, stat_list, 623 OID_AUTO, name, CTLTYPE_UINT|CTLFLAG_RD, 624 sc, id, sfxge_phy_stat_handler, 625 id == EFX_PHY_STAT_OUI ? "IX" : "IU", 626 ""); 627 } 628} 629 630void 631sfxge_port_fini(struct sfxge_softc *sc) 632{ 633 struct sfxge_port *port; 634 efsys_mem_t *esmp; 635 636 port = &sc->port; 637 esmp = &port->mac_stats.dma_buf; 638 639 KASSERT(port->init_state == SFXGE_PORT_INITIALIZED, 640 ("Port not initialized")); 641 642 port->init_state = SFXGE_PORT_UNINITIALIZED; 643 644 port->link_mode = EFX_LINK_UNKNOWN; 645 646 /* Finish with PHY DMA memory */ 647 sfxge_dma_free(&port->phy_stats.dma_buf); 648 free(port->phy_stats.decode_buf, M_SFXGE); 649 650 sfxge_dma_free(esmp); 651 free(port->mac_stats.decode_buf, M_SFXGE); 652 653 SFXGE_PORT_LOCK_DESTROY(port); 654 655 port->sc = NULL; 656} 657 658static uint16_t 659sfxge_port_stats_update_period_ms(struct sfxge_softc *sc) 660{ 661 int period_ms = sfxge_stats_update_period_ms; 662 663 if (period_ms < 0) { 664 device_printf(sc->dev, 665 "treat negative stats update period %d as 0 (disable)\n", 666 period_ms); 667 period_ms = 0; 668 } else if (period_ms > UINT16_MAX) { 669 device_printf(sc->dev, 670 "treat too big stats update period %d as %u\n", 671 period_ms, UINT16_MAX); 672 period_ms = UINT16_MAX; 673 } 674 675 return period_ms; 676} 677 678static int 679sfxge_port_stats_update_period_ms_handler(SYSCTL_HANDLER_ARGS) 680{ 681 struct sfxge_softc *sc; 682 struct sfxge_port *port; 683 unsigned int period_ms; 684 int error; 685 686 sc = arg1; 687 port = &sc->port; 688 689 if (req->newptr != NULL) { 690 error = SYSCTL_IN(req, &period_ms, sizeof(period_ms)); 691 if (error != 0) 692 return (error); 693 694 if (period_ms > UINT16_MAX) 695 return (EINVAL); 696 697 SFXGE_PORT_LOCK(port); 698 699 if (port->stats_update_period_ms != period_ms) { 700 if (port->init_state == SFXGE_PORT_STARTED) 701 error = efx_mac_stats_periodic(sc->enp, 702 &port->mac_stats.dma_buf, 703 period_ms, B_FALSE); 704 if (error == 0) 705 port->stats_update_period_ms = period_ms; 706 } 707 708 SFXGE_PORT_UNLOCK(port); 709 } else { 710 SFXGE_PORT_LOCK(port); 711 period_ms = port->stats_update_period_ms; 712 SFXGE_PORT_UNLOCK(port); 713 714 error = SYSCTL_OUT(req, &period_ms, sizeof(period_ms)); 715 } 716 717 return (error); 718} 719 720int 721sfxge_port_init(struct sfxge_softc *sc) 722{ 723 struct sfxge_port *port; 724 struct sysctl_ctx_list *sysctl_ctx; 725 struct sysctl_oid *sysctl_tree; 726 efsys_mem_t *mac_stats_buf, *phy_stats_buf; 727 int rc; 728 729 port = &sc->port; 730 mac_stats_buf = &port->mac_stats.dma_buf; 731 phy_stats_buf = &port->phy_stats.dma_buf; 732 733 KASSERT(port->init_state == SFXGE_PORT_UNINITIALIZED, 734 ("Port already initialized")); 735 736 port->sc = sc; 737 738 SFXGE_PORT_LOCK_INIT(port, device_get_nameunit(sc->dev)); 739 740 DBGPRINT(sc->dev, "alloc PHY stats"); 741 port->phy_stats.decode_buf = malloc(EFX_PHY_NSTATS * sizeof(uint32_t), 742 M_SFXGE, M_WAITOK | M_ZERO); 743 if ((rc = sfxge_dma_alloc(sc, EFX_PHY_STATS_SIZE, phy_stats_buf)) != 0) 744 goto fail; 745 sfxge_phy_stat_init(sc); 746 747 DBGPRINT(sc->dev, "init sysctl"); 748 sysctl_ctx = device_get_sysctl_ctx(sc->dev); 749 sysctl_tree = device_get_sysctl_tree(sc->dev); 750 751#ifndef SFXGE_HAVE_PAUSE_MEDIAOPTS 752 /* If flow control cannot be configured or reported through 753 * ifmedia, provide sysctls for it. */ 754 port->wanted_fc = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 755 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 756 "wanted_fc", CTLTYPE_UINT|CTLFLAG_RW, sc, 0, 757 sfxge_port_wanted_fc_handler, "IU", "wanted flow control mode"); 758 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 759 "link_fc", CTLTYPE_UINT|CTLFLAG_RD, sc, 0, 760 sfxge_port_link_fc_handler, "IU", "link flow control mode"); 761#endif 762 763 DBGPRINT(sc->dev, "alloc MAC stats"); 764 port->mac_stats.decode_buf = malloc(EFX_MAC_NSTATS * sizeof(uint64_t), 765 M_SFXGE, M_WAITOK | M_ZERO); 766 if ((rc = sfxge_dma_alloc(sc, EFX_MAC_STATS_SIZE, mac_stats_buf)) != 0) 767 goto fail2; 768 port->stats_update_period_ms = sfxge_port_stats_update_period_ms(sc); 769 sfxge_mac_stat_init(sc); 770 771 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, 772 "stats_update_period_ms", CTLTYPE_UINT|CTLFLAG_RW, sc, 0, 773 sfxge_port_stats_update_period_ms_handler, "IU", 774 "interface statistics refresh period"); 775 776 port->init_state = SFXGE_PORT_INITIALIZED; 777 778 DBGPRINT(sc->dev, "success"); 779 return (0); 780 781fail2: 782 free(port->mac_stats.decode_buf, M_SFXGE); 783 sfxge_dma_free(phy_stats_buf); 784fail: 785 free(port->phy_stats.decode_buf, M_SFXGE); 786 SFXGE_PORT_LOCK_DESTROY(port); 787 port->sc = NULL; 788 DBGPRINT(sc->dev, "failed %d", rc); 789 return (rc); 790} 791 792static const int sfxge_link_mode[EFX_PHY_MEDIA_NTYPES][EFX_LINK_NMODES] = { 793 [EFX_PHY_MEDIA_CX4] = { 794 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_CX4, 795 }, 796 [EFX_PHY_MEDIA_KX4] = { 797 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_KX4, 798 }, 799 [EFX_PHY_MEDIA_XFP] = { 800 /* Don't know the module type, but assume SR for now. */ 801 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_SR, 802 }, 803 [EFX_PHY_MEDIA_QSFP_PLUS] = { 804 /* Don't know the module type, but assume SR for now. */ 805 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_SR, 806 [EFX_LINK_40000FDX] = IFM_ETHER | IFM_FDX | IFM_40G_CR4, 807 }, 808 [EFX_PHY_MEDIA_SFP_PLUS] = { 809 /* Don't know the module type, but assume SX/SR for now. */ 810 [EFX_LINK_1000FDX] = IFM_ETHER | IFM_FDX | IFM_1000_SX, 811 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_SR, 812 }, 813 [EFX_PHY_MEDIA_BASE_T] = { 814 [EFX_LINK_10HDX] = IFM_ETHER | IFM_HDX | IFM_10_T, 815 [EFX_LINK_10FDX] = IFM_ETHER | IFM_FDX | IFM_10_T, 816 [EFX_LINK_100HDX] = IFM_ETHER | IFM_HDX | IFM_100_TX, 817 [EFX_LINK_100FDX] = IFM_ETHER | IFM_FDX | IFM_100_TX, 818 [EFX_LINK_1000HDX] = IFM_ETHER | IFM_HDX | IFM_1000_T, 819 [EFX_LINK_1000FDX] = IFM_ETHER | IFM_FDX | IFM_1000_T, 820 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_T, 821 }, 822}; 823 824static void 825sfxge_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) 826{ 827 struct sfxge_softc *sc; 828 efx_phy_media_type_t medium_type; 829 efx_link_mode_t mode; 830 831 sc = ifp->if_softc; 832 SFXGE_ADAPTER_LOCK(sc); 833 834 ifmr->ifm_status = IFM_AVALID; 835 ifmr->ifm_active = IFM_ETHER; 836 837 if (SFXGE_RUNNING(sc) && SFXGE_LINK_UP(sc)) { 838 ifmr->ifm_status |= IFM_ACTIVE; 839 840 efx_phy_media_type_get(sc->enp, &medium_type); 841 mode = sc->port.link_mode; 842 ifmr->ifm_active |= sfxge_link_mode[medium_type][mode]; 843 ifmr->ifm_active |= sfxge_port_link_fc_ifm(sc); 844 } 845 846 SFXGE_ADAPTER_UNLOCK(sc); 847} 848 849static efx_phy_cap_type_t 850sfxge_link_mode_to_phy_cap(efx_link_mode_t mode) 851{ 852 switch (mode) { 853 case EFX_LINK_10HDX: 854 return (EFX_PHY_CAP_10HDX); 855 case EFX_LINK_10FDX: 856 return (EFX_PHY_CAP_10FDX); 857 case EFX_LINK_100HDX: 858 return (EFX_PHY_CAP_100HDX); 859 case EFX_LINK_100FDX: 860 return (EFX_PHY_CAP_100FDX); 861 case EFX_LINK_1000HDX: 862 return (EFX_PHY_CAP_1000HDX); 863 case EFX_LINK_1000FDX: 864 return (EFX_PHY_CAP_1000FDX); 865 case EFX_LINK_10000FDX: 866 return (EFX_PHY_CAP_10000FDX); 867 case EFX_LINK_40000FDX: 868 return (EFX_PHY_CAP_40000FDX); 869 default: 870 EFSYS_ASSERT(B_FALSE); 871 return (EFX_PHY_CAP_INVALID); 872 } 873} 874 875static int 876sfxge_phy_cap_mask(struct sfxge_softc *sc, int ifmedia, uint32_t *phy_cap_mask) 877{ 878 /* Get global options (duplex), type and subtype bits */ 879 int ifmedia_masked = ifmedia & (IFM_GMASK | IFM_NMASK | IFM_TMASK); 880 efx_phy_media_type_t medium_type; 881 boolean_t mode_found = B_FALSE; 882 uint32_t cap_mask, mode_cap_mask; 883 efx_link_mode_t mode; 884 efx_phy_cap_type_t phy_cap; 885 886 efx_phy_media_type_get(sc->enp, &medium_type); 887 if (medium_type >= nitems(sfxge_link_mode)) { 888 if_printf(sc->ifnet, "unexpected media type %d\n", medium_type); 889 return (EINVAL); 890 } 891 892 efx_phy_adv_cap_get(sc->enp, EFX_PHY_CAP_PERM, &cap_mask); 893 894 for (mode = EFX_LINK_10HDX; mode < EFX_LINK_NMODES; mode++) { 895 if (ifmedia_masked == sfxge_link_mode[medium_type][mode]) { 896 mode_found = B_TRUE; 897 break; 898 } 899 } 900 901 if (!mode_found) { 902 /* 903 * If media is not in the table, it must be IFM_AUTO. 904 */ 905 KASSERT((cap_mask & (1 << EFX_PHY_CAP_AN)) && 906 ifmedia_masked == (IFM_ETHER | IFM_AUTO), 907 ("%s: no mode for media %#x", __func__, ifmedia)); 908 *phy_cap_mask = (cap_mask & ~(1 << EFX_PHY_CAP_ASYM)); 909 return (0); 910 } 911 912 phy_cap = sfxge_link_mode_to_phy_cap(mode); 913 if (phy_cap == EFX_PHY_CAP_INVALID) { 914 if_printf(sc->ifnet, 915 "cannot map link mode %d to phy capability\n", 916 mode); 917 return (EINVAL); 918 } 919 920 mode_cap_mask = (1 << phy_cap); 921 mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_AN); 922#ifdef SFXGE_HAVE_PAUSE_MEDIAOPTS 923 if (ifmedia & IFM_ETH_RXPAUSE) 924 mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_PAUSE); 925 if (!(ifmedia & IFM_ETH_TXPAUSE)) 926 mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_ASYM); 927#else 928 mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_PAUSE); 929#endif 930 931 *phy_cap_mask = mode_cap_mask; 932 return (0); 933} 934 935static int 936sfxge_media_change(struct ifnet *ifp) 937{ 938 struct sfxge_softc *sc; 939 struct ifmedia_entry *ifm; 940 int rc; 941 uint32_t phy_cap_mask; 942 943 sc = ifp->if_softc; 944 ifm = sc->media.ifm_cur; 945 946 SFXGE_ADAPTER_LOCK(sc); 947 948 if (!SFXGE_RUNNING(sc)) { 949 rc = 0; 950 goto out; 951 } 952 953 rc = efx_mac_fcntl_set(sc->enp, sfxge_port_wanted_fc(sc), B_TRUE); 954 if (rc != 0) 955 goto out; 956 957 if ((rc = sfxge_phy_cap_mask(sc, ifm->ifm_media, &phy_cap_mask)) != 0) 958 goto out; 959 960 rc = efx_phy_adv_cap_set(sc->enp, phy_cap_mask); 961out: 962 SFXGE_ADAPTER_UNLOCK(sc); 963 964 return (rc); 965} 966 967int sfxge_port_ifmedia_init(struct sfxge_softc *sc) 968{ 969 efx_phy_media_type_t medium_type; 970 uint32_t cap_mask, mode_cap_mask; 971 efx_link_mode_t mode; 972 efx_phy_cap_type_t phy_cap; 973 int mode_ifm, best_mode_ifm = 0; 974 int rc; 975 976 /* 977 * We need port state to initialise the ifmedia list. 978 * It requires initialized NIC what is already done in 979 * sfxge_create() when resources are estimated. 980 */ 981 if ((rc = efx_filter_init(sc->enp)) != 0) 982 goto out1; 983 if ((rc = efx_port_init(sc->enp)) != 0) 984 goto out2; 985 986 /* 987 * Register ifconfig callbacks for querying and setting the 988 * link mode and link status. 989 */ 990 ifmedia_init(&sc->media, IFM_IMASK, sfxge_media_change, 991 sfxge_media_status); 992 993 /* 994 * Map firmware medium type and capabilities to ifmedia types. 995 * ifmedia does not distinguish between forcing the link mode 996 * and disabling auto-negotiation. 1000BASE-T and 10GBASE-T 997 * require AN even if only one link mode is enabled, and for 998 * 100BASE-TX it is useful even if the link mode is forced. 999 * Therefore we never disable auto-negotiation. 1000 * 1001 * Also enable and advertise flow control by default. 1002 */ 1003 1004 efx_phy_media_type_get(sc->enp, &medium_type); 1005 efx_phy_adv_cap_get(sc->enp, EFX_PHY_CAP_PERM, &cap_mask); 1006 1007 for (mode = EFX_LINK_10HDX; mode < EFX_LINK_NMODES; mode++) { 1008 phy_cap = sfxge_link_mode_to_phy_cap(mode); 1009 if (phy_cap == EFX_PHY_CAP_INVALID) 1010 continue; 1011 1012 mode_cap_mask = (1 << phy_cap); 1013 mode_ifm = sfxge_link_mode[medium_type][mode]; 1014 1015 if ((cap_mask & mode_cap_mask) && mode_ifm) { 1016 /* No flow-control */ 1017 ifmedia_add(&sc->media, mode_ifm, 0, NULL); 1018 1019#ifdef SFXGE_HAVE_PAUSE_MEDIAOPTS 1020 /* Respond-only. If using AN, we implicitly 1021 * offer symmetric as well, but that doesn't 1022 * mean we *have* to generate pause frames. 1023 */ 1024 mode_ifm |= IFM_ETH_RXPAUSE; 1025 ifmedia_add(&sc->media, mode_ifm, 0, NULL); 1026 1027 /* Symmetric */ 1028 mode_ifm |= IFM_ETH_TXPAUSE; 1029 ifmedia_add(&sc->media, mode_ifm, 0, NULL); 1030#endif 1031 1032 /* Link modes are numbered in order of speed, 1033 * so assume the last one available is the best. 1034 */ 1035 best_mode_ifm = mode_ifm; 1036 } 1037 } 1038 1039 if (cap_mask & (1 << EFX_PHY_CAP_AN)) { 1040 /* Add autoselect mode. */ 1041 mode_ifm = IFM_ETHER | IFM_AUTO; 1042 ifmedia_add(&sc->media, mode_ifm, 0, NULL); 1043 best_mode_ifm = mode_ifm; 1044 } 1045 1046 if (best_mode_ifm != 0) 1047 ifmedia_set(&sc->media, best_mode_ifm); 1048 1049 /* Now discard port state until interface is started. */ 1050 efx_port_fini(sc->enp); 1051out2: 1052 efx_filter_fini(sc->enp); 1053out1: 1054 return (rc); 1055} 1056