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