efx_mac.c revision 299609
156638Srwatson/*- 2196123Srwatson * Copyright (c) 2007-2015 Solarflare Communications Inc. 356638Srwatson * All rights reserved. 456638Srwatson * 556638Srwatson * Redistribution and use in source and binary forms, with or without 656638Srwatson * modification, are permitted provided that the following conditions are met: 756638Srwatson * 856638Srwatson * 1. Redistributions of source code must retain the above copyright notice, 956638Srwatson * this list of conditions and the following disclaimer. 1056638Srwatson * 2. Redistributions in binary form must reproduce the above copyright notice, 1156638Srwatson * this list of conditions and the following disclaimer in the documentation 1256638Srwatson * and/or other materials provided with the distribution. 1356638Srwatson * 1456638Srwatson * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1556638Srwatson * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 1656638Srwatson * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1756638Srwatson * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 1856638Srwatson * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 1956638Srwatson * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2056638Srwatson * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 2156638Srwatson * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 2256638Srwatson * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 2356638Srwatson * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 2456638Srwatson * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2556638Srwatson * 2667035Srwatson * The views and conclusions contained in the software and documentation are 2756638Srwatson * those of the authors and should not be interpreted as representing official 28196123Srwatson * policies, either expressed or implied, of the FreeBSD Project. 2956638Srwatson */ 3079531Sru 3156638Srwatson#include <sys/cdefs.h> 3256791Smpp__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/efx_mac.c 299609 2016-05-13 07:15:02Z arybchik $"); 3356791Smpp 3459514Sphantom#include "efx.h" 3575222Sru#include "efx_impl.h" 3656638Srwatson 3784306Sru#if EFSYS_OPT_SIENA 3884306Sru 39105671Srwatsonstatic __checkReturn efx_rc_t 4056638Srwatsonsiena_mac_multicast_list_set( 41196123Srwatson __in efx_nic_t *enp); 42196123Srwatson 43196123Srwatson#endif /* EFSYS_OPT_SIENA */ 44196123Srwatson 45196123Srwatson#if EFSYS_OPT_SIENA 4670481Srustatic const efx_mac_ops_t __efx_siena_mac_ops = { 47106432Srwatson NULL, /* emo_reset */ 48196123Srwatson siena_mac_poll, /* emo_poll */ 49196123Srwatson siena_mac_up, /* emo_up */ 50196123Srwatson siena_mac_reconfigure, /* emo_addr_set */ 51196123Srwatson siena_mac_reconfigure, /* emo_pdu_set */ 52196123Srwatson siena_mac_reconfigure, /* emo_reconfigure */ 53196123Srwatson siena_mac_multicast_list_set, /* emo_multicast_list_set */ 5470481Sru NULL, /* emo_filter_set_default_rxq */ 55196123Srwatson NULL, /* emo_filter_default_rxq_clear */ 56196123Srwatson#if EFSYS_OPT_LOOPBACK 57196123Srwatson siena_mac_loopback_set, /* emo_loopback_set */ 58196123Srwatson#endif /* EFSYS_OPT_LOOPBACK */ 59106432Srwatson#if EFSYS_OPT_MAC_STATS 60196123Srwatson efx_mcdi_mac_stats_upload, /* emo_stats_upload */ 61196123Srwatson efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */ 62196123Srwatson siena_mac_stats_update /* emo_stats_update */ 63196123Srwatson#endif /* EFSYS_OPT_MAC_STATS */ 64196123Srwatson}; 65196123Srwatson#endif /* EFSYS_OPT_SIENA */ 66196123Srwatson 67196123Srwatson#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 6856638Srwatsonstatic const efx_mac_ops_t __efx_ef10_mac_ops = { 69196123Srwatson NULL, /* emo_reset */ 70105829Schris ef10_mac_poll, /* emo_poll */ 71196123Srwatson ef10_mac_up, /* emo_up */ 72196123Srwatson ef10_mac_addr_set, /* emo_addr_set */ 73196123Srwatson ef10_mac_pdu_set, /* emo_pdu_set */ 74196123Srwatson ef10_mac_reconfigure, /* emo_reconfigure */ 75196123Srwatson ef10_mac_multicast_list_set, /* emo_multicast_list_set */ 76105829Schris ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */ 77196123Srwatson ef10_mac_filter_default_rxq_clear, 78196123Srwatson /* emo_filter_default_rxq_clear */ 79106432Srwatson#if EFSYS_OPT_LOOPBACK 80196123Srwatson ef10_mac_loopback_set, /* emo_loopback_set */ 81196123Srwatson#endif /* EFSYS_OPT_LOOPBACK */ 82196123Srwatson#if EFSYS_OPT_MAC_STATS 83196123Srwatson efx_mcdi_mac_stats_upload, /* emo_stats_upload */ 84196123Srwatson efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */ 85196123Srwatson ef10_mac_stats_update /* emo_stats_update */ 8656638Srwatson#endif /* EFSYS_OPT_MAC_STATS */ 87196123Srwatson}; 88196123Srwatson#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 89107826Sru 9056638Srwatson 91196123Srwatson __checkReturn efx_rc_t 92192410Sbruefferefx_mac_pdu_set( 93101554Srwatson __in efx_nic_t *enp, 94196123Srwatson __in size_t pdu) 95196123Srwatson{ 96196123Srwatson efx_port_t *epp = &(enp->en_port); 97196123Srwatson const efx_mac_ops_t *emop = epp->ep_emop; 9856638Srwatson uint32_t old_pdu; 99105671Srwatson efx_rc_t rc; 100105671Srwatson 10156638Srwatson EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 102105829Schris EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 10356638Srwatson EFSYS_ASSERT(emop != NULL); 10456791Smpp 105106432Srwatson if (pdu < EFX_MAC_PDU_MIN) { 106196123Srwatson rc = EINVAL; 107106432Srwatson goto fail1; 10856638Srwatson } 10983327Sru 11083327Sru if (pdu > EFX_MAC_PDU_MAX) { 11183327Sru rc = EINVAL; 11256791Smpp goto fail2; 113 } 114 115 old_pdu = epp->ep_mac_pdu; 116 epp->ep_mac_pdu = (uint32_t)pdu; 117 if ((rc = emop->emo_pdu_set(enp)) != 0) 118 goto fail3; 119 120 return (0); 121 122fail3: 123 EFSYS_PROBE(fail3); 124 125 epp->ep_mac_pdu = old_pdu; 126 127fail2: 128 EFSYS_PROBE(fail2); 129fail1: 130 EFSYS_PROBE1(fail1, efx_rc_t, rc); 131 132 return (rc); 133} 134 135 __checkReturn efx_rc_t 136efx_mac_addr_set( 137 __in efx_nic_t *enp, 138 __in uint8_t *addr) 139{ 140 efx_port_t *epp = &(enp->en_port); 141 const efx_mac_ops_t *emop = epp->ep_emop; 142 uint8_t old_addr[6]; 143 uint32_t oui; 144 efx_rc_t rc; 145 146 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 147 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 148 149 if (EFX_MAC_ADDR_IS_MULTICAST(addr)) { 150 rc = EINVAL; 151 goto fail1; 152 } 153 154 oui = addr[0] << 16 | addr[1] << 8 | addr[2]; 155 if (oui == 0x000000) { 156 rc = EINVAL; 157 goto fail2; 158 } 159 160 EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr); 161 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr); 162 if ((rc = emop->emo_addr_set(enp)) != 0) 163 goto fail3; 164 165 return (0); 166 167fail3: 168 EFSYS_PROBE(fail3); 169 170 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr); 171 172fail2: 173 EFSYS_PROBE(fail2); 174fail1: 175 EFSYS_PROBE1(fail1, efx_rc_t, rc); 176 177 return (rc); 178} 179 180 __checkReturn efx_rc_t 181efx_mac_filter_set( 182 __in efx_nic_t *enp, 183 __in boolean_t all_unicst, 184 __in boolean_t mulcst, 185 __in boolean_t all_mulcst, 186 __in boolean_t brdcst) 187{ 188 efx_port_t *epp = &(enp->en_port); 189 const efx_mac_ops_t *emop = epp->ep_emop; 190 boolean_t old_all_unicst; 191 boolean_t old_mulcst; 192 boolean_t old_all_mulcst; 193 boolean_t old_brdcst; 194 efx_rc_t rc; 195 196 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 197 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 198 199 old_all_unicst = epp->ep_all_unicst; 200 old_mulcst = epp->ep_mulcst; 201 old_all_mulcst = epp->ep_all_mulcst; 202 old_brdcst = epp->ep_brdcst; 203 204 epp->ep_all_unicst = all_unicst; 205 epp->ep_mulcst = mulcst; 206 epp->ep_all_mulcst = all_mulcst; 207 epp->ep_brdcst = brdcst; 208 209 if ((rc = emop->emo_reconfigure(enp)) != 0) 210 goto fail1; 211 212 return (0); 213 214fail1: 215 EFSYS_PROBE1(fail1, efx_rc_t, rc); 216 217 epp->ep_all_unicst = old_all_unicst; 218 epp->ep_mulcst = old_mulcst; 219 epp->ep_all_mulcst = old_all_mulcst; 220 epp->ep_brdcst = old_brdcst; 221 222 return (rc); 223} 224 225 __checkReturn efx_rc_t 226efx_mac_drain( 227 __in efx_nic_t *enp, 228 __in boolean_t enabled) 229{ 230 efx_port_t *epp = &(enp->en_port); 231 const efx_mac_ops_t *emop = epp->ep_emop; 232 efx_rc_t rc; 233 234 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 235 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 236 EFSYS_ASSERT(emop != NULL); 237 238 if (epp->ep_mac_drain == enabled) 239 return (0); 240 241 epp->ep_mac_drain = enabled; 242 243 if (enabled && emop->emo_reset != NULL) { 244 if ((rc = emop->emo_reset(enp)) != 0) 245 goto fail1; 246 247 EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC); 248 enp->en_reset_flags &= ~EFX_RESET_PHY; 249 } 250 251 if ((rc = emop->emo_reconfigure(enp)) != 0) 252 goto fail2; 253 254 return (0); 255 256fail2: 257 EFSYS_PROBE(fail2); 258fail1: 259 EFSYS_PROBE1(fail1, efx_rc_t, rc); 260 261 return (rc); 262} 263 264 __checkReturn efx_rc_t 265efx_mac_up( 266 __in efx_nic_t *enp, 267 __out boolean_t *mac_upp) 268{ 269 efx_port_t *epp = &(enp->en_port); 270 const efx_mac_ops_t *emop = epp->ep_emop; 271 efx_rc_t rc; 272 273 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 274 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 275 276 if ((rc = emop->emo_up(enp, mac_upp)) != 0) 277 goto fail1; 278 279 return (0); 280 281fail1: 282 EFSYS_PROBE1(fail1, efx_rc_t, rc); 283 284 return (rc); 285} 286 287 __checkReturn efx_rc_t 288efx_mac_fcntl_set( 289 __in efx_nic_t *enp, 290 __in unsigned int fcntl, 291 __in boolean_t autoneg) 292{ 293 efx_port_t *epp = &(enp->en_port); 294 const efx_mac_ops_t *emop = epp->ep_emop; 295 const efx_phy_ops_t *epop = epp->ep_epop; 296 unsigned int old_fcntl; 297 boolean_t old_autoneg; 298 unsigned int old_adv_cap; 299 efx_rc_t rc; 300 301 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 302 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 303 304 if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) { 305 rc = EINVAL; 306 goto fail1; 307 } 308 309 /* 310 * Ignore a request to set flow control auto-negotiation 311 * if the PHY doesn't support it. 312 */ 313 if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) 314 autoneg = B_FALSE; 315 316 old_fcntl = epp->ep_fcntl; 317 old_autoneg = epp->ep_fcntl_autoneg; 318 old_adv_cap = epp->ep_adv_cap_mask; 319 320 epp->ep_fcntl = fcntl; 321 epp->ep_fcntl_autoneg = autoneg; 322 323 /* 324 * Always encode the flow control settings in the advertised 325 * capabilities even if we are not trying to auto-negotiate 326 * them and reconfigure both the PHY and the MAC. 327 */ 328 if (fcntl & EFX_FCNTL_RESPOND) 329 epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE | 330 1 << EFX_PHY_CAP_ASYM); 331 else 332 epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE | 333 1 << EFX_PHY_CAP_ASYM); 334 335 if (fcntl & EFX_FCNTL_GENERATE) 336 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM); 337 338 if ((rc = epop->epo_reconfigure(enp)) != 0) 339 goto fail2; 340 341 if ((rc = emop->emo_reconfigure(enp)) != 0) 342 goto fail3; 343 344 return (0); 345 346fail3: 347 EFSYS_PROBE(fail3); 348 349fail2: 350 EFSYS_PROBE(fail2); 351 352 epp->ep_fcntl = old_fcntl; 353 epp->ep_fcntl_autoneg = old_autoneg; 354 epp->ep_adv_cap_mask = old_adv_cap; 355 356fail1: 357 EFSYS_PROBE1(fail1, efx_rc_t, rc); 358 359 return (rc); 360} 361 362 void 363efx_mac_fcntl_get( 364 __in efx_nic_t *enp, 365 __out unsigned int *fcntl_wantedp, 366 __out unsigned int *fcntl_linkp) 367{ 368 efx_port_t *epp = &(enp->en_port); 369 unsigned int wanted = 0; 370 371 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 372 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 373 374 /* 375 * Decode the requested flow control settings from the PHY 376 * advertised capabilities. 377 */ 378 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE)) 379 wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 380 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM)) 381 wanted ^= EFX_FCNTL_GENERATE; 382 383 *fcntl_linkp = epp->ep_fcntl; 384 *fcntl_wantedp = wanted; 385} 386 387 __checkReturn efx_rc_t 388efx_mac_multicast_list_set( 389 __in efx_nic_t *enp, 390 __in_ecount(6*count) uint8_t const *addrs, 391 __in int count) 392{ 393 efx_port_t *epp = &(enp->en_port); 394 const efx_mac_ops_t *emop = epp->ep_emop; 395 uint8_t *old_mulcst_addr_list = NULL; 396 uint32_t old_mulcst_addr_count; 397 efx_rc_t rc; 398 399 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 400 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 401 402 if (count > EFX_MAC_MULTICAST_LIST_MAX) { 403 rc = EINVAL; 404 goto fail1; 405 } 406 407 old_mulcst_addr_count = epp->ep_mulcst_addr_count; 408 if (old_mulcst_addr_count > 0) { 409 /* Allocate memory to store old list (instead of using stack) */ 410 EFSYS_KMEM_ALLOC(enp->en_esip, 411 old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 412 old_mulcst_addr_list); 413 if (old_mulcst_addr_list == NULL) { 414 rc = ENOMEM; 415 goto fail2; 416 } 417 418 /* Save the old list in case we need to rollback */ 419 memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list, 420 old_mulcst_addr_count * EFX_MAC_ADDR_LEN); 421 } 422 423 /* Store the new list */ 424 memcpy(epp->ep_mulcst_addr_list, addrs, 425 count * EFX_MAC_ADDR_LEN); 426 epp->ep_mulcst_addr_count = count; 427 428 if ((rc = emop->emo_multicast_list_set(enp)) != 0) 429 goto fail3; 430 431 if (old_mulcst_addr_count > 0) { 432 EFSYS_KMEM_FREE(enp->en_esip, 433 old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 434 old_mulcst_addr_list); 435 } 436 437 return (0); 438 439fail3: 440 EFSYS_PROBE(fail3); 441 442 /* Restore original list on failure */ 443 epp->ep_mulcst_addr_count = old_mulcst_addr_count; 444 if (old_mulcst_addr_count > 0) { 445 memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list, 446 old_mulcst_addr_count * EFX_MAC_ADDR_LEN); 447 448 EFSYS_KMEM_FREE(enp->en_esip, 449 old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 450 old_mulcst_addr_list); 451 } 452 453fail2: 454 EFSYS_PROBE(fail2); 455 456fail1: 457 EFSYS_PROBE1(fail1, efx_rc_t, rc); 458 459 return (rc); 460 461} 462 463 __checkReturn efx_rc_t 464efx_mac_filter_default_rxq_set( 465 __in efx_nic_t *enp, 466 __in efx_rxq_t *erp, 467 __in boolean_t using_rss) 468{ 469 efx_port_t *epp = &(enp->en_port); 470 const efx_mac_ops_t *emop = epp->ep_emop; 471 efx_rc_t rc; 472 473 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 474 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 475 476 if (emop->emo_filter_default_rxq_set != NULL) { 477 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss); 478 if (rc != 0) 479 goto fail1; 480 } 481 482 return (0); 483 484fail1: 485 EFSYS_PROBE1(fail1, efx_rc_t, rc); 486 487 return (rc); 488} 489 490 void 491efx_mac_filter_default_rxq_clear( 492 __in efx_nic_t *enp) 493{ 494 efx_port_t *epp = &(enp->en_port); 495 const efx_mac_ops_t *emop = epp->ep_emop; 496 497 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 498 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 499 500 if (emop->emo_filter_default_rxq_clear != NULL) 501 emop->emo_filter_default_rxq_clear(enp); 502} 503 504 505#if EFSYS_OPT_MAC_STATS 506 507#if EFSYS_OPT_NAMES 508 509/* START MKCONFIG GENERATED EfxMacStatNamesBlock 054d43a31d2d7a45 */ 510static const char *__efx_mac_stat_name[] = { 511 "rx_octets", 512 "rx_pkts", 513 "rx_unicst_pkts", 514 "rx_multicst_pkts", 515 "rx_brdcst_pkts", 516 "rx_pause_pkts", 517 "rx_le_64_pkts", 518 "rx_65_to_127_pkts", 519 "rx_128_to_255_pkts", 520 "rx_256_to_511_pkts", 521 "rx_512_to_1023_pkts", 522 "rx_1024_to_15xx_pkts", 523 "rx_ge_15xx_pkts", 524 "rx_errors", 525 "rx_fcs_errors", 526 "rx_drop_events", 527 "rx_false_carrier_errors", 528 "rx_symbol_errors", 529 "rx_align_errors", 530 "rx_internal_errors", 531 "rx_jabber_pkts", 532 "rx_lane0_char_err", 533 "rx_lane1_char_err", 534 "rx_lane2_char_err", 535 "rx_lane3_char_err", 536 "rx_lane0_disp_err", 537 "rx_lane1_disp_err", 538 "rx_lane2_disp_err", 539 "rx_lane3_disp_err", 540 "rx_match_fault", 541 "rx_nodesc_drop_cnt", 542 "tx_octets", 543 "tx_pkts", 544 "tx_unicst_pkts", 545 "tx_multicst_pkts", 546 "tx_brdcst_pkts", 547 "tx_pause_pkts", 548 "tx_le_64_pkts", 549 "tx_65_to_127_pkts", 550 "tx_128_to_255_pkts", 551 "tx_256_to_511_pkts", 552 "tx_512_to_1023_pkts", 553 "tx_1024_to_15xx_pkts", 554 "tx_ge_15xx_pkts", 555 "tx_errors", 556 "tx_sgl_col_pkts", 557 "tx_mult_col_pkts", 558 "tx_ex_col_pkts", 559 "tx_late_col_pkts", 560 "tx_def_pkts", 561 "tx_ex_def_pkts", 562 "pm_trunc_bb_overflow", 563 "pm_discard_bb_overflow", 564 "pm_trunc_vfifo_full", 565 "pm_discard_vfifo_full", 566 "pm_trunc_qbb", 567 "pm_discard_qbb", 568 "pm_discard_mapping", 569 "rxdp_q_disabled_pkts", 570 "rxdp_di_dropped_pkts", 571 "rxdp_streaming_pkts", 572 "rxdp_hlb_fetch", 573 "rxdp_hlb_wait", 574 "vadapter_rx_unicast_packets", 575 "vadapter_rx_unicast_bytes", 576 "vadapter_rx_multicast_packets", 577 "vadapter_rx_multicast_bytes", 578 "vadapter_rx_broadcast_packets", 579 "vadapter_rx_broadcast_bytes", 580 "vadapter_rx_bad_packets", 581 "vadapter_rx_bad_bytes", 582 "vadapter_rx_overflow", 583 "vadapter_tx_unicast_packets", 584 "vadapter_tx_unicast_bytes", 585 "vadapter_tx_multicast_packets", 586 "vadapter_tx_multicast_bytes", 587 "vadapter_tx_broadcast_packets", 588 "vadapter_tx_broadcast_bytes", 589 "vadapter_tx_bad_packets", 590 "vadapter_tx_bad_bytes", 591 "vadapter_tx_overflow", 592}; 593/* END MKCONFIG GENERATED EfxMacStatNamesBlock */ 594 595 __checkReturn const char * 596efx_mac_stat_name( 597 __in efx_nic_t *enp, 598 __in unsigned int id) 599{ 600 _NOTE(ARGUNUSED(enp)) 601 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 602 603 EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS); 604 return (__efx_mac_stat_name[id]); 605} 606 607#endif /* EFSYS_OPT_NAMES */ 608 609 __checkReturn efx_rc_t 610efx_mac_stats_upload( 611 __in efx_nic_t *enp, 612 __in efsys_mem_t *esmp) 613{ 614 efx_port_t *epp = &(enp->en_port); 615 const efx_mac_ops_t *emop = epp->ep_emop; 616 efx_rc_t rc; 617 618 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 619 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 620 EFSYS_ASSERT(emop != NULL); 621 622 /* 623 * Don't assert !ep_mac_stats_pending, because the client might 624 * have failed to finalise statistics when previously stopping 625 * the port. 626 */ 627 if ((rc = emop->emo_stats_upload(enp, esmp)) != 0) 628 goto fail1; 629 630 epp->ep_mac_stats_pending = B_TRUE; 631 632 return (0); 633 634fail1: 635 EFSYS_PROBE1(fail1, efx_rc_t, rc); 636 637 return (rc); 638} 639 640 __checkReturn efx_rc_t 641efx_mac_stats_periodic( 642 __in efx_nic_t *enp, 643 __in efsys_mem_t *esmp, 644 __in uint16_t period_ms, 645 __in boolean_t events) 646{ 647 efx_port_t *epp = &(enp->en_port); 648 const efx_mac_ops_t *emop = epp->ep_emop; 649 efx_rc_t rc; 650 651 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 652 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 653 654 EFSYS_ASSERT(emop != NULL); 655 656 if (emop->emo_stats_periodic == NULL) { 657 rc = EINVAL; 658 goto fail1; 659 } 660 661 if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0) 662 goto fail2; 663 664 return (0); 665 666fail2: 667 EFSYS_PROBE(fail2); 668fail1: 669 EFSYS_PROBE1(fail1, efx_rc_t, rc); 670 671 return (rc); 672} 673 674 675 __checkReturn efx_rc_t 676efx_mac_stats_update( 677 __in efx_nic_t *enp, 678 __in efsys_mem_t *esmp, 679 __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp, 680 __inout_opt uint32_t *generationp) 681{ 682 efx_port_t *epp = &(enp->en_port); 683 const efx_mac_ops_t *emop = epp->ep_emop; 684 efx_rc_t rc; 685 686 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 687 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 688 EFSYS_ASSERT(emop != NULL); 689 690 rc = emop->emo_stats_update(enp, esmp, essp, generationp); 691 if (rc == 0) 692 epp->ep_mac_stats_pending = B_FALSE; 693 694 return (rc); 695} 696 697#endif /* EFSYS_OPT_MAC_STATS */ 698 699 __checkReturn efx_rc_t 700efx_mac_select( 701 __in efx_nic_t *enp) 702{ 703 efx_port_t *epp = &(enp->en_port); 704 efx_mac_type_t type = EFX_MAC_INVALID; 705 const efx_mac_ops_t *emop; 706 int rc = EINVAL; 707 708 switch (enp->en_family) { 709#if EFSYS_OPT_SIENA 710 case EFX_FAMILY_SIENA: 711 emop = &__efx_siena_mac_ops; 712 type = EFX_MAC_SIENA; 713 break; 714#endif /* EFSYS_OPT_SIENA */ 715 716#if EFSYS_OPT_HUNTINGTON 717 case EFX_FAMILY_HUNTINGTON: 718 emop = &__efx_ef10_mac_ops; 719 type = EFX_MAC_HUNTINGTON; 720 break; 721#endif /* EFSYS_OPT_HUNTINGTON */ 722 723#if EFSYS_OPT_MEDFORD 724 case EFX_FAMILY_MEDFORD: 725 emop = &__efx_ef10_mac_ops; 726 type = EFX_MAC_MEDFORD; 727 break; 728#endif /* EFSYS_OPT_MEDFORD */ 729 730 default: 731 rc = EINVAL; 732 goto fail1; 733 } 734 735 EFSYS_ASSERT(type != EFX_MAC_INVALID); 736 EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES); 737 EFSYS_ASSERT(emop != NULL); 738 739 epp->ep_emop = emop; 740 epp->ep_mac_type = type; 741 742 if (emop->emo_reset != NULL) { 743 if ((rc = emop->emo_reset(enp)) != 0) 744 goto fail2; 745 746 EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC); 747 enp->en_reset_flags &= ~EFX_RESET_MAC; 748 } 749 750 return (0); 751 752fail2: 753 EFSYS_PROBE(fail2); 754fail1: 755 EFSYS_PROBE1(fail1, efx_rc_t, rc); 756 757 return (rc); 758} 759 760 761#if EFSYS_OPT_SIENA 762 763#define EFX_MAC_HASH_BITS (1 << 8) 764 765/* Compute the multicast hash as used on Falcon and Siena. */ 766static void 767siena_mac_multicast_hash_compute( 768 __in_ecount(6*count) uint8_t const *addrs, 769 __in int count, 770 __out efx_oword_t *hash_low, 771 __out efx_oword_t *hash_high) 772{ 773 uint32_t crc, index; 774 int i; 775 776 EFSYS_ASSERT(hash_low != NULL); 777 EFSYS_ASSERT(hash_high != NULL); 778 779 EFX_ZERO_OWORD(*hash_low); 780 EFX_ZERO_OWORD(*hash_high); 781 782 for (i = 0; i < count; i++) { 783 /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */ 784 crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN); 785 index = crc % EFX_MAC_HASH_BITS; 786 if (index < 128) { 787 EFX_SET_OWORD_BIT(*hash_low, index); 788 } else { 789 EFX_SET_OWORD_BIT(*hash_high, index - 128); 790 } 791 792 addrs += EFX_MAC_ADDR_LEN; 793 } 794} 795 796static __checkReturn efx_rc_t 797siena_mac_multicast_list_set( 798 __in efx_nic_t *enp) 799{ 800 efx_port_t *epp = &(enp->en_port); 801 const efx_mac_ops_t *emop = epp->ep_emop; 802 efx_oword_t old_hash[2]; 803 efx_rc_t rc; 804 805 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 806 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 807 808 memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash)); 809 810 siena_mac_multicast_hash_compute( 811 epp->ep_mulcst_addr_list, 812 epp->ep_mulcst_addr_count, 813 &epp->ep_multicst_hash[0], 814 &epp->ep_multicst_hash[1]); 815 816 if ((rc = emop->emo_reconfigure(enp)) != 0) 817 goto fail1; 818 819 return (0); 820 821fail1: 822 EFSYS_PROBE1(fail1, efx_rc_t, rc); 823 824 memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash)); 825 826 return (rc); 827} 828 829#endif /* EFSYS_OPT_SIENA */ 830