1 /*- 2 * Copyright (c) 2007-2015 Solarflare Communications Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * The views and conclusions contained in the software and documentation are 27 * those of the authors and should not be interpreted as representing official 28 * policies, either expressed or implied, of the FreeBSD Project. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include "efx.h" 35 #include "efx_impl.h" 36 37 #if EFSYS_OPT_MAC_FALCON_GMAC 38 #include "falcon_gmac.h" 39 #endif 40 41 #if EFSYS_OPT_MAC_FALCON_XMAC 42 #include "falcon_xmac.h" 43 #endif 44 45 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA 46 47 static __checkReturn efx_rc_t 48 falconsiena_mac_multicast_list_set( 49 __in efx_nic_t *enp); 50 51 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */ 52 53 #if EFSYS_OPT_MAC_FALCON_GMAC 54 static efx_mac_ops_t __efx_falcon_gmac_ops = { 55 falcon_gmac_reset, /* emo_reset */ 56 falcon_mac_poll, /* emo_poll */ 57 falcon_mac_up, /* emo_up */ 58 falcon_gmac_reconfigure, /* emo_addr_set */ 59 falcon_gmac_reconfigure, /* emo_reconfigure */ 60 falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */ 61 NULL, /* emo_filter_set_default_rxq */ 62 NULL, /* emo_filter_default_rxq_clear */ 63 #if EFSYS_OPT_LOOPBACK 64 falcon_mac_loopback_set, /* emo_loopback_set */ 65 #endif /* EFSYS_OPT_LOOPBACK */ 66 #if EFSYS_OPT_MAC_STATS 67 falcon_mac_stats_upload, /* emo_stats_upload */ 68 NULL, /* emo_stats_periodic */ 69 falcon_gmac_stats_update /* emo_stats_update */ 70 #endif /* EFSYS_OPT_MAC_STATS */ 71 }; 72 #endif /* EFSYS_OPT_MAC_FALCON_GMAC */ 73 74 #if EFSYS_OPT_MAC_FALCON_XMAC 75 static efx_mac_ops_t __efx_falcon_xmac_ops = { 76 falcon_xmac_reset, /* emo_reset */ 77 falcon_mac_poll, /* emo_poll */ 78 falcon_mac_up, /* emo_up */ 79 falcon_xmac_reconfigure, /* emo_addr_set */ 80 falcon_xmac_reconfigure, /* emo_reconfigure */ 81 falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */ 82 NULL, /* emo_filter_set_default_rxq */ 83 NULL, /* emo_filter_default_rxq_clear */ 84 #if EFSYS_OPT_LOOPBACK 85 falcon_mac_loopback_set, /* emo_loopback_set */ 86 #endif /* EFSYS_OPT_LOOPBACK */ 87 #if EFSYS_OPT_MAC_STATS 88 falcon_mac_stats_upload, /* emo_stats_upload */ 89 NULL, /* emo_stats_periodic */ 90 falcon_xmac_stats_update /* emo_stats_update */ 91 #endif /* EFSYS_OPT_MAC_STATS */ 92 }; 93 #endif /* EFSYS_OPT_MAC_FALCON_XMAC */ 94 95 #if EFSYS_OPT_SIENA 96 static efx_mac_ops_t __efx_siena_mac_ops = { 97 NULL, /* emo_reset */ 98 siena_mac_poll, /* emo_poll */ 99 siena_mac_up, /* emo_up */ 100 siena_mac_reconfigure, /* emo_addr_set */ 101 siena_mac_reconfigure, /* emo_reconfigure */ 102 falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */ 103 NULL, /* emo_filter_set_default_rxq */ 104 NULL, /* emo_filter_default_rxq_clear */ 105 #if EFSYS_OPT_LOOPBACK 106 siena_mac_loopback_set, /* emo_loopback_set */ 107 #endif /* EFSYS_OPT_LOOPBACK */ 108 #if EFSYS_OPT_MAC_STATS 109 efx_mcdi_mac_stats_upload, /* emo_stats_upload */ 110 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */ 111 siena_mac_stats_update /* emo_stats_update */ 112 #endif /* EFSYS_OPT_MAC_STATS */ 113 }; 114 #endif /* EFSYS_OPT_SIENA */ 115 116 #if EFSYS_OPT_HUNTINGTON 117 static efx_mac_ops_t __efx_hunt_mac_ops = { 118 NULL, /* emo_reset */ 119 hunt_mac_poll, /* emo_poll */ 120 hunt_mac_up, /* emo_up */ 121 hunt_mac_addr_set, /* emo_addr_set */ 122 hunt_mac_reconfigure, /* emo_reconfigure */ 123 hunt_mac_multicast_list_set, /* emo_multicast_list_set */ 124 hunt_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */ 125 hunt_mac_filter_default_rxq_clear, 126 /* emo_filter_default_rxq_clear */ 127 #if EFSYS_OPT_LOOPBACK 128 hunt_mac_loopback_set, /* emo_loopback_set */ 129 #endif /* EFSYS_OPT_LOOPBACK */ 130 #if EFSYS_OPT_MAC_STATS 131 efx_mcdi_mac_stats_upload, /* emo_stats_upload */ 132 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */ 133 hunt_mac_stats_update /* emo_stats_update */ 134 #endif /* EFSYS_OPT_MAC_STATS */ 135 }; 136 #endif /* EFSYS_OPT_HUNTINGTON */ 137 138 static efx_mac_ops_t *__efx_mac_ops[] = { 139 /* [EFX_MAC_INVALID] */ 140 NULL, 141 /* [EFX_MAC_FALCON_GMAC] */ 142 #if EFSYS_OPT_MAC_FALCON_GMAC 143 &__efx_falcon_gmac_ops, 144 #else 145 NULL, 146 #endif 147 /* [EFX_MAC_FALCON_XMAC] */ 148 #if EFSYS_OPT_MAC_FALCON_XMAC 149 &__efx_falcon_xmac_ops, 150 #else 151 NULL, 152 #endif 153 /* [EFX_MAC_SIENA] */ 154 #if EFSYS_OPT_SIENA 155 &__efx_siena_mac_ops, 156 #else 157 NULL, 158 #endif 159 /* [EFX_MAC_HUNTINGTON] */ 160 #if EFSYS_OPT_HUNTINGTON 161 &__efx_hunt_mac_ops, 162 #else 163 NULL, 164 #endif 165 }; 166 167 __checkReturn efx_rc_t 168 efx_mac_pdu_set( 169 __in efx_nic_t *enp, 170 __in size_t pdu) 171 { 172 efx_port_t *epp = &(enp->en_port); 173 efx_mac_ops_t *emop = epp->ep_emop; 174 uint32_t old_pdu; 175 efx_rc_t rc; 176 177 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 178 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 179 EFSYS_ASSERT(emop != NULL); 180 181 if (pdu < EFX_MAC_PDU_MIN) { 182 rc = EINVAL; 183 goto fail1; 184 } 185 186 if (pdu > EFX_MAC_PDU_MAX) { 187 rc = EINVAL; 188 goto fail2; 189 } 190 191 old_pdu = epp->ep_mac_pdu; 192 epp->ep_mac_pdu = (uint32_t)pdu; 193 if ((rc = emop->emo_reconfigure(enp)) != 0) 194 goto fail3; 195 196 return (0); 197 198 fail3: 199 EFSYS_PROBE(fail3); 200 201 epp->ep_mac_pdu = old_pdu; 202 203 fail2: 204 EFSYS_PROBE(fail2); 205 fail1: 206 EFSYS_PROBE1(fail1, efx_rc_t, rc); 207 208 return (rc); 209 } 210 211 __checkReturn efx_rc_t 212 efx_mac_addr_set( 213 __in efx_nic_t *enp, 214 __in uint8_t *addr) 215 { 216 efx_port_t *epp = &(enp->en_port); 217 efx_mac_ops_t *emop = epp->ep_emop; 218 uint8_t old_addr[6]; 219 uint32_t oui; 220 efx_rc_t rc; 221 222 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 223 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 224 225 if (EFX_MAC_ADDR_IS_MULTICAST(addr)) { 226 rc = EINVAL; 227 goto fail1; 228 } 229 230 oui = addr[0] << 16 | addr[1] << 8 | addr[2]; 231 if (oui == 0x000000) { 232 rc = EINVAL; 233 goto fail2; 234 } 235 236 EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr); 237 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr); 238 if ((rc = emop->emo_addr_set(enp)) != 0) 239 goto fail3; 240 241 return (0); 242 243 fail3: 244 EFSYS_PROBE(fail3); 245 246 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr); 247 248 fail2: 249 EFSYS_PROBE(fail2); 250 fail1: 251 EFSYS_PROBE1(fail1, efx_rc_t, rc); 252 253 return (rc); 254 } 255 256 __checkReturn efx_rc_t 257 efx_mac_filter_set( 258 __in efx_nic_t *enp, 259 __in boolean_t all_unicst, 260 __in boolean_t mulcst, 261 __in boolean_t all_mulcst, 262 __in boolean_t brdcst) 263 { 264 efx_port_t *epp = &(enp->en_port); 265 efx_mac_ops_t *emop = epp->ep_emop; 266 boolean_t old_all_unicst; 267 boolean_t old_mulcst; 268 boolean_t old_all_mulcst; 269 boolean_t old_brdcst; 270 efx_rc_t rc; 271 272 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 273 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 274 275 old_all_unicst = epp->ep_all_unicst; 276 old_mulcst = epp->ep_mulcst; 277 old_all_mulcst = epp->ep_all_mulcst; 278 old_brdcst = epp->ep_brdcst; 279 280 epp->ep_all_unicst = all_unicst; 281 epp->ep_mulcst = mulcst; 282 epp->ep_all_mulcst = all_mulcst; 283 epp->ep_brdcst = brdcst; 284 285 if ((rc = emop->emo_reconfigure(enp)) != 0) 286 goto fail1; 287 288 return (0); 289 290 fail1: 291 EFSYS_PROBE1(fail1, efx_rc_t, rc); 292 293 epp->ep_all_unicst = old_all_unicst; 294 epp->ep_mulcst = old_mulcst; 295 epp->ep_all_mulcst = old_all_mulcst; 296 epp->ep_brdcst = old_brdcst; 297 298 return (rc); 299 } 300 301 __checkReturn efx_rc_t 302 efx_mac_drain( 303 __in efx_nic_t *enp, 304 __in boolean_t enabled) 305 { 306 efx_port_t *epp = &(enp->en_port); 307 efx_mac_ops_t *emop = epp->ep_emop; 308 efx_rc_t rc; 309 310 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 311 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 312 EFSYS_ASSERT(emop != NULL); 313 314 if (epp->ep_mac_drain == enabled) 315 return (0); 316 317 epp->ep_mac_drain = enabled; 318 319 if (enabled && emop->emo_reset != NULL) { 320 if ((rc = emop->emo_reset(enp)) != 0) 321 goto fail1; 322 323 EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC); 324 enp->en_reset_flags &= ~EFX_RESET_PHY; 325 } 326 327 if ((rc = emop->emo_reconfigure(enp)) != 0) 328 goto fail2; 329 330 return (0); 331 332 fail2: 333 EFSYS_PROBE(fail2); 334 fail1: 335 EFSYS_PROBE1(fail1, efx_rc_t, rc); 336 337 return (rc); 338 } 339 340 __checkReturn efx_rc_t 341 efx_mac_up( 342 __in efx_nic_t *enp, 343 __out boolean_t *mac_upp) 344 { 345 efx_port_t *epp = &(enp->en_port); 346 efx_mac_ops_t *emop = epp->ep_emop; 347 efx_rc_t rc; 348 349 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 350 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 351 352 if ((rc = emop->emo_up(enp, mac_upp)) != 0) 353 goto fail1; 354 355 return (0); 356 357 fail1: 358 EFSYS_PROBE1(fail1, efx_rc_t, rc); 359 360 return (rc); 361 } 362 363 __checkReturn efx_rc_t 364 efx_mac_fcntl_set( 365 __in efx_nic_t *enp, 366 __in unsigned int fcntl, 367 __in boolean_t autoneg) 368 { 369 efx_port_t *epp = &(enp->en_port); 370 efx_mac_ops_t *emop = epp->ep_emop; 371 efx_phy_ops_t *epop = epp->ep_epop; 372 unsigned int old_fcntl; 373 boolean_t old_autoneg; 374 unsigned int old_adv_cap; 375 efx_rc_t rc; 376 377 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 378 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 379 380 if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) { 381 rc = EINVAL; 382 goto fail1; 383 } 384 385 /* 386 * Ignore a request to set flow control auto-negotiation 387 * if the PHY doesn't support it. 388 */ 389 if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) 390 autoneg = B_FALSE; 391 392 old_fcntl = epp->ep_fcntl; 393 old_autoneg = epp->ep_fcntl_autoneg; 394 old_adv_cap = epp->ep_adv_cap_mask; 395 396 epp->ep_fcntl = fcntl; 397 epp->ep_fcntl_autoneg = autoneg; 398 399 /* 400 * Always encode the flow control settings in the advertised 401 * capabilities even if we are not trying to auto-negotiate 402 * them and reconfigure both the PHY and the MAC. 403 */ 404 if (fcntl & EFX_FCNTL_RESPOND) 405 epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE | 406 1 << EFX_PHY_CAP_ASYM); 407 else 408 epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE | 409 1 << EFX_PHY_CAP_ASYM); 410 411 if (fcntl & EFX_FCNTL_GENERATE) 412 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM); 413 414 if ((rc = epop->epo_reconfigure(enp)) != 0) 415 goto fail2; 416 417 if ((rc = emop->emo_reconfigure(enp)) != 0) 418 goto fail3; 419 420 return (0); 421 422 fail3: 423 EFSYS_PROBE(fail3); 424 425 fail2: 426 EFSYS_PROBE(fail2); 427 428 epp->ep_fcntl = old_fcntl; 429 epp->ep_fcntl_autoneg = old_autoneg; 430 epp->ep_adv_cap_mask = old_adv_cap; 431 432 fail1: 433 EFSYS_PROBE1(fail1, efx_rc_t, rc); 434 435 return (rc); 436 } 437 438 void 439 efx_mac_fcntl_get( 440 __in efx_nic_t *enp, 441 __out unsigned int *fcntl_wantedp, 442 __out unsigned int *fcntl_linkp) 443 { 444 efx_port_t *epp = &(enp->en_port); 445 unsigned int wanted = 0; 446 447 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 448 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 449 450 /* 451 * Decode the requested flow control settings from the PHY 452 * advertised capabilities. 453 */ 454 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE)) 455 wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 456 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM)) 457 wanted ^= EFX_FCNTL_GENERATE; 458 459 *fcntl_linkp = epp->ep_fcntl; 460 *fcntl_wantedp = wanted; 461 } 462 463 __checkReturn efx_rc_t 464 efx_mac_multicast_list_set( 465 __in efx_nic_t *enp, 466 __in_ecount(6*count) uint8_t const *addrs, 467 __in int count) 468 { 469 efx_port_t *epp = &(enp->en_port); 470 efx_mac_ops_t *emop = epp->ep_emop; 471 uint8_t *old_mulcst_addr_list = NULL; 472 uint32_t old_mulcst_addr_count; 473 efx_rc_t rc; 474 475 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 476 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 477 478 if (count > EFX_MAC_MULTICAST_LIST_MAX) { 479 rc = EINVAL; 480 goto fail1; 481 } 482 483 old_mulcst_addr_count = epp->ep_mulcst_addr_count; 484 if (old_mulcst_addr_count > 0) { 485 /* Allocate memory to store old list (instead of using stack) */ 486 EFSYS_KMEM_ALLOC(enp->en_esip, 487 old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 488 old_mulcst_addr_list); 489 if (old_mulcst_addr_list == NULL) { 490 rc = ENOMEM; 491 goto fail2; 492 } 493 494 /* Save the old list in case we need to rollback */ 495 memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list, 496 old_mulcst_addr_count * EFX_MAC_ADDR_LEN); 497 } 498 499 /* Store the new list */ 500 memcpy(epp->ep_mulcst_addr_list, addrs, 501 count * EFX_MAC_ADDR_LEN); 502 epp->ep_mulcst_addr_count = count; 503 504 if ((rc = emop->emo_multicast_list_set(enp)) != 0) 505 goto fail3; 506 507 if (old_mulcst_addr_count > 0) { 508 EFSYS_KMEM_FREE(enp->en_esip, 509 old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 510 old_mulcst_addr_list); 511 } 512 513 return (0); 514 515 fail3: 516 EFSYS_PROBE(fail3); 517 518 /* Restore original list on failure */ 519 epp->ep_mulcst_addr_count = old_mulcst_addr_count; 520 if (old_mulcst_addr_count > 0) { 521 memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list, 522 old_mulcst_addr_count * EFX_MAC_ADDR_LEN); 523 524 EFSYS_KMEM_FREE(enp->en_esip, 525 old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 526 old_mulcst_addr_list); 527 } 528 529 fail2: 530 EFSYS_PROBE(fail2); 531 532 fail1: 533 EFSYS_PROBE1(fail1, efx_rc_t, rc); 534 535 return (rc); 536 537 } 538 539 __checkReturn efx_rc_t 540 efx_mac_filter_default_rxq_set( 541 __in efx_nic_t *enp, 542 __in efx_rxq_t *erp, 543 __in boolean_t using_rss) 544 { 545 efx_port_t *epp = &(enp->en_port); 546 efx_mac_ops_t *emop = epp->ep_emop; 547 efx_rc_t rc; 548 549 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 550 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 551 552 if (emop->emo_filter_default_rxq_set != NULL) { 553 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss); 554 if (rc != 0) 555 goto fail1; 556 } 557 558 return (0); 559 560 fail1: 561 EFSYS_PROBE1(fail1, efx_rc_t, rc); 562 563 return (rc); 564 } 565 566 void 567 efx_mac_filter_default_rxq_clear( 568 __in efx_nic_t *enp) 569 { 570 efx_port_t *epp = &(enp->en_port); 571 efx_mac_ops_t *emop = epp->ep_emop; 572 573 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 574 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 575 576 if (emop->emo_filter_default_rxq_clear != NULL) 577 emop->emo_filter_default_rxq_clear(enp); 578 } 579 580 581 #if EFSYS_OPT_MAC_STATS 582 583 #if EFSYS_OPT_NAMES 584 585 /* START MKCONFIG GENERATED EfxMacStatNamesBlock 054d43a31d2d7a45 */ 586 static const char *__efx_mac_stat_name[] = { 587 "rx_octets", 588 "rx_pkts", 589 "rx_unicst_pkts", 590 "rx_multicst_pkts", 591 "rx_brdcst_pkts", 592 "rx_pause_pkts", 593 "rx_le_64_pkts", 594 "rx_65_to_127_pkts", 595 "rx_128_to_255_pkts", 596 "rx_256_to_511_pkts", 597 "rx_512_to_1023_pkts", 598 "rx_1024_to_15xx_pkts", 599 "rx_ge_15xx_pkts", 600 "rx_errors", 601 "rx_fcs_errors", 602 "rx_drop_events", 603 "rx_false_carrier_errors", 604 "rx_symbol_errors", 605 "rx_align_errors", 606 "rx_internal_errors", 607 "rx_jabber_pkts", 608 "rx_lane0_char_err", 609 "rx_lane1_char_err", 610 "rx_lane2_char_err", 611 "rx_lane3_char_err", 612 "rx_lane0_disp_err", 613 "rx_lane1_disp_err", 614 "rx_lane2_disp_err", 615 "rx_lane3_disp_err", 616 "rx_match_fault", 617 "rx_nodesc_drop_cnt", 618 "tx_octets", 619 "tx_pkts", 620 "tx_unicst_pkts", 621 "tx_multicst_pkts", 622 "tx_brdcst_pkts", 623 "tx_pause_pkts", 624 "tx_le_64_pkts", 625 "tx_65_to_127_pkts", 626 "tx_128_to_255_pkts", 627 "tx_256_to_511_pkts", 628 "tx_512_to_1023_pkts", 629 "tx_1024_to_15xx_pkts", 630 "tx_ge_15xx_pkts", 631 "tx_errors", 632 "tx_sgl_col_pkts", 633 "tx_mult_col_pkts", 634 "tx_ex_col_pkts", 635 "tx_late_col_pkts", 636 "tx_def_pkts", 637 "tx_ex_def_pkts", 638 "pm_trunc_bb_overflow", 639 "pm_discard_bb_overflow", 640 "pm_trunc_vfifo_full", 641 "pm_discard_vfifo_full", 642 "pm_trunc_qbb", 643 "pm_discard_qbb", 644 "pm_discard_mapping", 645 "rxdp_q_disabled_pkts", 646 "rxdp_di_dropped_pkts", 647 "rxdp_streaming_pkts", 648 "rxdp_hlb_fetch", 649 "rxdp_hlb_wait", 650 "vadapter_rx_unicast_packets", 651 "vadapter_rx_unicast_bytes", 652 "vadapter_rx_multicast_packets", 653 "vadapter_rx_multicast_bytes", 654 "vadapter_rx_broadcast_packets", 655 "vadapter_rx_broadcast_bytes", 656 "vadapter_rx_bad_packets", 657 "vadapter_rx_bad_bytes", 658 "vadapter_rx_overflow", 659 "vadapter_tx_unicast_packets", 660 "vadapter_tx_unicast_bytes", 661 "vadapter_tx_multicast_packets", 662 "vadapter_tx_multicast_bytes", 663 "vadapter_tx_broadcast_packets", 664 "vadapter_tx_broadcast_bytes", 665 "vadapter_tx_bad_packets", 666 "vadapter_tx_bad_bytes", 667 "vadapter_tx_overflow", 668 }; 669 /* END MKCONFIG GENERATED EfxMacStatNamesBlock */ 670 671 __checkReturn const char * 672 efx_mac_stat_name( 673 __in efx_nic_t *enp, 674 __in unsigned int id) 675 { 676 _NOTE(ARGUNUSED(enp)) 677 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 678 679 EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS); 680 return (__efx_mac_stat_name[id]); 681 } 682 683 #endif /* EFSYS_OPT_NAMES */ 684 685 __checkReturn efx_rc_t 686 efx_mac_stats_upload( 687 __in efx_nic_t *enp, 688 __in efsys_mem_t *esmp) 689 { 690 efx_port_t *epp = &(enp->en_port); 691 efx_mac_ops_t *emop = epp->ep_emop; 692 efx_rc_t rc; 693 694 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 695 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 696 EFSYS_ASSERT(emop != NULL); 697 698 /* 699 * Don't assert !ep_mac_stats_pending, because the client might 700 * have failed to finalise statistics when previously stopping 701 * the port. 702 */ 703 if ((rc = emop->emo_stats_upload(enp, esmp)) != 0) 704 goto fail1; 705 706 epp->ep_mac_stats_pending = B_TRUE; 707 708 return (0); 709 710 fail1: 711 EFSYS_PROBE1(fail1, efx_rc_t, rc); 712 713 return (rc); 714 } 715 716 __checkReturn efx_rc_t 717 efx_mac_stats_periodic( 718 __in efx_nic_t *enp, 719 __in efsys_mem_t *esmp, 720 __in uint16_t period_ms, 721 __in boolean_t events) 722 { 723 efx_port_t *epp = &(enp->en_port); 724 efx_mac_ops_t *emop = epp->ep_emop; 725 efx_rc_t rc; 726 727 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 728 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 729 730 EFSYS_ASSERT(emop != NULL); 731 732 if (emop->emo_stats_periodic == NULL) { 733 rc = EINVAL; 734 goto fail1; 735 } 736 737 if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0) 738 goto fail2; 739 740 return (0); 741 742 fail2: 743 EFSYS_PROBE(fail2); 744 fail1: 745 EFSYS_PROBE1(fail1, efx_rc_t, rc); 746 747 return (rc); 748 } 749 750 751 __checkReturn efx_rc_t 752 efx_mac_stats_update( 753 __in efx_nic_t *enp, 754 __in efsys_mem_t *esmp, 755 __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp, 756 __inout_opt uint32_t *generationp) 757 { 758 efx_port_t *epp = &(enp->en_port); 759 efx_mac_ops_t *emop = epp->ep_emop; 760 efx_rc_t rc; 761 762 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 763 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 764 EFSYS_ASSERT(emop != NULL); 765 766 rc = emop->emo_stats_update(enp, esmp, essp, generationp); 767 if (rc == 0) 768 epp->ep_mac_stats_pending = B_FALSE; 769 770 return (rc); 771 } 772 773 #endif /* EFSYS_OPT_MAC_STATS */ 774 775 __checkReturn efx_rc_t 776 efx_mac_select( 777 __in efx_nic_t *enp) 778 { 779 efx_port_t *epp = &(enp->en_port); 780 efx_mac_type_t type = EFX_MAC_INVALID; 781 efx_mac_ops_t *emop; 782 int rc = EINVAL; 783 784 #if EFSYS_OPT_HUNTINGTON 785 if (enp->en_family == EFX_FAMILY_HUNTINGTON) { 786 type = EFX_MAC_HUNTINGTON; 787 goto chosen; 788 } 789 #endif 790 791 #if EFSYS_OPT_SIENA 792 if (enp->en_family == EFX_FAMILY_SIENA) { 793 type = EFX_MAC_SIENA; 794 goto chosen; 795 } 796 #endif 797 798 #if EFSYS_OPT_FALCON 799 switch (epp->ep_link_mode) { 800 #if EFSYS_OPT_MAC_FALCON_GMAC 801 case EFX_LINK_100HDX: 802 case EFX_LINK_100FDX: 803 case EFX_LINK_1000HDX: 804 case EFX_LINK_1000FDX: 805 type = EFX_MAC_FALCON_GMAC; 806 goto chosen; 807 #endif /* EFSYS_OPT_FALCON_GMAC */ 808 809 #if EFSYS_OPT_MAC_FALCON_XMAC 810 case EFX_LINK_10000FDX: 811 type = EFX_MAC_FALCON_XMAC; 812 goto chosen; 813 #endif /* EFSYS_OPT_FALCON_XMAC */ 814 815 default: 816 #if EFSYS_OPT_MAC_FALCON_GMAC && EFSYS_OPT_MAC_FALCON_XMAC 817 /* Only initialise a MAC supported by the PHY */ 818 if (epp->ep_phy_cap_mask & 819 ((1 << EFX_PHY_CAP_1000FDX) | 820 (1 << EFX_PHY_CAP_1000HDX) | 821 (1 << EFX_PHY_CAP_100FDX) | 822 (1 << EFX_PHY_CAP_100HDX) | 823 (1 << EFX_PHY_CAP_10FDX) | 824 (1 << EFX_PHY_CAP_10FDX))) 825 type = EFX_MAC_FALCON_GMAC; 826 else 827 type = EFX_MAC_FALCON_XMAC; 828 #elif EFSYS_OPT_MAC_FALCON_GMAC 829 type = EFX_MAC_FALCON_GMAC; 830 #else 831 type = EFX_MAC_FALCON_XMAC; 832 #endif 833 goto chosen; 834 } 835 #endif /* EFSYS_OPT_FALCON */ 836 837 chosen: 838 EFSYS_ASSERT(type != EFX_MAC_INVALID); 839 EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES); 840 emop = epp->ep_emop = (efx_mac_ops_t *)__efx_mac_ops[type]; 841 EFSYS_ASSERT(emop != NULL); 842 843 epp->ep_mac_type = type; 844 845 if (emop->emo_reset != NULL) { 846 if ((rc = emop->emo_reset(enp)) != 0) 847 goto fail1; 848 849 EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC); 850 enp->en_reset_flags &= ~EFX_RESET_MAC; 851 } 852 853 return (0); 854 855 fail1: 856 EFSYS_PROBE1(fail1, efx_rc_t, rc); 857 858 return (rc); 859 } 860 861 862 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA 863 864 #define EFX_MAC_HASH_BITS (1 << 8) 865 866 /* Compute the multicast hash as used on Falcon and Siena. */ 867 static void 868 falconsiena_mac_multicast_hash_compute( 869 __in_ecount(6*count) uint8_t const *addrs, 870 __in int count, 871 __out efx_oword_t *hash_low, 872 __out efx_oword_t *hash_high) 873 { 874 uint32_t crc, index; 875 int i; 876 877 EFSYS_ASSERT(hash_low != NULL); 878 EFSYS_ASSERT(hash_high != NULL); 879 880 EFX_ZERO_OWORD(*hash_low); 881 EFX_ZERO_OWORD(*hash_high); 882 883 for (i = 0; i < count; i++) { 884 /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */ 885 crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN); 886 index = crc % EFX_MAC_HASH_BITS; 887 if (index < 128) { 888 EFX_SET_OWORD_BIT(*hash_low, index); 889 } else { 890 EFX_SET_OWORD_BIT(*hash_high, index - 128); 891 } 892 893 addrs += EFX_MAC_ADDR_LEN; 894 } 895 } 896 897 static __checkReturn efx_rc_t 898 falconsiena_mac_multicast_list_set( 899 __in efx_nic_t *enp) 900 { 901 efx_port_t *epp = &(enp->en_port); 902 efx_mac_ops_t *emop = epp->ep_emop; 903 efx_oword_t old_hash[2]; 904 efx_rc_t rc; 905 906 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 907 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 908 909 memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash)); 910 911 falconsiena_mac_multicast_hash_compute(epp->ep_mulcst_addr_list, 912 epp->ep_mulcst_addr_count, 913 &epp->ep_multicst_hash[0], 914 &epp->ep_multicst_hash[1]); 915 916 if ((rc = emop->emo_reconfigure(enp)) != 0) 917 goto fail1; 918 919 return (0); 920 921 fail1: 922 EFSYS_PROBE1(fail1, efx_rc_t, rc); 923 924 memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash)); 925 926 return (rc); 927 } 928 929 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */ 930