28 29#include "efsys.h" 30#include "efx.h" 31#include "efx_types.h" 32#include "efx_impl.h" 33 34#if EFSYS_OPT_MAC_FALCON_GMAC 35#include "falcon_gmac.h" 36#endif 37 38#if EFSYS_OPT_MAC_FALCON_XMAC 39#include "falcon_xmac.h" 40#endif 41 42#if EFSYS_OPT_MAC_FALCON_GMAC 43static efx_mac_ops_t __cs __efx_falcon_gmac_ops = { 44 falcon_gmac_reset, /* emo_reset */ 45 falcon_mac_poll, /* emo_poll */ 46 falcon_mac_up, /* emo_up */ 47 falcon_gmac_reconfigure, /* emo_reconfigure */ 48#if EFSYS_OPT_LOOPBACK 49 falcon_mac_loopback_set, /* emo_loopback_set */ 50#endif /* EFSYS_OPT_LOOPBACK */ 51#if EFSYS_OPT_MAC_STATS 52 falcon_mac_stats_upload, /* emo_stats_upload */ 53 NULL, /* emo_stats_periodic */ 54 falcon_gmac_stats_update /* emo_stats_update */ 55#endif /* EFSYS_OPT_MAC_STATS */ 56}; 57#endif /* EFSYS_OPT_MAC_FALCON_GMAC */ 58 59#if EFSYS_OPT_MAC_FALCON_XMAC 60static efx_mac_ops_t __cs __efx_falcon_xmac_ops = { 61 falcon_xmac_reset, /* emo_reset */ 62 falcon_mac_poll, /* emo_poll */ 63 falcon_mac_up, /* emo_up */ 64 falcon_xmac_reconfigure, /* emo_reconfigure */ 65#if EFSYS_OPT_LOOPBACK 66 falcon_mac_loopback_set, /* emo_loopback_set */ 67#endif /* EFSYS_OPT_LOOPBACK */ 68#if EFSYS_OPT_MAC_STATS 69 falcon_mac_stats_upload, /* emo_stats_upload */ 70 NULL, /* emo_stats_periodic */ 71 falcon_xmac_stats_update /* emo_stats_update */ 72#endif /* EFSYS_OPT_MAC_STATS */ 73}; 74#endif /* EFSYS_OPT_MAC_FALCON_XMAC */ 75 76#if EFSYS_OPT_SIENA 77static efx_mac_ops_t __cs __efx_siena_mac_ops = { 78 NULL, /* emo_reset */ 79 siena_mac_poll, /* emo_poll */ 80 siena_mac_up, /* emo_up */ 81 siena_mac_reconfigure, /* emo_reconfigure */ 82#if EFSYS_OPT_LOOPBACK 83 siena_mac_loopback_set, /* emo_loopback_set */ 84#endif /* EFSYS_OPT_LOOPBACK */ 85#if EFSYS_OPT_MAC_STATS 86 siena_mac_stats_upload, /* emo_stats_upload */ 87 siena_mac_stats_periodic, /* emo_stats_periodic */ 88 siena_mac_stats_update /* emo_stats_update */ 89#endif /* EFSYS_OPT_MAC_STATS */ 90}; 91#endif /* EFSYS_OPT_SIENA */ 92 93static efx_mac_ops_t __cs * __cs __efx_mac_ops[] = { 94 NULL, 95#if EFSYS_OPT_MAC_FALCON_GMAC 96 &__efx_falcon_gmac_ops, 97#else 98 NULL, 99#endif /* EFSYS_OPT_MAC_FALCON_GMAC */ 100#if EFSYS_OPT_MAC_FALCON_XMAC 101 &__efx_falcon_xmac_ops, 102#else 103 NULL, 104#endif /* EFSYS_OPT_MAC_FALCON_XMAC */ 105#if EFSYS_OPT_SIENA 106 &__efx_siena_mac_ops, 107#else 108 NULL, 109#endif /* EFSYS_OPT_SIENA */ 110}; 111 112 __checkReturn int 113efx_mac_pdu_set( 114 __in efx_nic_t *enp, 115 __in size_t pdu) 116{ 117 efx_port_t *epp = &(enp->en_port); 118 efx_mac_ops_t *emop = epp->ep_emop; 119 uint32_t old_pdu; 120 int rc; 121 122 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 123 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 124 EFSYS_ASSERT(emop != NULL); 125 126 if (pdu < EFX_MAC_PDU_MIN) { 127 rc = EINVAL; 128 goto fail1; 129 } 130 131 if (pdu > EFX_MAC_PDU_MAX) { 132 rc = EINVAL; 133 goto fail2; 134 } 135 136 old_pdu = epp->ep_mac_pdu; 137 epp->ep_mac_pdu = (uint32_t)pdu; 138 if ((rc = emop->emo_reconfigure(enp)) != 0) 139 goto fail3; 140 141 return (0); 142 143fail3: 144 EFSYS_PROBE(fail3); 145 146 epp->ep_mac_pdu = old_pdu; 147 148fail2: 149 EFSYS_PROBE(fail2); 150fail1: 151 EFSYS_PROBE1(fail1, int, rc); 152 153 return (rc); 154} 155 156 __checkReturn int 157efx_mac_addr_set( 158 __in efx_nic_t *enp, 159 __in uint8_t *addr) 160{ 161 efx_port_t *epp = &(enp->en_port); 162 efx_mac_ops_t *emop = epp->ep_emop; 163 uint8_t old_addr[6]; 164 uint32_t oui; 165 int rc; 166 167 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 168 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 169 170 if (addr[0] & 0x01) { 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_reconfigure(enp)) != 0) 184 goto fail3; 185 186 return (0); 187 188fail3: 189 EFSYS_PROBE(fail3); 190 191 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr); 192 193fail2: 194 EFSYS_PROBE(fail2); 195fail1: 196 EFSYS_PROBE1(fail1, int, rc); 197 198 return (rc); 199} 200 201 __checkReturn int 202efx_mac_filter_set( 203 __in efx_nic_t *enp, 204 __in boolean_t unicst, 205 __in boolean_t brdcst) 206{ 207 efx_port_t *epp = &(enp->en_port); 208 efx_mac_ops_t *emop = epp->ep_emop; 209 boolean_t old_unicst; 210 boolean_t old_brdcst; 211 int rc; 212 213 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 214 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 215 216 old_unicst = unicst; 217 old_brdcst = brdcst; 218 219 epp->ep_unicst = unicst; 220 epp->ep_brdcst = brdcst; 221 222 if ((rc = emop->emo_reconfigure(enp)) != 0) 223 goto fail1; 224 225 return (0); 226 227fail1: 228 EFSYS_PROBE1(fail1, int, rc); 229 230 epp->ep_unicst = old_unicst; 231 epp->ep_brdcst = old_brdcst; 232 233 return (rc); 234} 235 236 __checkReturn int 237efx_mac_drain( 238 __in efx_nic_t *enp, 239 __in boolean_t enabled) 240{ 241 efx_port_t *epp = &(enp->en_port); 242 efx_mac_ops_t *emop = epp->ep_emop; 243 int 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 (enabled && emop->emo_reset != NULL) { 255 if ((rc = emop->emo_reset(enp)) != 0) 256 goto fail1; 257 258 EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC); 259 enp->en_reset_flags &= ~EFX_RESET_PHY; 260 } 261 262 if ((rc = emop->emo_reconfigure(enp)) != 0) 263 goto fail2; 264 265 return (0); 266 267fail2: 268 EFSYS_PROBE(fail2); 269fail1: 270 EFSYS_PROBE1(fail1, int, rc); 271 272 return (rc); 273} 274 275 __checkReturn int 276efx_mac_up( 277 __in efx_nic_t *enp, 278 __out boolean_t *mac_upp) 279{ 280 efx_port_t *epp = &(enp->en_port); 281 efx_mac_ops_t *emop = epp->ep_emop; 282 int 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 292fail1: 293 EFSYS_PROBE1(fail1, int, rc); 294 295 return (rc); 296} 297 298 __checkReturn int 299efx_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 efx_mac_ops_t *emop = epp->ep_emop; 306 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 int 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 autonegotiation 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 = 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 * If the PHY supports autonegotiation, then encode the flow control 336 * settings in the advertised capabilities, and restart AN. Otherwise, 337 * just push the new settings directly to the MAC. 338 */ 339 if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) { 340 if (fcntl & EFX_FCNTL_RESPOND) 341 epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE | 342 1 << EFX_PHY_CAP_ASYM); 343 else 344 epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE | 345 1 << EFX_PHY_CAP_ASYM); 346 347 if (fcntl & EFX_FCNTL_GENERATE) 348 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM); 349 350 if ((rc = epop->epo_reconfigure(enp)) != 0) 351 goto fail2; 352 353 } else { 354 if ((rc = emop->emo_reconfigure(enp)) != 0) 355 goto fail2; 356 } 357 358 return (0); 359 360fail2: 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 367fail1: 368 EFSYS_PROBE1(fail1, int, rc); 369 370 return (rc); 371} 372 373 void 374efx_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; 381 382 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 383 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 384 385 /* 386 * If the PHY supports auto negotiation, then the requested flow 387 * control settings are encoded in the advertised capabilities. 388 */ 389 if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) { 390 wanted = 0; 391 392 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE)) 393 wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 394 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM)) 395 wanted ^= EFX_FCNTL_GENERATE; 396 } else 397 wanted = epp->ep_fcntl; 398 399 *fcntl_linkp = epp->ep_fcntl; 400 *fcntl_wantedp = wanted; 401} 402 403 __checkReturn int 404efx_mac_hash_set( 405 __in efx_nic_t *enp, 406 __in_ecount(EFX_MAC_HASH_BITS) unsigned int const *bucket) 407{ 408 efx_port_t *epp = &(enp->en_port); 409 efx_mac_ops_t *emop = epp->ep_emop; 410 efx_oword_t old_hash[2]; 411 unsigned int index; 412 int rc; 413 414 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 415 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 416 417 memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash)); 418 419 /* Set the lower 128 bits of the hash */ 420 EFX_ZERO_OWORD(epp->ep_multicst_hash[0]); 421 for (index = 0; index < 128; index++) { 422 if (bucket[index] != 0) 423 EFX_SET_OWORD_BIT(epp->ep_multicst_hash[0], index); 424 } 425 426 /* Set the upper 128 bits of the hash */ 427 EFX_ZERO_OWORD(epp->ep_multicst_hash[1]); 428 for (index = 0; index < 128; index++) { 429 if (bucket[index + 128] != 0) 430 EFX_SET_OWORD_BIT(epp->ep_multicst_hash[1], index); 431 } 432 433 if ((rc = emop->emo_reconfigure(enp)) != 0) 434 goto fail1; 435 436 return (0); 437 438fail1: 439 EFSYS_PROBE1(fail1, int, rc); 440 441 memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash)); 442 443 return (rc); 444} 445 446#if EFSYS_OPT_MAC_STATS 447 448#if EFSYS_OPT_NAMES 449 450/* START MKCONFIG GENERATED EfxMacStatNamesBlock adf707adba80813e */ 451static const char __cs * __cs __efx_mac_stat_name[] = { 452 "rx_octets", 453 "rx_pkts", 454 "rx_unicst_pkts", 455 "rx_multicst_pkts", 456 "rx_brdcst_pkts", 457 "rx_pause_pkts", 458 "rx_le_64_pkts", 459 "rx_65_to_127_pkts", 460 "rx_128_to_255_pkts", 461 "rx_256_to_511_pkts", 462 "rx_512_to_1023_pkts", 463 "rx_1024_to_15xx_pkts", 464 "rx_ge_15xx_pkts", 465 "rx_errors", 466 "rx_fcs_errors", 467 "rx_drop_events", 468 "rx_false_carrier_errors", 469 "rx_symbol_errors", 470 "rx_align_errors", 471 "rx_internal_errors", 472 "rx_jabber_pkts", 473 "rx_lane0_char_err", 474 "rx_lane1_char_err", 475 "rx_lane2_char_err", 476 "rx_lane3_char_err", 477 "rx_lane0_disp_err", 478 "rx_lane1_disp_err", 479 "rx_lane2_disp_err", 480 "rx_lane3_disp_err", 481 "rx_match_fault", 482 "rx_nodesc_drop_cnt", 483 "tx_octets", 484 "tx_pkts", 485 "tx_unicst_pkts", 486 "tx_multicst_pkts", 487 "tx_brdcst_pkts", 488 "tx_pause_pkts", 489 "tx_le_64_pkts", 490 "tx_65_to_127_pkts", 491 "tx_128_to_255_pkts", 492 "tx_256_to_511_pkts", 493 "tx_512_to_1023_pkts", 494 "tx_1024_to_15xx_pkts", 495 "tx_ge_15xx_pkts", 496 "tx_errors", 497 "tx_sgl_col_pkts", 498 "tx_mult_col_pkts", 499 "tx_ex_col_pkts", 500 "tx_late_col_pkts", 501 "tx_def_pkts", 502 "tx_ex_def_pkts", 503}; 504/* END MKCONFIG GENERATED EfxMacStatNamesBlock */ 505 506 __checkReturn const char __cs * 507efx_mac_stat_name( 508 __in efx_nic_t *enp, 509 __in unsigned int id) 510{ 511 _NOTE(ARGUNUSED(enp)) 512 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 513 514 EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS); 515 return (__efx_mac_stat_name[id]); 516} 517 518#endif /* EFSYS_OPT_STAT_NAME */ 519 520 __checkReturn int 521efx_mac_stats_upload( 522 __in efx_nic_t *enp, 523 __in efsys_mem_t *esmp) 524{ 525 efx_port_t *epp = &(enp->en_port); 526 efx_mac_ops_t *emop = epp->ep_emop; 527 int rc; 528 529 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 530 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 531 EFSYS_ASSERT(emop != NULL); 532 533 /* 534 * Don't assert !ep_mac_stats_pending, because the client might 535 * have failed to finalise statistics when previously stopping 536 * the port. 537 */ 538 if ((rc = emop->emo_stats_upload(enp, esmp)) != 0) 539 goto fail1; 540 541 epp->ep_mac_stats_pending = B_TRUE; 542 543 return (0); 544 545fail1: 546 EFSYS_PROBE1(fail1, int, rc); 547 548 return (rc); 549} 550 551 __checkReturn int 552efx_mac_stats_periodic( 553 __in efx_nic_t *enp, 554 __in efsys_mem_t *esmp, 555 __in uint16_t period_ms, 556 __in boolean_t events) 557{ 558 efx_port_t *epp = &(enp->en_port); 559 efx_mac_ops_t *emop = epp->ep_emop; 560 int rc; 561 562 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 563 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 564 565 EFSYS_ASSERT(emop != NULL); 566 567 if (emop->emo_stats_periodic == NULL) { 568 rc = EINVAL; 569 goto fail1; 570 } 571 572 if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0) 573 goto fail2; 574 575 return (0); 576 577fail2: 578 EFSYS_PROBE(fail2); 579fail1: 580 EFSYS_PROBE1(fail1, int, rc); 581 582 return (rc); 583} 584 585 586 __checkReturn int 587efx_mac_stats_update( 588 __in efx_nic_t *enp, 589 __in efsys_mem_t *esmp, 590 __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp, 591 __in uint32_t *generationp) 592{ 593 efx_port_t *epp = &(enp->en_port); 594 efx_mac_ops_t *emop = epp->ep_emop; 595 int rc; 596 597 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 598 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 599 EFSYS_ASSERT(emop != NULL); 600 601 rc = emop->emo_stats_update(enp, esmp, essp, generationp); 602 if (rc == 0) 603 epp->ep_mac_stats_pending = B_FALSE; 604 605 return (rc); 606} 607 608#endif /* EFSYS_OPT_MAC_STATS */ 609 610 __checkReturn int 611efx_mac_select( 612 __in efx_nic_t *enp) 613{ 614 efx_port_t *epp = &(enp->en_port); 615 efx_mac_type_t type = EFX_MAC_INVALID; 616 efx_mac_ops_t *emop; 617 int rc = EINVAL; 618 619#if EFSYS_OPT_SIENA 620 if (enp->en_family == EFX_FAMILY_SIENA) { 621 type = EFX_MAC_SIENA; 622 goto chosen; 623 } 624#endif 625 626#if EFSYS_OPT_FALCON 627 switch (epp->ep_link_mode) { 628#if EFSYS_OPT_MAC_FALCON_GMAC 629 case EFX_LINK_100HDX: 630 case EFX_LINK_100FDX: 631 case EFX_LINK_1000HDX: 632 case EFX_LINK_1000FDX: 633 type = EFX_MAC_FALCON_GMAC; 634 goto chosen; 635#endif /* EFSYS_OPT_FALCON_GMAC */ 636 637#if EFSYS_OPT_MAC_FALCON_XMAC 638 case EFX_LINK_10000FDX: 639 type = EFX_MAC_FALCON_XMAC; 640 goto chosen; 641#endif /* EFSYS_OPT_FALCON_XMAC */ 642 643 default: 644#if EFSYS_OPT_MAC_FALCON_GMAC && EFSYS_OPT_MAC_FALCON_XMAC 645 /* Only initialise a MAC supported by the PHY */ 646 if (epp->ep_phy_cap_mask & 647 ((1 << EFX_PHY_CAP_1000FDX) | 648 (1 << EFX_PHY_CAP_1000HDX) | 649 (1 << EFX_PHY_CAP_100FDX) | 650 (1 << EFX_PHY_CAP_100HDX) | 651 (1 << EFX_PHY_CAP_10FDX) | 652 (1 << EFX_PHY_CAP_10FDX))) 653 type = EFX_MAC_FALCON_GMAC; 654 else 655 type = EFX_MAC_FALCON_XMAC; 656#elif EFSYS_OPT_MAC_FALCON_GMAC 657 type = EFX_MAC_FALCON_GMAC; 658#else 659 type = EFX_MAC_FALCON_XMAC; 660#endif 661 goto chosen; 662 } 663#endif /* EFSYS_OPT_FALCON */ 664 665chosen: 666 EFSYS_ASSERT(type != EFX_MAC_INVALID); 667 EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES); 668 emop = epp->ep_emop = (efx_mac_ops_t *)__efx_mac_ops[type]; 669 EFSYS_ASSERT(emop != NULL); 670 671 epp->ep_mac_type = type;
|