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