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 "efx.h" 32 #include "efx_impl.h" 33 34 #if EFSYS_OPT_SIENA 35 36 static __checkReturn efx_rc_t 37 siena_mac_multicast_list_set( 38 __in efx_nic_t *enp); 39 40 #endif /* EFSYS_OPT_SIENA */ 41 42 #if EFSYS_OPT_SIENA 43 static const efx_mac_ops_t __efx_siena_mac_ops = { 44 siena_mac_poll, /* emo_poll */ 45 siena_mac_up, /* emo_up */ 46 siena_mac_reconfigure, /* emo_addr_set */ 47 siena_mac_reconfigure, /* emo_pdu_set */ 48 siena_mac_reconfigure, /* emo_reconfigure */ 49 siena_mac_multicast_list_set, /* emo_multicast_list_set */ 50 NULL, /* emo_filter_set_default_rxq */ 51 NULL, /* emo_filter_default_rxq_clear */ 52 #if EFSYS_OPT_LOOPBACK 53 siena_mac_loopback_set, /* emo_loopback_set */ 54 #endif /* EFSYS_OPT_LOOPBACK */ 55 #if EFSYS_OPT_MAC_STATS 56 efx_mcdi_mac_stats_upload, /* emo_stats_upload */ 57 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */ 58 siena_mac_stats_update /* emo_stats_update */ 59 #endif /* EFSYS_OPT_MAC_STATS */ 60 }; 61 #endif /* EFSYS_OPT_SIENA */ 62 63 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 64 static const efx_mac_ops_t __efx_ef10_mac_ops = { 65 ef10_mac_poll, /* emo_poll */ 66 ef10_mac_up, /* emo_up */ 67 ef10_mac_addr_set, /* emo_addr_set */ 68 ef10_mac_pdu_set, /* emo_pdu_set */ 69 ef10_mac_reconfigure, /* emo_reconfigure */ 70 ef10_mac_multicast_list_set, /* emo_multicast_list_set */ 71 ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */ 72 ef10_mac_filter_default_rxq_clear, 73 /* emo_filter_default_rxq_clear */ 74 #if EFSYS_OPT_LOOPBACK 75 ef10_mac_loopback_set, /* emo_loopback_set */ 76 #endif /* EFSYS_OPT_LOOPBACK */ 77 #if EFSYS_OPT_MAC_STATS 78 efx_mcdi_mac_stats_upload, /* emo_stats_upload */ 79 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */ 80 ef10_mac_stats_update /* emo_stats_update */ 81 #endif /* EFSYS_OPT_MAC_STATS */ 82 }; 83 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 84 85 86 __checkReturn efx_rc_t 87 efx_mac_pdu_set( 88 __in efx_nic_t *enp, 89 __in size_t pdu) 90 { 91 efx_port_t *epp = &(enp->en_port); 92 const efx_mac_ops_t *emop = epp->ep_emop; 93 uint32_t old_pdu; 94 efx_rc_t rc; 95 96 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 97 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 98 EFSYS_ASSERT(emop != NULL); 99 100 if (pdu < EFX_MAC_PDU_MIN) { 101 rc = EINVAL; 102 goto fail1; 103 } 104 105 if (pdu > EFX_MAC_PDU_MAX) { 106 rc = EINVAL; 107 goto fail2; 108 } 109 110 old_pdu = epp->ep_mac_pdu; 111 epp->ep_mac_pdu = (uint32_t)pdu; 112 if ((rc = emop->emo_pdu_set(enp)) != 0) 113 goto fail3; 114 115 return (0); 116 117 fail3: 118 EFSYS_PROBE(fail3); 119 120 epp->ep_mac_pdu = old_pdu; 121 122 fail2: 123 EFSYS_PROBE(fail2); 124 fail1: 125 EFSYS_PROBE1(fail1, efx_rc_t, rc); 126 127 return (rc); 128 } 129 130 __checkReturn efx_rc_t 131 efx_mac_addr_set( 132 __in efx_nic_t *enp, 133 __in uint8_t *addr) 134 { 135 efx_port_t *epp = &(enp->en_port); 136 const efx_mac_ops_t *emop = epp->ep_emop; 137 uint8_t old_addr[6]; 138 uint32_t oui; 139 efx_rc_t rc; 140 141 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 142 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 143 144 if (EFX_MAC_ADDR_IS_MULTICAST(addr)) { 145 rc = EINVAL; 146 goto fail1; 147 } 148 149 oui = addr[0] << 16 | addr[1] << 8 | addr[2]; 150 if (oui == 0x000000) { 151 rc = EINVAL; 152 goto fail2; 153 } 154 155 EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr); 156 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr); 157 if ((rc = emop->emo_addr_set(enp)) != 0) 158 goto fail3; 159 160 return (0); 161 162 fail3: 163 EFSYS_PROBE(fail3); 164 165 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr); 166 167 fail2: 168 EFSYS_PROBE(fail2); 169 fail1: 170 EFSYS_PROBE1(fail1, efx_rc_t, rc); 171 172 return (rc); 173 } 174 175 __checkReturn efx_rc_t 176 efx_mac_filter_set( 177 __in efx_nic_t *enp, 178 __in boolean_t all_unicst, 179 __in boolean_t mulcst, 180 __in boolean_t all_mulcst, 181 __in boolean_t brdcst) 182 { 183 efx_port_t *epp = &(enp->en_port); 184 const efx_mac_ops_t *emop = epp->ep_emop; 185 boolean_t old_all_unicst; 186 boolean_t old_mulcst; 187 boolean_t old_all_mulcst; 188 boolean_t old_brdcst; 189 efx_rc_t rc; 190 191 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 192 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 193 194 old_all_unicst = epp->ep_all_unicst; 195 old_mulcst = epp->ep_mulcst; 196 old_all_mulcst = epp->ep_all_mulcst; 197 old_brdcst = epp->ep_brdcst; 198 199 epp->ep_all_unicst = all_unicst; 200 epp->ep_mulcst = mulcst; 201 epp->ep_all_mulcst = all_mulcst; 202 epp->ep_brdcst = brdcst; 203 204 if ((rc = emop->emo_reconfigure(enp)) != 0) 205 goto fail1; 206 207 return (0); 208 209 fail1: 210 EFSYS_PROBE1(fail1, efx_rc_t, rc); 211 212 epp->ep_all_unicst = old_all_unicst; 213 epp->ep_mulcst = old_mulcst; 214 epp->ep_all_mulcst = old_all_mulcst; 215 epp->ep_brdcst = old_brdcst; 216 217 return (rc); 218 } 219 220 __checkReturn efx_rc_t 221 efx_mac_drain( 222 __in efx_nic_t *enp, 223 __in boolean_t enabled) 224 { 225 efx_port_t *epp = &(enp->en_port); 226 const efx_mac_ops_t *emop = epp->ep_emop; 227 efx_rc_t rc; 228 229 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 230 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 231 EFSYS_ASSERT(emop != NULL); 232 233 if (epp->ep_mac_drain == enabled) 234 return (0); 235 236 epp->ep_mac_drain = enabled; 237 238 if ((rc = emop->emo_reconfigure(enp)) != 0) 239 goto fail1; 240 241 return (0); 242 243 fail1: 244 EFSYS_PROBE1(fail1, efx_rc_t, rc); 245 246 return (rc); 247 } 248 249 __checkReturn efx_rc_t 250 efx_mac_up( 251 __in efx_nic_t *enp, 252 __out boolean_t *mac_upp) 253 { 254 efx_port_t *epp = &(enp->en_port); 255 const efx_mac_ops_t *emop = epp->ep_emop; 256 efx_rc_t rc; 257 258 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 259 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 260 261 if ((rc = emop->emo_up(enp, mac_upp)) != 0) 262 goto fail1; 263 264 return (0); 265 266 fail1: 267 EFSYS_PROBE1(fail1, efx_rc_t, rc); 268 269 return (rc); 270 } 271 272 __checkReturn efx_rc_t 273 efx_mac_fcntl_set( 274 __in efx_nic_t *enp, 275 __in unsigned int fcntl, 276 __in boolean_t autoneg) 277 { 278 efx_port_t *epp = &(enp->en_port); 279 const efx_mac_ops_t *emop = epp->ep_emop; 280 const efx_phy_ops_t *epop = epp->ep_epop; 281 unsigned int old_fcntl; 282 boolean_t old_autoneg; 283 unsigned int old_adv_cap; 284 efx_rc_t rc; 285 286 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 287 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 288 289 if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) { 290 rc = EINVAL; 291 goto fail1; 292 } 293 294 /* 295 * Ignore a request to set flow control auto-negotiation 296 * if the PHY doesn't support it. 297 */ 298 if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) 299 autoneg = B_FALSE; 300 301 old_fcntl = epp->ep_fcntl; 302 old_autoneg = epp->ep_fcntl_autoneg; 303 old_adv_cap = epp->ep_adv_cap_mask; 304 305 epp->ep_fcntl = fcntl; 306 epp->ep_fcntl_autoneg = autoneg; 307 308 /* 309 * Always encode the flow control settings in the advertised 310 * capabilities even if we are not trying to auto-negotiate 311 * them and reconfigure both the PHY and the MAC. 312 */ 313 if (fcntl & EFX_FCNTL_RESPOND) 314 epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE | 315 1 << EFX_PHY_CAP_ASYM); 316 else 317 epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE | 318 1 << EFX_PHY_CAP_ASYM); 319 320 if (fcntl & EFX_FCNTL_GENERATE) 321 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM); 322 323 if ((rc = epop->epo_reconfigure(enp)) != 0) 324 goto fail2; 325 326 if ((rc = emop->emo_reconfigure(enp)) != 0) 327 goto fail3; 328 329 return (0); 330 331 fail3: 332 EFSYS_PROBE(fail3); 333 334 fail2: 335 EFSYS_PROBE(fail2); 336 337 epp->ep_fcntl = old_fcntl; 338 epp->ep_fcntl_autoneg = old_autoneg; 339 epp->ep_adv_cap_mask = old_adv_cap; 340 341 fail1: 342 EFSYS_PROBE1(fail1, efx_rc_t, rc); 343 344 return (rc); 345 } 346 347 void 348 efx_mac_fcntl_get( 349 __in efx_nic_t *enp, 350 __out unsigned int *fcntl_wantedp, 351 __out unsigned int *fcntl_linkp) 352 { 353 efx_port_t *epp = &(enp->en_port); 354 unsigned int wanted = 0; 355 356 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 357 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 358 359 /* 360 * Decode the requested flow control settings from the PHY 361 * advertised capabilities. 362 */ 363 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE)) 364 wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 365 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM)) 366 wanted ^= EFX_FCNTL_GENERATE; 367 368 *fcntl_linkp = epp->ep_fcntl; 369 *fcntl_wantedp = wanted; 370 } 371 372 __checkReturn efx_rc_t 373 efx_mac_multicast_list_set( 374 __in efx_nic_t *enp, 375 __in_ecount(6*count) uint8_t const *addrs, 376 __in int count) 377 { 378 efx_port_t *epp = &(enp->en_port); 379 const efx_mac_ops_t *emop = epp->ep_emop; 380 uint8_t *old_mulcst_addr_list = NULL; 381 uint32_t old_mulcst_addr_count; 382 efx_rc_t rc; 383 384 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 385 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 386 387 if (count > EFX_MAC_MULTICAST_LIST_MAX) { 388 rc = EINVAL; 389 goto fail1; 390 } 391 392 old_mulcst_addr_count = epp->ep_mulcst_addr_count; 393 if (old_mulcst_addr_count > 0) { 394 /* Allocate memory to store old list (instead of using stack) */ 395 EFSYS_KMEM_ALLOC(enp->en_esip, 396 old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 397 old_mulcst_addr_list); 398 if (old_mulcst_addr_list == NULL) { 399 rc = ENOMEM; 400 goto fail2; 401 } 402 403 /* Save the old list in case we need to rollback */ 404 (void) memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list, 405 old_mulcst_addr_count * EFX_MAC_ADDR_LEN); 406 } 407 408 /* Store the new list */ 409 (void) memcpy(epp->ep_mulcst_addr_list, addrs, 410 count * EFX_MAC_ADDR_LEN); 411 epp->ep_mulcst_addr_count = count; 412 413 if ((rc = emop->emo_multicast_list_set(enp)) != 0) 414 goto fail3; 415 416 if (old_mulcst_addr_count > 0) { 417 EFSYS_KMEM_FREE(enp->en_esip, 418 old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 419 old_mulcst_addr_list); 420 } 421 422 return (0); 423 424 fail3: 425 EFSYS_PROBE(fail3); 426 427 /* Restore original list on failure */ 428 epp->ep_mulcst_addr_count = old_mulcst_addr_count; 429 if (old_mulcst_addr_count > 0) { 430 (void) memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list, 431 old_mulcst_addr_count * EFX_MAC_ADDR_LEN); 432 433 EFSYS_KMEM_FREE(enp->en_esip, 434 old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 435 old_mulcst_addr_list); 436 } 437 438 fail2: 439 EFSYS_PROBE(fail2); 440 441 fail1: 442 EFSYS_PROBE1(fail1, efx_rc_t, rc); 443 444 return (rc); 445 446 } 447 448 __checkReturn efx_rc_t 449 efx_mac_filter_default_rxq_set( 450 __in efx_nic_t *enp, 451 __in efx_rxq_t *erp, 452 __in boolean_t using_rss) 453 { 454 efx_port_t *epp = &(enp->en_port); 455 const efx_mac_ops_t *emop = epp->ep_emop; 456 efx_rc_t rc; 457 458 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 459 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 460 461 if (emop->emo_filter_default_rxq_set != NULL) { 462 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss); 463 if (rc != 0) 464 goto fail1; 465 } 466 467 return (0); 468 469 fail1: 470 EFSYS_PROBE1(fail1, efx_rc_t, rc); 471 472 return (rc); 473 } 474 475 void 476 efx_mac_filter_default_rxq_clear( 477 __in efx_nic_t *enp) 478 { 479 efx_port_t *epp = &(enp->en_port); 480 const efx_mac_ops_t *emop = epp->ep_emop; 481 482 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 483 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 484 485 if (emop->emo_filter_default_rxq_clear != NULL) 486 emop->emo_filter_default_rxq_clear(enp); 487 } 488 489 490 #if EFSYS_OPT_MAC_STATS 491 492 #if EFSYS_OPT_NAMES 493 494 /* START MKCONFIG GENERATED EfxMacStatNamesBlock 054d43a31d2d7a45 */ 495 static const char *__efx_mac_stat_name[] = { 496 "rx_octets", 497 "rx_pkts", 498 "rx_unicst_pkts", 499 "rx_multicst_pkts", 500 "rx_brdcst_pkts", 501 "rx_pause_pkts", 502 "rx_le_64_pkts", 503 "rx_65_to_127_pkts", 504 "rx_128_to_255_pkts", 505 "rx_256_to_511_pkts", 506 "rx_512_to_1023_pkts", 507 "rx_1024_to_15xx_pkts", 508 "rx_ge_15xx_pkts", 509 "rx_errors", 510 "rx_fcs_errors", 511 "rx_drop_events", 512 "rx_false_carrier_errors", 513 "rx_symbol_errors", 514 "rx_align_errors", 515 "rx_internal_errors", 516 "rx_jabber_pkts", 517 "rx_lane0_char_err", 518 "rx_lane1_char_err", 519 "rx_lane2_char_err", 520 "rx_lane3_char_err", 521 "rx_lane0_disp_err", 522 "rx_lane1_disp_err", 523 "rx_lane2_disp_err", 524 "rx_lane3_disp_err", 525 "rx_match_fault", 526 "rx_nodesc_drop_cnt", 527 "tx_octets", 528 "tx_pkts", 529 "tx_unicst_pkts", 530 "tx_multicst_pkts", 531 "tx_brdcst_pkts", 532 "tx_pause_pkts", 533 "tx_le_64_pkts", 534 "tx_65_to_127_pkts", 535 "tx_128_to_255_pkts", 536 "tx_256_to_511_pkts", 537 "tx_512_to_1023_pkts", 538 "tx_1024_to_15xx_pkts", 539 "tx_ge_15xx_pkts", 540 "tx_errors", 541 "tx_sgl_col_pkts", 542 "tx_mult_col_pkts", 543 "tx_ex_col_pkts", 544 "tx_late_col_pkts", 545 "tx_def_pkts", 546 "tx_ex_def_pkts", 547 "pm_trunc_bb_overflow", 548 "pm_discard_bb_overflow", 549 "pm_trunc_vfifo_full", 550 "pm_discard_vfifo_full", 551 "pm_trunc_qbb", 552 "pm_discard_qbb", 553 "pm_discard_mapping", 554 "rxdp_q_disabled_pkts", 555 "rxdp_di_dropped_pkts", 556 "rxdp_streaming_pkts", 557 "rxdp_hlb_fetch", 558 "rxdp_hlb_wait", 559 "vadapter_rx_unicast_packets", 560 "vadapter_rx_unicast_bytes", 561 "vadapter_rx_multicast_packets", 562 "vadapter_rx_multicast_bytes", 563 "vadapter_rx_broadcast_packets", 564 "vadapter_rx_broadcast_bytes", 565 "vadapter_rx_bad_packets", 566 "vadapter_rx_bad_bytes", 567 "vadapter_rx_overflow", 568 "vadapter_tx_unicast_packets", 569 "vadapter_tx_unicast_bytes", 570 "vadapter_tx_multicast_packets", 571 "vadapter_tx_multicast_bytes", 572 "vadapter_tx_broadcast_packets", 573 "vadapter_tx_broadcast_bytes", 574 "vadapter_tx_bad_packets", 575 "vadapter_tx_bad_bytes", 576 "vadapter_tx_overflow", 577 }; 578 /* END MKCONFIG GENERATED EfxMacStatNamesBlock */ 579 580 __checkReturn const char * 581 efx_mac_stat_name( 582 __in efx_nic_t *enp, 583 __in unsigned int id) 584 { 585 _NOTE(ARGUNUSED(enp)) 586 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 587 588 EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS); 589 return (__efx_mac_stat_name[id]); 590 } 591 592 #endif /* EFSYS_OPT_NAMES */ 593 594 __checkReturn efx_rc_t 595 efx_mac_stats_upload( 596 __in efx_nic_t *enp, 597 __in efsys_mem_t *esmp) 598 { 599 efx_port_t *epp = &(enp->en_port); 600 const efx_mac_ops_t *emop = epp->ep_emop; 601 efx_rc_t rc; 602 603 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 604 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 605 EFSYS_ASSERT(emop != NULL); 606 607 /* 608 * Don't assert !ep_mac_stats_pending, because the client might 609 * have failed to finalise statistics when previously stopping 610 * the port. 611 */ 612 if ((rc = emop->emo_stats_upload(enp, esmp)) != 0) 613 goto fail1; 614 615 epp->ep_mac_stats_pending = B_TRUE; 616 617 return (0); 618 619 fail1: 620 EFSYS_PROBE1(fail1, efx_rc_t, rc); 621 622 return (rc); 623 } 624 625 __checkReturn efx_rc_t 626 efx_mac_stats_periodic( 627 __in efx_nic_t *enp, 628 __in efsys_mem_t *esmp, 629 __in uint16_t period_ms, 630 __in boolean_t events) 631 { 632 efx_port_t *epp = &(enp->en_port); 633 const efx_mac_ops_t *emop = epp->ep_emop; 634 efx_rc_t rc; 635 636 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 637 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 638 639 EFSYS_ASSERT(emop != NULL); 640 641 if (emop->emo_stats_periodic == NULL) { 642 rc = EINVAL; 643 goto fail1; 644 } 645 646 if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0) 647 goto fail2; 648 649 return (0); 650 651 fail2: 652 EFSYS_PROBE(fail2); 653 fail1: 654 EFSYS_PROBE1(fail1, efx_rc_t, rc); 655 656 return (rc); 657 } 658 659 660 __checkReturn efx_rc_t 661 efx_mac_stats_update( 662 __in efx_nic_t *enp, 663 __in efsys_mem_t *esmp, 664 __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp, 665 __inout_opt uint32_t *generationp) 666 { 667 efx_port_t *epp = &(enp->en_port); 668 const efx_mac_ops_t *emop = epp->ep_emop; 669 efx_rc_t rc; 670 671 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 672 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 673 EFSYS_ASSERT(emop != NULL); 674 675 rc = emop->emo_stats_update(enp, esmp, essp, generationp); 676 if (rc == 0) 677 epp->ep_mac_stats_pending = B_FALSE; 678 679 return (rc); 680 } 681 682 #endif /* EFSYS_OPT_MAC_STATS */ 683 684 __checkReturn efx_rc_t 685 efx_mac_select( 686 __in efx_nic_t *enp) 687 { 688 efx_port_t *epp = &(enp->en_port); 689 efx_mac_type_t type = EFX_MAC_INVALID; 690 const efx_mac_ops_t *emop; 691 int rc = EINVAL; 692 693 switch (enp->en_family) { 694 #if EFSYS_OPT_SIENA 695 case EFX_FAMILY_SIENA: 696 emop = &__efx_siena_mac_ops; 697 type = EFX_MAC_SIENA; 698 break; 699 #endif /* EFSYS_OPT_SIENA */ 700 701 #if EFSYS_OPT_HUNTINGTON 702 case EFX_FAMILY_HUNTINGTON: 703 emop = &__efx_ef10_mac_ops; 704 type = EFX_MAC_HUNTINGTON; 705 break; 706 #endif /* EFSYS_OPT_HUNTINGTON */ 707 708 #if EFSYS_OPT_MEDFORD 709 case EFX_FAMILY_MEDFORD: 710 emop = &__efx_ef10_mac_ops; 711 type = EFX_MAC_MEDFORD; 712 break; 713 #endif /* EFSYS_OPT_MEDFORD */ 714 715 default: 716 rc = EINVAL; 717 goto fail1; 718 } 719 720 EFSYS_ASSERT(type != EFX_MAC_INVALID); 721 EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES); 722 EFSYS_ASSERT(emop != NULL); 723 724 epp->ep_emop = emop; 725 epp->ep_mac_type = type; 726 727 return (0); 728 729 fail1: 730 EFSYS_PROBE1(fail1, efx_rc_t, rc); 731 732 return (rc); 733 } 734 735 736 #if EFSYS_OPT_SIENA 737 738 #define EFX_MAC_HASH_BITS (1 << 8) 739 740 /* Compute the multicast hash as used on Falcon and Siena. */ 741 static void 742 siena_mac_multicast_hash_compute( 743 __in_ecount(6*count) uint8_t const *addrs, 744 __in int count, 745 __out efx_oword_t *hash_low, 746 __out efx_oword_t *hash_high) 747 { 748 uint32_t crc, index; 749 int i; 750 751 EFSYS_ASSERT(hash_low != NULL); 752 EFSYS_ASSERT(hash_high != NULL); 753 754 EFX_ZERO_OWORD(*hash_low); 755 EFX_ZERO_OWORD(*hash_high); 756 757 for (i = 0; i < count; i++) { 758 /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */ 759 crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN); 760 index = crc % EFX_MAC_HASH_BITS; 761 if (index < 128) { 762 EFX_SET_OWORD_BIT(*hash_low, index); 763 } else { 764 EFX_SET_OWORD_BIT(*hash_high, index - 128); 765 } 766 767 addrs += EFX_MAC_ADDR_LEN; 768 } 769 } 770 771 static __checkReturn efx_rc_t 772 siena_mac_multicast_list_set( 773 __in efx_nic_t *enp) 774 { 775 efx_port_t *epp = &(enp->en_port); 776 const efx_mac_ops_t *emop = epp->ep_emop; 777 efx_oword_t old_hash[2]; 778 efx_rc_t rc; 779 780 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 781 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 782 783 (void) memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash)); 784 785 siena_mac_multicast_hash_compute( 786 epp->ep_mulcst_addr_list, 787 epp->ep_mulcst_addr_count, 788 &epp->ep_multicst_hash[0], 789 &epp->ep_multicst_hash[1]); 790 791 if ((rc = emop->emo_reconfigure(enp)) != 0) 792 goto fail1; 793 794 return (0); 795 796 fail1: 797 EFSYS_PROBE1(fail1, efx_rc_t, rc); 798 799 (void) memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash)); 800 801 return (rc); 802 } 803 804 #endif /* EFSYS_OPT_SIENA */ 805