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