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