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