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