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