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