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