ef10_nic.c revision 293899
1/*- 2 * Copyright (c) 2012-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: head/sys/dev/sfxge/common/hunt_nic.c 293899 2016-01-14 09:12:40Z arybchik $"); 33 34#include "efx.h" 35#include "efx_impl.h" 36#if EFSYS_OPT_MON_MCDI 37#include "mcdi_mon.h" 38#endif 39 40#if EFSYS_OPT_HUNTINGTON 41 42#include "ef10_tlv_layout.h" 43 44 __checkReturn efx_rc_t 45efx_mcdi_get_port_assignment( 46 __in efx_nic_t *enp, 47 __out uint32_t *portp) 48{ 49 efx_mcdi_req_t req; 50 uint8_t payload[MAX(MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN, 51 MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN)]; 52 efx_rc_t rc; 53 54 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 55 enp->en_family == EFX_FAMILY_MEDFORD); 56 57 (void) memset(payload, 0, sizeof (payload)); 58 req.emr_cmd = MC_CMD_GET_PORT_ASSIGNMENT; 59 req.emr_in_buf = payload; 60 req.emr_in_length = MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN; 61 req.emr_out_buf = payload; 62 req.emr_out_length = MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN; 63 64 efx_mcdi_execute(enp, &req); 65 66 if (req.emr_rc != 0) { 67 rc = req.emr_rc; 68 goto fail1; 69 } 70 71 if (req.emr_out_length_used < MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN) { 72 rc = EMSGSIZE; 73 goto fail2; 74 } 75 76 *portp = MCDI_OUT_DWORD(req, GET_PORT_ASSIGNMENT_OUT_PORT); 77 78 return (0); 79 80fail2: 81 EFSYS_PROBE(fail2); 82fail1: 83 EFSYS_PROBE1(fail1, efx_rc_t, rc); 84 85 return (rc); 86} 87 88 __checkReturn efx_rc_t 89efx_mcdi_get_port_modes( 90 __in efx_nic_t *enp, 91 __out uint32_t *modesp) 92{ 93 efx_mcdi_req_t req; 94 uint8_t payload[MAX(MC_CMD_GET_PORT_MODES_IN_LEN, 95 MC_CMD_GET_PORT_MODES_OUT_LEN)]; 96 efx_rc_t rc; 97 98 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 99 enp->en_family == EFX_FAMILY_MEDFORD); 100 101 (void) memset(payload, 0, sizeof (payload)); 102 req.emr_cmd = MC_CMD_GET_PORT_MODES; 103 req.emr_in_buf = payload; 104 req.emr_in_length = MC_CMD_GET_PORT_MODES_IN_LEN; 105 req.emr_out_buf = payload; 106 req.emr_out_length = MC_CMD_GET_PORT_MODES_OUT_LEN; 107 108 efx_mcdi_execute(enp, &req); 109 110 if (req.emr_rc != 0) { 111 rc = req.emr_rc; 112 goto fail1; 113 } 114 115 /* 116 * Require only Modes and DefaultMode fields. 117 * (CurrentMode field was added for Medford) 118 */ 119 if (req.emr_out_length_used < 120 MC_CMD_GET_PORT_MODES_OUT_CURRENT_MODE_OFST) { 121 rc = EMSGSIZE; 122 goto fail2; 123 } 124 125 *modesp = MCDI_OUT_DWORD(req, GET_PORT_MODES_OUT_MODES); 126 127 return (0); 128 129fail2: 130 EFSYS_PROBE(fail2); 131fail1: 132 EFSYS_PROBE1(fail1, efx_rc_t, rc); 133 134 return (rc); 135} 136 137 138static __checkReturn efx_rc_t 139efx_mcdi_vadaptor_alloc( 140 __in efx_nic_t *enp, 141 __in uint32_t port_id) 142{ 143 efx_mcdi_req_t req; 144 uint8_t payload[MAX(MC_CMD_VADAPTOR_ALLOC_IN_LEN, 145 MC_CMD_VADAPTOR_ALLOC_OUT_LEN)]; 146 efx_rc_t rc; 147 148 EFSYS_ASSERT3U(enp->en_vport_id, ==, EVB_PORT_ID_NULL); 149 150 (void) memset(payload, 0, sizeof (payload)); 151 req.emr_cmd = MC_CMD_VADAPTOR_ALLOC; 152 req.emr_in_buf = payload; 153 req.emr_in_length = MC_CMD_VADAPTOR_ALLOC_IN_LEN; 154 req.emr_out_buf = payload; 155 req.emr_out_length = MC_CMD_VADAPTOR_ALLOC_OUT_LEN; 156 157 MCDI_IN_SET_DWORD(req, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id); 158 MCDI_IN_POPULATE_DWORD_1(req, VADAPTOR_ALLOC_IN_FLAGS, 159 VADAPTOR_ALLOC_IN_FLAG_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED, 160 enp->en_nic_cfg.enc_allow_set_mac_with_installed_filters ? 1 : 0); 161 162 efx_mcdi_execute(enp, &req); 163 164 if (req.emr_rc != 0) { 165 rc = req.emr_rc; 166 goto fail1; 167 } 168 169 return (0); 170 171fail1: 172 EFSYS_PROBE1(fail1, efx_rc_t, rc); 173 174 return (rc); 175} 176 177static __checkReturn efx_rc_t 178efx_mcdi_vadaptor_free( 179 __in efx_nic_t *enp, 180 __in uint32_t port_id) 181{ 182 efx_mcdi_req_t req; 183 uint8_t payload[MAX(MC_CMD_VADAPTOR_FREE_IN_LEN, 184 MC_CMD_VADAPTOR_FREE_OUT_LEN)]; 185 efx_rc_t rc; 186 187 (void) memset(payload, 0, sizeof (payload)); 188 req.emr_cmd = MC_CMD_VADAPTOR_FREE; 189 req.emr_in_buf = payload; 190 req.emr_in_length = MC_CMD_VADAPTOR_FREE_IN_LEN; 191 req.emr_out_buf = payload; 192 req.emr_out_length = MC_CMD_VADAPTOR_FREE_OUT_LEN; 193 194 MCDI_IN_SET_DWORD(req, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id); 195 196 efx_mcdi_execute(enp, &req); 197 198 if (req.emr_rc != 0) { 199 rc = req.emr_rc; 200 goto fail1; 201 } 202 203 return (0); 204 205fail1: 206 EFSYS_PROBE1(fail1, efx_rc_t, rc); 207 208 return (rc); 209} 210 211 __checkReturn efx_rc_t 212efx_mcdi_get_mac_address_pf( 213 __in efx_nic_t *enp, 214 __out_ecount_opt(6) uint8_t mac_addrp[6]) 215{ 216 efx_mcdi_req_t req; 217 uint8_t payload[MAX(MC_CMD_GET_MAC_ADDRESSES_IN_LEN, 218 MC_CMD_GET_MAC_ADDRESSES_OUT_LEN)]; 219 efx_rc_t rc; 220 221 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 222 enp->en_family == EFX_FAMILY_MEDFORD); 223 224 (void) memset(payload, 0, sizeof (payload)); 225 req.emr_cmd = MC_CMD_GET_MAC_ADDRESSES; 226 req.emr_in_buf = payload; 227 req.emr_in_length = MC_CMD_GET_MAC_ADDRESSES_IN_LEN; 228 req.emr_out_buf = payload; 229 req.emr_out_length = MC_CMD_GET_MAC_ADDRESSES_OUT_LEN; 230 231 efx_mcdi_execute(enp, &req); 232 233 if (req.emr_rc != 0) { 234 rc = req.emr_rc; 235 goto fail1; 236 } 237 238 if (req.emr_out_length_used < MC_CMD_GET_MAC_ADDRESSES_OUT_LEN) { 239 rc = EMSGSIZE; 240 goto fail2; 241 } 242 243 if (MCDI_OUT_DWORD(req, GET_MAC_ADDRESSES_OUT_MAC_COUNT) < 1) { 244 rc = ENOENT; 245 goto fail3; 246 } 247 248 if (mac_addrp != NULL) { 249 uint8_t *addrp; 250 251 addrp = MCDI_OUT2(req, uint8_t, 252 GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE); 253 254 EFX_MAC_ADDR_COPY(mac_addrp, addrp); 255 } 256 257 return (0); 258 259fail3: 260 EFSYS_PROBE(fail3); 261fail2: 262 EFSYS_PROBE(fail2); 263fail1: 264 EFSYS_PROBE1(fail1, efx_rc_t, rc); 265 266 return (rc); 267} 268 269 __checkReturn efx_rc_t 270efx_mcdi_get_mac_address_vf( 271 __in efx_nic_t *enp, 272 __out_ecount_opt(6) uint8_t mac_addrp[6]) 273{ 274 efx_mcdi_req_t req; 275 uint8_t payload[MAX(MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN, 276 MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX)]; 277 efx_rc_t rc; 278 279 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 280 enp->en_family == EFX_FAMILY_MEDFORD); 281 282 (void) memset(payload, 0, sizeof (payload)); 283 req.emr_cmd = MC_CMD_VPORT_GET_MAC_ADDRESSES; 284 req.emr_in_buf = payload; 285 req.emr_in_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN; 286 req.emr_out_buf = payload; 287 req.emr_out_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX; 288 289 MCDI_IN_SET_DWORD(req, VPORT_GET_MAC_ADDRESSES_IN_VPORT_ID, 290 EVB_PORT_ID_ASSIGNED); 291 292 efx_mcdi_execute(enp, &req); 293 294 if (req.emr_rc != 0) { 295 rc = req.emr_rc; 296 goto fail1; 297 } 298 299 if (req.emr_out_length_used < 300 MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMIN) { 301 rc = EMSGSIZE; 302 goto fail2; 303 } 304 305 if (MCDI_OUT_DWORD(req, 306 VPORT_GET_MAC_ADDRESSES_OUT_MACADDR_COUNT) < 1) { 307 rc = ENOENT; 308 goto fail3; 309 } 310 311 if (mac_addrp != NULL) { 312 uint8_t *addrp; 313 314 addrp = MCDI_OUT2(req, uint8_t, 315 VPORT_GET_MAC_ADDRESSES_OUT_MACADDR); 316 317 EFX_MAC_ADDR_COPY(mac_addrp, addrp); 318 } 319 320 return (0); 321 322fail3: 323 EFSYS_PROBE(fail3); 324fail2: 325 EFSYS_PROBE(fail2); 326fail1: 327 EFSYS_PROBE1(fail1, efx_rc_t, rc); 328 329 return (rc); 330} 331 332 __checkReturn efx_rc_t 333efx_mcdi_get_clock( 334 __in efx_nic_t *enp, 335 __out uint32_t *sys_freqp) 336{ 337 efx_mcdi_req_t req; 338 uint8_t payload[MAX(MC_CMD_GET_CLOCK_IN_LEN, 339 MC_CMD_GET_CLOCK_OUT_LEN)]; 340 efx_rc_t rc; 341 342 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 343 enp->en_family == EFX_FAMILY_MEDFORD); 344 345 (void) memset(payload, 0, sizeof (payload)); 346 req.emr_cmd = MC_CMD_GET_CLOCK; 347 req.emr_in_buf = payload; 348 req.emr_in_length = MC_CMD_GET_CLOCK_IN_LEN; 349 req.emr_out_buf = payload; 350 req.emr_out_length = MC_CMD_GET_CLOCK_OUT_LEN; 351 352 efx_mcdi_execute(enp, &req); 353 354 if (req.emr_rc != 0) { 355 rc = req.emr_rc; 356 goto fail1; 357 } 358 359 if (req.emr_out_length_used < MC_CMD_GET_CLOCK_OUT_LEN) { 360 rc = EMSGSIZE; 361 goto fail2; 362 } 363 364 *sys_freqp = MCDI_OUT_DWORD(req, GET_CLOCK_OUT_SYS_FREQ); 365 if (*sys_freqp == 0) { 366 rc = EINVAL; 367 goto fail3; 368 } 369 370 return (0); 371 372fail3: 373 EFSYS_PROBE(fail3); 374fail2: 375 EFSYS_PROBE(fail2); 376fail1: 377 EFSYS_PROBE1(fail1, efx_rc_t, rc); 378 379 return (rc); 380} 381 382 __checkReturn efx_rc_t 383efx_mcdi_get_vector_cfg( 384 __in efx_nic_t *enp, 385 __out_opt uint32_t *vec_basep, 386 __out_opt uint32_t *pf_nvecp, 387 __out_opt uint32_t *vf_nvecp) 388{ 389 efx_mcdi_req_t req; 390 uint8_t payload[MAX(MC_CMD_GET_VECTOR_CFG_IN_LEN, 391 MC_CMD_GET_VECTOR_CFG_OUT_LEN)]; 392 efx_rc_t rc; 393 394 (void) memset(payload, 0, sizeof (payload)); 395 req.emr_cmd = MC_CMD_GET_VECTOR_CFG; 396 req.emr_in_buf = payload; 397 req.emr_in_length = MC_CMD_GET_VECTOR_CFG_IN_LEN; 398 req.emr_out_buf = payload; 399 req.emr_out_length = MC_CMD_GET_VECTOR_CFG_OUT_LEN; 400 401 efx_mcdi_execute(enp, &req); 402 403 if (req.emr_rc != 0) { 404 rc = req.emr_rc; 405 goto fail1; 406 } 407 408 if (req.emr_out_length_used < MC_CMD_GET_VECTOR_CFG_OUT_LEN) { 409 rc = EMSGSIZE; 410 goto fail2; 411 } 412 413 if (vec_basep != NULL) 414 *vec_basep = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VEC_BASE); 415 if (pf_nvecp != NULL) 416 *pf_nvecp = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VECS_PER_PF); 417 if (vf_nvecp != NULL) 418 *vf_nvecp = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VECS_PER_VF); 419 420 return (0); 421 422fail2: 423 EFSYS_PROBE(fail2); 424fail1: 425 EFSYS_PROBE1(fail1, efx_rc_t, rc); 426 427 return (rc); 428} 429 430static __checkReturn efx_rc_t 431efx_mcdi_get_capabilities( 432 __in efx_nic_t *enp, 433 __out efx_dword_t *flagsp, 434 __out efx_dword_t *flags2p) 435{ 436 efx_mcdi_req_t req; 437 uint8_t payload[MAX(MC_CMD_GET_CAPABILITIES_IN_LEN, 438 MC_CMD_GET_CAPABILITIES_V2_OUT_LEN)]; 439 efx_rc_t rc; 440 441 (void) memset(payload, 0, sizeof (payload)); 442 req.emr_cmd = MC_CMD_GET_CAPABILITIES; 443 req.emr_in_buf = payload; 444 req.emr_in_length = MC_CMD_GET_CAPABILITIES_IN_LEN; 445 req.emr_out_buf = payload; 446 req.emr_out_length = MC_CMD_GET_CAPABILITIES_V2_OUT_LEN; 447 448 efx_mcdi_execute(enp, &req); 449 450 if (req.emr_rc != 0) { 451 rc = req.emr_rc; 452 goto fail1; 453 } 454 455 if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_OUT_LEN) { 456 rc = EMSGSIZE; 457 goto fail2; 458 } 459 460 *flagsp = *MCDI_OUT2(req, efx_dword_t, GET_CAPABILITIES_OUT_FLAGS1); 461 462 if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_V2_OUT_LEN) 463 EFX_ZERO_DWORD(*flags2p); 464 else 465 *flags2p = *MCDI_OUT2(req, efx_dword_t, 466 GET_CAPABILITIES_V2_OUT_FLAGS2); 467 468 return (0); 469 470fail2: 471 EFSYS_PROBE(fail2); 472fail1: 473 EFSYS_PROBE1(fail1, efx_rc_t, rc); 474 475 return (rc); 476} 477 478 479static __checkReturn efx_rc_t 480efx_mcdi_alloc_vis( 481 __in efx_nic_t *enp, 482 __in uint32_t min_vi_count, 483 __in uint32_t max_vi_count, 484 __out uint32_t *vi_basep, 485 __out uint32_t *vi_countp, 486 __out uint32_t *vi_shiftp) 487{ 488 efx_mcdi_req_t req; 489 uint8_t payload[MAX(MC_CMD_ALLOC_VIS_IN_LEN, 490 MC_CMD_ALLOC_VIS_OUT_LEN)]; 491 efx_rc_t rc; 492 493 if (vi_countp == NULL) { 494 rc = EINVAL; 495 goto fail1; 496 } 497 498 (void) memset(payload, 0, sizeof (payload)); 499 req.emr_cmd = MC_CMD_ALLOC_VIS; 500 req.emr_in_buf = payload; 501 req.emr_in_length = MC_CMD_ALLOC_VIS_IN_LEN; 502 req.emr_out_buf = payload; 503 req.emr_out_length = MC_CMD_ALLOC_VIS_OUT_LEN; 504 505 MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MIN_VI_COUNT, min_vi_count); 506 MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MAX_VI_COUNT, max_vi_count); 507 508 efx_mcdi_execute(enp, &req); 509 510 if (req.emr_rc != 0) { 511 rc = req.emr_rc; 512 goto fail2; 513 } 514 515 if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_OUT_LEN) { 516 rc = EMSGSIZE; 517 goto fail3; 518 } 519 520 *vi_basep = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_BASE); 521 *vi_countp = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_COUNT); 522 523 /* Report VI_SHIFT if available (always zero for Huntington) */ 524 if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_EXT_OUT_LEN) 525 *vi_shiftp = 0; 526 else 527 *vi_shiftp = MCDI_OUT_DWORD(req, ALLOC_VIS_EXT_OUT_VI_SHIFT); 528 529 return (0); 530 531fail3: 532 EFSYS_PROBE(fail3); 533fail2: 534 EFSYS_PROBE(fail2); 535fail1: 536 EFSYS_PROBE1(fail1, efx_rc_t, rc); 537 538 return (rc); 539} 540 541 542static __checkReturn efx_rc_t 543efx_mcdi_free_vis( 544 __in efx_nic_t *enp) 545{ 546 efx_mcdi_req_t req; 547 efx_rc_t rc; 548 549 EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_IN_LEN == 0); 550 EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_OUT_LEN == 0); 551 552 req.emr_cmd = MC_CMD_FREE_VIS; 553 req.emr_in_buf = NULL; 554 req.emr_in_length = 0; 555 req.emr_out_buf = NULL; 556 req.emr_out_length = 0; 557 558 efx_mcdi_execute_quiet(enp, &req); 559 560 /* Ignore ELREADY (no allocated VIs, so nothing to free) */ 561 if ((req.emr_rc != 0) && (req.emr_rc != EALREADY)) { 562 rc = req.emr_rc; 563 goto fail1; 564 } 565 566 return (0); 567 568fail1: 569 EFSYS_PROBE1(fail1, efx_rc_t, rc); 570 571 return (rc); 572} 573 574 575static __checkReturn efx_rc_t 576efx_mcdi_alloc_piobuf( 577 __in efx_nic_t *enp, 578 __out efx_piobuf_handle_t *handlep) 579{ 580 efx_mcdi_req_t req; 581 uint8_t payload[MAX(MC_CMD_ALLOC_PIOBUF_IN_LEN, 582 MC_CMD_ALLOC_PIOBUF_OUT_LEN)]; 583 efx_rc_t rc; 584 585 if (handlep == NULL) { 586 rc = EINVAL; 587 goto fail1; 588 } 589 590 (void) memset(payload, 0, sizeof (payload)); 591 req.emr_cmd = MC_CMD_ALLOC_PIOBUF; 592 req.emr_in_buf = payload; 593 req.emr_in_length = MC_CMD_ALLOC_PIOBUF_IN_LEN; 594 req.emr_out_buf = payload; 595 req.emr_out_length = MC_CMD_ALLOC_PIOBUF_OUT_LEN; 596 597 efx_mcdi_execute_quiet(enp, &req); 598 599 if (req.emr_rc != 0) { 600 rc = req.emr_rc; 601 goto fail2; 602 } 603 604 if (req.emr_out_length_used < MC_CMD_ALLOC_PIOBUF_OUT_LEN) { 605 rc = EMSGSIZE; 606 goto fail3; 607 } 608 609 *handlep = MCDI_OUT_DWORD(req, ALLOC_PIOBUF_OUT_PIOBUF_HANDLE); 610 611 return (0); 612 613fail3: 614 EFSYS_PROBE(fail3); 615fail2: 616 EFSYS_PROBE(fail2); 617fail1: 618 EFSYS_PROBE1(fail1, efx_rc_t, rc); 619 620 return (rc); 621} 622 623static __checkReturn efx_rc_t 624efx_mcdi_free_piobuf( 625 __in efx_nic_t *enp, 626 __in efx_piobuf_handle_t handle) 627{ 628 efx_mcdi_req_t req; 629 uint8_t payload[MAX(MC_CMD_FREE_PIOBUF_IN_LEN, 630 MC_CMD_FREE_PIOBUF_OUT_LEN)]; 631 efx_rc_t rc; 632 633 (void) memset(payload, 0, sizeof (payload)); 634 req.emr_cmd = MC_CMD_FREE_PIOBUF; 635 req.emr_in_buf = payload; 636 req.emr_in_length = MC_CMD_FREE_PIOBUF_IN_LEN; 637 req.emr_out_buf = payload; 638 req.emr_out_length = MC_CMD_FREE_PIOBUF_OUT_LEN; 639 640 MCDI_IN_SET_DWORD(req, FREE_PIOBUF_IN_PIOBUF_HANDLE, handle); 641 642 efx_mcdi_execute_quiet(enp, &req); 643 644 if (req.emr_rc != 0) { 645 rc = req.emr_rc; 646 goto fail1; 647 } 648 649 return (0); 650 651fail1: 652 EFSYS_PROBE1(fail1, efx_rc_t, rc); 653 654 return (rc); 655} 656 657static __checkReturn efx_rc_t 658efx_mcdi_link_piobuf( 659 __in efx_nic_t *enp, 660 __in uint32_t vi_index, 661 __in efx_piobuf_handle_t handle) 662{ 663 efx_mcdi_req_t req; 664 uint8_t payload[MAX(MC_CMD_LINK_PIOBUF_IN_LEN, 665 MC_CMD_LINK_PIOBUF_OUT_LEN)]; 666 efx_rc_t rc; 667 668 (void) memset(payload, 0, sizeof (payload)); 669 req.emr_cmd = MC_CMD_LINK_PIOBUF; 670 req.emr_in_buf = payload; 671 req.emr_in_length = MC_CMD_LINK_PIOBUF_IN_LEN; 672 req.emr_out_buf = payload; 673 req.emr_out_length = MC_CMD_LINK_PIOBUF_OUT_LEN; 674 675 MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_PIOBUF_HANDLE, handle); 676 MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_TXQ_INSTANCE, vi_index); 677 678 efx_mcdi_execute(enp, &req); 679 680 if (req.emr_rc != 0) { 681 rc = req.emr_rc; 682 goto fail1; 683 } 684 685 return (0); 686 687fail1: 688 EFSYS_PROBE1(fail1, efx_rc_t, rc); 689 690 return (rc); 691} 692 693static __checkReturn efx_rc_t 694efx_mcdi_unlink_piobuf( 695 __in efx_nic_t *enp, 696 __in uint32_t vi_index) 697{ 698 efx_mcdi_req_t req; 699 uint8_t payload[MAX(MC_CMD_UNLINK_PIOBUF_IN_LEN, 700 MC_CMD_UNLINK_PIOBUF_OUT_LEN)]; 701 efx_rc_t rc; 702 703 (void) memset(payload, 0, sizeof (payload)); 704 req.emr_cmd = MC_CMD_UNLINK_PIOBUF; 705 req.emr_in_buf = payload; 706 req.emr_in_length = MC_CMD_UNLINK_PIOBUF_IN_LEN; 707 req.emr_out_buf = payload; 708 req.emr_out_length = MC_CMD_UNLINK_PIOBUF_OUT_LEN; 709 710 MCDI_IN_SET_DWORD(req, UNLINK_PIOBUF_IN_TXQ_INSTANCE, vi_index); 711 712 efx_mcdi_execute(enp, &req); 713 714 if (req.emr_rc != 0) { 715 rc = req.emr_rc; 716 goto fail1; 717 } 718 719 return (0); 720 721fail1: 722 EFSYS_PROBE1(fail1, efx_rc_t, rc); 723 724 return (rc); 725} 726 727static void 728ef10_nic_alloc_piobufs( 729 __in efx_nic_t *enp, 730 __in uint32_t max_piobuf_count) 731{ 732 efx_piobuf_handle_t *handlep; 733 unsigned int i; 734 efx_rc_t rc; 735 736 EFSYS_ASSERT3U(max_piobuf_count, <=, 737 EFX_ARRAY_SIZE(enp->en_arch.ef10.ena_piobuf_handle)); 738 739 enp->en_arch.ef10.ena_piobuf_count = 0; 740 741 for (i = 0; i < max_piobuf_count; i++) { 742 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i]; 743 744 if ((rc = efx_mcdi_alloc_piobuf(enp, handlep)) != 0) 745 goto fail1; 746 747 enp->en_arch.ef10.ena_pio_alloc_map[i] = 0; 748 enp->en_arch.ef10.ena_piobuf_count++; 749 } 750 751 return; 752 753fail1: 754 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 755 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i]; 756 757 efx_mcdi_free_piobuf(enp, *handlep); 758 *handlep = EFX_PIOBUF_HANDLE_INVALID; 759 } 760 enp->en_arch.ef10.ena_piobuf_count = 0; 761} 762 763 764static void 765ef10_nic_free_piobufs( 766 __in efx_nic_t *enp) 767{ 768 efx_piobuf_handle_t *handlep; 769 unsigned int i; 770 771 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 772 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i]; 773 774 efx_mcdi_free_piobuf(enp, *handlep); 775 *handlep = EFX_PIOBUF_HANDLE_INVALID; 776 } 777 enp->en_arch.ef10.ena_piobuf_count = 0; 778} 779 780/* Sub-allocate a block from a piobuf */ 781 __checkReturn efx_rc_t 782ef10_nic_pio_alloc( 783 __inout efx_nic_t *enp, 784 __out uint32_t *bufnump, 785 __out efx_piobuf_handle_t *handlep, 786 __out uint32_t *blknump, 787 __out uint32_t *offsetp, 788 __out size_t *sizep) 789{ 790 efx_nic_cfg_t *encp = &enp->en_nic_cfg; 791 efx_drv_cfg_t *edcp = &enp->en_drv_cfg; 792 uint32_t blk_per_buf; 793 uint32_t buf, blk; 794 efx_rc_t rc; 795 796 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 797 enp->en_family == EFX_FAMILY_MEDFORD); 798 EFSYS_ASSERT(bufnump); 799 EFSYS_ASSERT(handlep); 800 EFSYS_ASSERT(blknump); 801 EFSYS_ASSERT(offsetp); 802 EFSYS_ASSERT(sizep); 803 804 if ((edcp->edc_pio_alloc_size == 0) || 805 (enp->en_arch.ef10.ena_piobuf_count == 0)) { 806 rc = ENOMEM; 807 goto fail1; 808 } 809 blk_per_buf = encp->enc_piobuf_size / edcp->edc_pio_alloc_size; 810 811 for (buf = 0; buf < enp->en_arch.ef10.ena_piobuf_count; buf++) { 812 uint32_t *map = &enp->en_arch.ef10.ena_pio_alloc_map[buf]; 813 814 if (~(*map) == 0) 815 continue; 816 817 EFSYS_ASSERT3U(blk_per_buf, <=, (8 * sizeof (*map))); 818 for (blk = 0; blk < blk_per_buf; blk++) { 819 if ((*map & (1u << blk)) == 0) { 820 *map |= (1u << blk); 821 goto done; 822 } 823 } 824 } 825 rc = ENOMEM; 826 goto fail2; 827 828done: 829 *handlep = enp->en_arch.ef10.ena_piobuf_handle[buf]; 830 *bufnump = buf; 831 *blknump = blk; 832 *sizep = edcp->edc_pio_alloc_size; 833 *offsetp = blk * (*sizep); 834 835 return (0); 836 837fail2: 838 EFSYS_PROBE(fail2); 839fail1: 840 EFSYS_PROBE1(fail1, efx_rc_t, rc); 841 842 return (rc); 843} 844 845/* Free a piobuf sub-allocated block */ 846 __checkReturn efx_rc_t 847ef10_nic_pio_free( 848 __inout efx_nic_t *enp, 849 __in uint32_t bufnum, 850 __in uint32_t blknum) 851{ 852 uint32_t *map; 853 efx_rc_t rc; 854 855 if ((bufnum >= enp->en_arch.ef10.ena_piobuf_count) || 856 (blknum >= (8 * sizeof (*map)))) { 857 rc = EINVAL; 858 goto fail1; 859 } 860 861 map = &enp->en_arch.ef10.ena_pio_alloc_map[bufnum]; 862 if ((*map & (1u << blknum)) == 0) { 863 rc = ENOENT; 864 goto fail2; 865 } 866 *map &= ~(1u << blknum); 867 868 return (0); 869 870fail2: 871 EFSYS_PROBE(fail2); 872fail1: 873 EFSYS_PROBE1(fail1, efx_rc_t, rc); 874 875 return (rc); 876} 877 878 __checkReturn efx_rc_t 879ef10_nic_pio_link( 880 __inout efx_nic_t *enp, 881 __in uint32_t vi_index, 882 __in efx_piobuf_handle_t handle) 883{ 884 return (efx_mcdi_link_piobuf(enp, vi_index, handle)); 885} 886 887 __checkReturn efx_rc_t 888ef10_nic_pio_unlink( 889 __inout efx_nic_t *enp, 890 __in uint32_t vi_index) 891{ 892 return (efx_mcdi_unlink_piobuf(enp, vi_index)); 893} 894 895 __checkReturn efx_rc_t 896ef10_get_datapath_caps( 897 __in efx_nic_t *enp) 898{ 899 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 900 efx_dword_t datapath_capabilities; 901 efx_dword_t datapath_capabilities_v2; 902 efx_rc_t rc; 903 904 if ((rc = efx_mcdi_get_capabilities(enp, &datapath_capabilities, 905 &datapath_capabilities_v2)) != 0) 906 goto fail1; 907 908 /* 909 * Huntington RXDP firmware inserts a 0 or 14 byte prefix. 910 * We only support the 14 byte prefix here. 911 */ 912 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 913 GET_CAPABILITIES_OUT_RX_PREFIX_LEN_14) != 1) { 914 rc = ENOTSUP; 915 goto fail2; 916 } 917 encp->enc_rx_prefix_size = 14; 918 919 /* Check if the firmware supports TSO */ 920 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 921 GET_CAPABILITIES_OUT_TX_TSO) == 1) 922 encp->enc_fw_assisted_tso_enabled = B_TRUE; 923 else 924 encp->enc_fw_assisted_tso_enabled = B_FALSE; 925 926 /* Check if the firmware supports FATSOv2 */ 927 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities_v2, 928 GET_CAPABILITIES_V2_OUT_TX_TSO_V2) == 1) 929 encp->enc_fw_assisted_tso_v2_enabled = B_TRUE; 930 else 931 encp->enc_fw_assisted_tso_v2_enabled = B_FALSE; 932 933 /* Check if the firmware has vadapter/vport/vswitch support */ 934 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 935 GET_CAPABILITIES_OUT_EVB) == 1) 936 encp->enc_datapath_cap_evb = B_TRUE; 937 else 938 encp->enc_datapath_cap_evb = B_FALSE; 939 940 /* Check if the firmware supports VLAN insertion */ 941 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 942 GET_CAPABILITIES_OUT_TX_VLAN_INSERTION) == 1) 943 encp->enc_hw_tx_insert_vlan_enabled = B_TRUE; 944 else 945 encp->enc_hw_tx_insert_vlan_enabled = B_FALSE; 946 947 /* Check if the firmware supports RX event batching */ 948 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 949 GET_CAPABILITIES_OUT_RX_BATCHING) == 1) { 950 encp->enc_rx_batching_enabled = B_TRUE; 951 encp->enc_rx_batch_max = 16; 952 } else { 953 encp->enc_rx_batching_enabled = B_FALSE; 954 } 955 956 /* Check if the firmware supports disabling scatter on RXQs */ 957 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 958 GET_CAPABILITIES_OUT_RX_DISABLE_SCATTER) == 1) { 959 encp->enc_rx_disable_scatter_supported = B_TRUE; 960 } else { 961 encp->enc_rx_disable_scatter_supported = B_FALSE; 962 } 963 964 /* Check if the firmware supports set mac with running filters */ 965 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 966 GET_CAPABILITIES_OUT_VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED) 967 == 1) { 968 encp->enc_allow_set_mac_with_installed_filters = B_TRUE; 969 } else { 970 encp->enc_allow_set_mac_with_installed_filters = B_FALSE; 971 } 972 973 return (0); 974 975fail2: 976 EFSYS_PROBE(fail2); 977fail1: 978 EFSYS_PROBE1(fail1, efx_rc_t, rc); 979 980 return (rc); 981} 982 983/* 984 * The external port mapping is a one-based numbering of the external 985 * connectors on the board. It does not distinguish off-board separated 986 * outputs such as multi-headed cables. 987 * The number of ports that map to each external port connector 988 * on the board is determined by the chip family and the port modes to 989 * which the NIC can be configured. The mapping table lists modes with 990 * port numbering requirements in increasing order. 991 */ 992static struct { 993 efx_family_t family; 994 uint32_t modes_mask; 995 uint32_t stride; 996} __ef10_external_port_mappings[] = { 997 /* Supported modes requiring 1 output per port */ 998 { 999 EFX_FAMILY_HUNTINGTON, 1000 (1 << TLV_PORT_MODE_10G) | 1001 (1 << TLV_PORT_MODE_10G_10G) | 1002 (1 << TLV_PORT_MODE_10G_10G_10G_10G), 1003 1 1004 }, 1005 { 1006 EFX_FAMILY_MEDFORD, 1007 (1 << TLV_PORT_MODE_10G) | 1008 (1 << TLV_PORT_MODE_10G_10G) | 1009 (1 << TLV_PORT_MODE_10G_10G_10G_10G), 1010 1 1011 }, 1012 /* Supported modes requiring 2 outputs per port */ 1013 { 1014 EFX_FAMILY_HUNTINGTON, 1015 (1 << TLV_PORT_MODE_40G) | 1016 (1 << TLV_PORT_MODE_40G_40G) | 1017 (1 << TLV_PORT_MODE_40G_10G_10G) | 1018 (1 << TLV_PORT_MODE_10G_10G_40G), 1019 2 1020 }, 1021 { 1022 EFX_FAMILY_MEDFORD, 1023 (1 << TLV_PORT_MODE_40G) | 1024 (1 << TLV_PORT_MODE_40G_40G) | 1025 (1 << TLV_PORT_MODE_40G_10G_10G) | 1026 (1 << TLV_PORT_MODE_10G_10G_40G), 1027 2 1028 }, 1029 /* Supported modes requiring 4 outputs per port */ 1030 { 1031 EFX_FAMILY_MEDFORD, 1032 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q) | 1033 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q2), 1034 4 1035 }, 1036}; 1037 1038 __checkReturn efx_rc_t 1039ef10_external_port_mapping( 1040 __in efx_nic_t *enp, 1041 __in uint32_t port, 1042 __out uint8_t *external_portp) 1043{ 1044 efx_rc_t rc; 1045 int i; 1046 uint32_t port_modes; 1047 uint32_t matches; 1048 uint32_t stride = 1; /* default 1-1 mapping */ 1049 1050 if ((rc = efx_mcdi_get_port_modes(enp, &port_modes)) != 0) { 1051 /* No port mode information available - use default mapping */ 1052 goto out; 1053 } 1054 1055 /* 1056 * Infer the internal port -> external port mapping from 1057 * the possible port modes for this NIC. 1058 */ 1059 for (i = 0; i < EFX_ARRAY_SIZE(__ef10_external_port_mappings); ++i) { 1060 if (__ef10_external_port_mappings[i].family != 1061 enp->en_family) 1062 continue; 1063 matches = (__ef10_external_port_mappings[i].modes_mask & 1064 port_modes); 1065 if (matches != 0) { 1066 stride = __ef10_external_port_mappings[i].stride; 1067 port_modes &= ~matches; 1068 } 1069 } 1070 1071 if (port_modes != 0) { 1072 /* Some advertised modes are not supported */ 1073 rc = ENOTSUP; 1074 goto fail1; 1075 } 1076 1077out: 1078 /* 1079 * Scale as required by last matched mode and then convert to 1080 * one-based numbering 1081 */ 1082 *external_portp = (uint8_t)(port / stride) + 1; 1083 return (0); 1084 1085fail1: 1086 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1087 1088 return (rc); 1089} 1090 1091 __checkReturn efx_rc_t 1092hunt_board_cfg( 1093 __in efx_nic_t *enp) 1094{ 1095 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 1096 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1097 uint8_t mac_addr[6]; 1098 uint32_t board_type = 0; 1099 hunt_link_state_t hls; 1100 efx_port_t *epp = &(enp->en_port); 1101 uint32_t port; 1102 uint32_t pf; 1103 uint32_t vf; 1104 uint32_t mask; 1105 uint32_t flags; 1106 uint32_t sysclk; 1107 uint32_t base, nvec; 1108 efx_rc_t rc; 1109 1110 if ((rc = efx_mcdi_get_port_assignment(enp, &port)) != 0) 1111 goto fail1; 1112 1113 /* 1114 * NOTE: The MCDI protocol numbers ports from zero. 1115 * The common code MCDI interface numbers ports from one. 1116 */ 1117 emip->emi_port = port + 1; 1118 1119 if ((rc = ef10_external_port_mapping(enp, port, 1120 &encp->enc_external_port)) != 0) 1121 goto fail2; 1122 1123 /* 1124 * Get PCIe function number from firmware (used for 1125 * per-function privilege and dynamic config info). 1126 * - PCIe PF: pf = PF number, vf = 0xffff. 1127 * - PCIe VF: pf = parent PF, vf = VF number. 1128 */ 1129 if ((rc = efx_mcdi_get_function_info(enp, &pf, &vf)) != 0) 1130 goto fail3; 1131 1132 encp->enc_pf = pf; 1133 encp->enc_vf = vf; 1134 1135 /* MAC address for this function */ 1136 if (EFX_PCI_FUNCTION_IS_PF(encp)) { 1137 rc = efx_mcdi_get_mac_address_pf(enp, mac_addr); 1138 if ((rc == 0) && (mac_addr[0] & 0x02)) { 1139 /* 1140 * If the static config does not include a global MAC 1141 * address pool then the board may return a locally 1142 * administered MAC address (this should only happen on 1143 * incorrectly programmed boards). 1144 */ 1145 rc = EINVAL; 1146 } 1147 } else { 1148 rc = efx_mcdi_get_mac_address_vf(enp, mac_addr); 1149 } 1150 if (rc != 0) 1151 goto fail4; 1152 1153 EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr); 1154 1155 /* Board configuration */ 1156 rc = efx_mcdi_get_board_cfg(enp, &board_type, NULL, NULL); 1157 if (rc != 0) { 1158 /* Unprivileged functions may not be able to read board cfg */ 1159 if (rc == EACCES) 1160 board_type = 0; 1161 else 1162 goto fail5; 1163 } 1164 1165 encp->enc_board_type = board_type; 1166 encp->enc_clk_mult = 1; /* not used for Huntington */ 1167 1168 /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */ 1169 if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0) 1170 goto fail6; 1171 1172 /* Obtain the default PHY advertised capabilities */ 1173 if ((rc = hunt_phy_get_link(enp, &hls)) != 0) 1174 goto fail7; 1175 epp->ep_default_adv_cap_mask = hls.hls_adv_cap_mask; 1176 epp->ep_adv_cap_mask = hls.hls_adv_cap_mask; 1177 1178 /* 1179 * Enable firmware workarounds for hardware errata. 1180 * Expected responses are: 1181 * - 0 (zero): 1182 * Success: workaround enabled or disabled as requested. 1183 * - MC_CMD_ERR_ENOSYS (reported as ENOTSUP): 1184 * Firmware does not support the MC_CMD_WORKAROUND request. 1185 * (assume that the workaround is not supported). 1186 * - MC_CMD_ERR_ENOENT (reported as ENOENT): 1187 * Firmware does not support the requested workaround. 1188 * - MC_CMD_ERR_EPERM (reported as EACCES): 1189 * Unprivileged function cannot enable/disable workarounds. 1190 * 1191 * See efx_mcdi_request_errcode() for MCDI error translations. 1192 */ 1193 1194 /* 1195 * If the bug35388 workaround is enabled, then use an indirect access 1196 * method to avoid unsafe EVQ writes. 1197 */ 1198 rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG35388, B_TRUE, 1199 NULL); 1200 if ((rc == 0) || (rc == EACCES)) 1201 encp->enc_bug35388_workaround = B_TRUE; 1202 else if ((rc == ENOTSUP) || (rc == ENOENT)) 1203 encp->enc_bug35388_workaround = B_FALSE; 1204 else 1205 goto fail8; 1206 1207 /* 1208 * If the bug41750 workaround is enabled, then do not test interrupts, 1209 * as the test will fail (seen with Greenport controllers). 1210 */ 1211 rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG41750, B_TRUE, 1212 NULL); 1213 if (rc == 0) { 1214 encp->enc_bug41750_workaround = B_TRUE; 1215 } else if (rc == EACCES) { 1216 /* Assume a controller with 40G ports needs the workaround. */ 1217 if (epp->ep_default_adv_cap_mask & EFX_PHY_CAP_40000FDX) 1218 encp->enc_bug41750_workaround = B_TRUE; 1219 else 1220 encp->enc_bug41750_workaround = B_FALSE; 1221 } else if ((rc == ENOTSUP) || (rc == ENOENT)) { 1222 encp->enc_bug41750_workaround = B_FALSE; 1223 } else { 1224 goto fail9; 1225 } 1226 if (EFX_PCI_FUNCTION_IS_VF(encp)) { 1227 /* Interrupt testing does not work for VFs. See bug50084. */ 1228 encp->enc_bug41750_workaround = B_TRUE; 1229 } 1230 1231 /* 1232 * If the bug26807 workaround is enabled, then firmware has enabled 1233 * support for chained multicast filters. Firmware will reset (FLR) 1234 * functions which have filters in the hardware filter table when the 1235 * workaround is enabled/disabled. 1236 * 1237 * We must recheck if the workaround is enabled after inserting the 1238 * first hardware filter, in case it has been changed since this check. 1239 */ 1240 rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG26807, 1241 B_TRUE, &flags); 1242 if (rc == 0) { 1243 encp->enc_bug26807_workaround = B_TRUE; 1244 if (flags & (1 << MC_CMD_WORKAROUND_EXT_OUT_FLR_DONE_LBN)) { 1245 /* 1246 * Other functions had installed filters before the 1247 * workaround was enabled, and they have been reset 1248 * by firmware. 1249 */ 1250 EFSYS_PROBE(bug26807_workaround_flr_done); 1251 /* FIXME: bump MC warm boot count ? */ 1252 } 1253 } else if (rc == EACCES) { 1254 /* 1255 * Unprivileged functions cannot enable the workaround in older 1256 * firmware. 1257 */ 1258 encp->enc_bug26807_workaround = B_FALSE; 1259 } else if ((rc == ENOTSUP) || (rc == ENOENT)) { 1260 encp->enc_bug26807_workaround = B_FALSE; 1261 } else { 1262 goto fail10; 1263 } 1264 1265 /* Get sysclk frequency (in MHz). */ 1266 if ((rc = efx_mcdi_get_clock(enp, &sysclk)) != 0) 1267 goto fail11; 1268 1269 /* 1270 * The timer quantum is 1536 sysclk cycles, documented for the 1271 * EV_TMR_VAL field of EV_TIMER_TBL. Scale for MHz and ns units. 1272 */ 1273 encp->enc_evq_timer_quantum_ns = 1536000UL / sysclk; /* 1536 cycles */ 1274 if (encp->enc_bug35388_workaround) { 1275 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns << 1276 ERF_DD_EVQ_IND_TIMER_VAL_WIDTH) / 1000; 1277 } else { 1278 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns << 1279 FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000; 1280 } 1281 1282 /* Check capabilities of running datapath firmware */ 1283 if ((rc = ef10_get_datapath_caps(enp)) != 0) 1284 goto fail12; 1285 1286 /* Alignment for receive packet DMA buffers */ 1287 encp->enc_rx_buf_align_start = 1; 1288 encp->enc_rx_buf_align_end = 64; /* RX DMA end padding */ 1289 1290 /* Alignment for WPTR updates */ 1291 encp->enc_rx_push_align = EF10_RX_WPTR_ALIGN; 1292 1293 /* 1294 * Set resource limits for MC_CMD_ALLOC_VIS. Note that we cannot use 1295 * MC_CMD_GET_RESOURCE_LIMITS here as that reports the available 1296 * resources (allocated to this PCIe function), which is zero until 1297 * after we have allocated VIs. 1298 */ 1299 encp->enc_evq_limit = 1024; 1300 encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET; 1301 encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET; 1302 1303 encp->enc_buftbl_limit = 0xFFFFFFFF; 1304 1305 encp->enc_piobuf_limit = HUNT_PIOBUF_NBUFS; 1306 encp->enc_piobuf_size = HUNT_PIOBUF_SIZE; 1307 encp->enc_piobuf_min_alloc_size = HUNT_MIN_PIO_ALLOC_SIZE; 1308 1309 /* 1310 * Get the current privilege mask. Note that this may be modified 1311 * dynamically, so this value is informational only. DO NOT use 1312 * the privilege mask to check for sufficient privileges, as that 1313 * can result in time-of-check/time-of-use bugs. 1314 */ 1315 if ((rc = efx_mcdi_privilege_mask(enp, pf, vf, &mask)) != 0) { 1316 if (rc != ENOTSUP) 1317 goto fail13; 1318 1319 /* Fallback for old firmware without privilege mask support */ 1320 if (EFX_PCI_FUNCTION_IS_PF(encp)) { 1321 /* Assume PF has admin privilege */ 1322 mask = HUNT_LEGACY_PF_PRIVILEGE_MASK; 1323 } else { 1324 /* VF is always unprivileged by default */ 1325 mask = HUNT_LEGACY_VF_PRIVILEGE_MASK; 1326 } 1327 } 1328 1329 encp->enc_privilege_mask = mask; 1330 1331 /* Get interrupt vector limits */ 1332 if ((rc = efx_mcdi_get_vector_cfg(enp, &base, &nvec, NULL)) != 0) { 1333 if (EFX_PCI_FUNCTION_IS_PF(encp)) 1334 goto fail14; 1335 1336 /* Ignore error (cannot query vector limits from a VF). */ 1337 base = 0; 1338 nvec = 1024; 1339 } 1340 encp->enc_intr_vec_base = base; 1341 encp->enc_intr_limit = nvec; 1342 1343 /* 1344 * Maximum number of bytes into the frame the TCP header can start for 1345 * firmware assisted TSO to work. 1346 */ 1347 encp->enc_tx_tso_tcp_header_offset_limit = EF10_TCP_HEADER_OFFSET_LIMIT; 1348 1349 return (0); 1350 1351fail14: 1352 EFSYS_PROBE(fail14); 1353fail13: 1354 EFSYS_PROBE(fail13); 1355fail12: 1356 EFSYS_PROBE(fail12); 1357fail11: 1358 EFSYS_PROBE(fail11); 1359fail10: 1360 EFSYS_PROBE(fail10); 1361fail9: 1362 EFSYS_PROBE(fail9); 1363fail8: 1364 EFSYS_PROBE(fail8); 1365fail7: 1366 EFSYS_PROBE(fail7); 1367fail6: 1368 EFSYS_PROBE(fail6); 1369fail5: 1370 EFSYS_PROBE(fail5); 1371fail4: 1372 EFSYS_PROBE(fail4); 1373fail3: 1374 EFSYS_PROBE(fail3); 1375fail2: 1376 EFSYS_PROBE(fail2); 1377fail1: 1378 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1379 1380 return (rc); 1381} 1382 1383 1384 __checkReturn efx_rc_t 1385ef10_nic_probe( 1386 __in efx_nic_t *enp) 1387{ 1388 efx_nic_ops_t *enop = enp->en_enop; 1389 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1390 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1391 efx_rc_t rc; 1392 1393 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1394 enp->en_family == EFX_FAMILY_MEDFORD); 1395 1396 /* Read and clear any assertion state */ 1397 if ((rc = efx_mcdi_read_assertion(enp)) != 0) 1398 goto fail1; 1399 1400 /* Exit the assertion handler */ 1401 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 1402 if (rc != EACCES) 1403 goto fail2; 1404 1405 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0) 1406 goto fail3; 1407 1408 if ((rc = enop->eno_board_cfg(enp)) != 0) 1409 if (rc != EACCES) 1410 goto fail4; 1411 1412 /* 1413 * Set default driver config limits (based on board config). 1414 * 1415 * FIXME: For now allocate a fixed number of VIs which is likely to be 1416 * sufficient and small enough to allow multiple functions on the same 1417 * port. 1418 */ 1419 edcp->edc_min_vi_count = edcp->edc_max_vi_count = 1420 MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit)); 1421 1422 /* The client driver must configure and enable PIO buffer support */ 1423 edcp->edc_max_piobuf_count = 0; 1424 edcp->edc_pio_alloc_size = 0; 1425 1426#if EFSYS_OPT_MAC_STATS 1427 /* Wipe the MAC statistics */ 1428 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0) 1429 goto fail5; 1430#endif 1431 1432#if EFSYS_OPT_LOOPBACK 1433 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0) 1434 goto fail6; 1435#endif 1436 1437#if EFSYS_OPT_MON_STATS 1438 if ((rc = mcdi_mon_cfg_build(enp)) != 0) { 1439 /* Unprivileged functions do not have access to sensors */ 1440 if (rc != EACCES) 1441 goto fail7; 1442 } 1443#endif 1444 1445 encp->enc_features = enp->en_features; 1446 1447 return (0); 1448 1449#if EFSYS_OPT_MON_STATS 1450fail7: 1451 EFSYS_PROBE(fail7); 1452#endif 1453#if EFSYS_OPT_LOOPBACK 1454fail6: 1455 EFSYS_PROBE(fail6); 1456#endif 1457#if EFSYS_OPT_MAC_STATS 1458fail5: 1459 EFSYS_PROBE(fail5); 1460#endif 1461fail4: 1462 EFSYS_PROBE(fail4); 1463fail3: 1464 EFSYS_PROBE(fail3); 1465fail2: 1466 EFSYS_PROBE(fail2); 1467fail1: 1468 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1469 1470 return (rc); 1471} 1472 1473 __checkReturn efx_rc_t 1474ef10_nic_set_drv_limits( 1475 __inout efx_nic_t *enp, 1476 __in efx_drv_limits_t *edlp) 1477{ 1478 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1479 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1480 uint32_t min_evq_count, max_evq_count; 1481 uint32_t min_rxq_count, max_rxq_count; 1482 uint32_t min_txq_count, max_txq_count; 1483 efx_rc_t rc; 1484 1485 if (edlp == NULL) { 1486 rc = EINVAL; 1487 goto fail1; 1488 } 1489 1490 /* Get minimum required and maximum usable VI limits */ 1491 min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit); 1492 min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit); 1493 min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit); 1494 1495 edcp->edc_min_vi_count = 1496 MAX(min_evq_count, MAX(min_rxq_count, min_txq_count)); 1497 1498 max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit); 1499 max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit); 1500 max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit); 1501 1502 edcp->edc_max_vi_count = 1503 MAX(max_evq_count, MAX(max_rxq_count, max_txq_count)); 1504 1505 /* 1506 * Check limits for sub-allocated piobuf blocks. 1507 * PIO is optional, so don't fail if the limits are incorrect. 1508 */ 1509 if ((encp->enc_piobuf_size == 0) || 1510 (encp->enc_piobuf_limit == 0) || 1511 (edlp->edl_min_pio_alloc_size == 0) || 1512 (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) { 1513 /* Disable PIO */ 1514 edcp->edc_max_piobuf_count = 0; 1515 edcp->edc_pio_alloc_size = 0; 1516 } else { 1517 uint32_t blk_size, blk_count, blks_per_piobuf; 1518 1519 blk_size = 1520 MAX(edlp->edl_min_pio_alloc_size, 1521 encp->enc_piobuf_min_alloc_size); 1522 1523 blks_per_piobuf = encp->enc_piobuf_size / blk_size; 1524 EFSYS_ASSERT3U(blks_per_piobuf, <=, 32); 1525 1526 blk_count = (encp->enc_piobuf_limit * blks_per_piobuf); 1527 1528 /* A zero max pio alloc count means unlimited */ 1529 if ((edlp->edl_max_pio_alloc_count > 0) && 1530 (edlp->edl_max_pio_alloc_count < blk_count)) { 1531 blk_count = edlp->edl_max_pio_alloc_count; 1532 } 1533 1534 edcp->edc_pio_alloc_size = blk_size; 1535 edcp->edc_max_piobuf_count = 1536 (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf; 1537 } 1538 1539 return (0); 1540 1541fail1: 1542 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1543 1544 return (rc); 1545} 1546 1547 1548 __checkReturn efx_rc_t 1549ef10_nic_reset( 1550 __in efx_nic_t *enp) 1551{ 1552 efx_mcdi_req_t req; 1553 uint8_t payload[MAX(MC_CMD_ENTITY_RESET_IN_LEN, 1554 MC_CMD_ENTITY_RESET_OUT_LEN)]; 1555 efx_rc_t rc; 1556 1557 /* ef10_nic_reset() is called to recover from BADASSERT failures. */ 1558 if ((rc = efx_mcdi_read_assertion(enp)) != 0) 1559 goto fail1; 1560 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 1561 goto fail2; 1562 1563 (void) memset(payload, 0, sizeof (payload)); 1564 req.emr_cmd = MC_CMD_ENTITY_RESET; 1565 req.emr_in_buf = payload; 1566 req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN; 1567 req.emr_out_buf = payload; 1568 req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN; 1569 1570 MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG, 1571 ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1); 1572 1573 efx_mcdi_execute(enp, &req); 1574 1575 if (req.emr_rc != 0) { 1576 rc = req.emr_rc; 1577 goto fail3; 1578 } 1579 1580 /* Clear RX/TX DMA queue errors */ 1581 enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR); 1582 1583 return (0); 1584 1585fail3: 1586 EFSYS_PROBE(fail3); 1587fail2: 1588 EFSYS_PROBE(fail2); 1589fail1: 1590 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1591 1592 return (rc); 1593} 1594 1595 __checkReturn efx_rc_t 1596ef10_nic_init( 1597 __in efx_nic_t *enp) 1598{ 1599 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1600 uint32_t min_vi_count, max_vi_count; 1601 uint32_t vi_count, vi_base, vi_shift; 1602 uint32_t i; 1603 uint32_t retry; 1604 uint32_t delay_us; 1605 efx_rc_t rc; 1606 1607 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1608 enp->en_family == EFX_FAMILY_MEDFORD); 1609 1610 /* Enable reporting of some events (e.g. link change) */ 1611 if ((rc = efx_mcdi_log_ctrl(enp)) != 0) 1612 goto fail1; 1613 1614 /* Allocate (optional) on-chip PIO buffers */ 1615 ef10_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count); 1616 1617 /* 1618 * For best performance, PIO writes should use a write-combined 1619 * (WC) memory mapping. Using a separate WC mapping for the PIO 1620 * aperture of each VI would be a burden to drivers (and not 1621 * possible if the host page size is >4Kbyte). 1622 * 1623 * To avoid this we use a single uncached (UC) mapping for VI 1624 * register access, and a single WC mapping for extra VIs used 1625 * for PIO writes. 1626 * 1627 * Each piobuf must be linked to a VI in the WC mapping, and to 1628 * each VI that is using a sub-allocated block from the piobuf. 1629 */ 1630 min_vi_count = edcp->edc_min_vi_count; 1631 max_vi_count = 1632 edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count; 1633 1634 /* Ensure that the previously attached driver's VIs are freed */ 1635 if ((rc = efx_mcdi_free_vis(enp)) != 0) 1636 goto fail2; 1637 1638 /* 1639 * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this 1640 * fails then retrying the request for fewer VI resources may succeed. 1641 */ 1642 vi_count = 0; 1643 if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count, 1644 &vi_base, &vi_count, &vi_shift)) != 0) 1645 goto fail3; 1646 1647 EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count); 1648 1649 if (vi_count < min_vi_count) { 1650 rc = ENOMEM; 1651 goto fail4; 1652 } 1653 1654 enp->en_arch.ef10.ena_vi_base = vi_base; 1655 enp->en_arch.ef10.ena_vi_count = vi_count; 1656 enp->en_arch.ef10.ena_vi_shift = vi_shift; 1657 1658 if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) { 1659 /* Not enough extra VIs to map piobufs */ 1660 ef10_nic_free_piobufs(enp); 1661 } 1662 1663 enp->en_arch.ef10.ena_pio_write_vi_base = 1664 vi_count - enp->en_arch.ef10.ena_piobuf_count; 1665 1666 /* Save UC memory mapping details */ 1667 enp->en_arch.ef10.ena_uc_mem_map_offset = 0; 1668 if (enp->en_arch.ef10.ena_piobuf_count > 0) { 1669 enp->en_arch.ef10.ena_uc_mem_map_size = 1670 (ER_DZ_TX_PIOBUF_STEP * 1671 enp->en_arch.ef10.ena_pio_write_vi_base); 1672 } else { 1673 enp->en_arch.ef10.ena_uc_mem_map_size = 1674 (ER_DZ_TX_PIOBUF_STEP * 1675 enp->en_arch.ef10.ena_vi_count); 1676 } 1677 1678 /* Save WC memory mapping details */ 1679 enp->en_arch.ef10.ena_wc_mem_map_offset = 1680 enp->en_arch.ef10.ena_uc_mem_map_offset + 1681 enp->en_arch.ef10.ena_uc_mem_map_size; 1682 1683 enp->en_arch.ef10.ena_wc_mem_map_size = 1684 (ER_DZ_TX_PIOBUF_STEP * 1685 enp->en_arch.ef10.ena_piobuf_count); 1686 1687 /* Link piobufs to extra VIs in WC mapping */ 1688 if (enp->en_arch.ef10.ena_piobuf_count > 0) { 1689 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 1690 rc = efx_mcdi_link_piobuf(enp, 1691 enp->en_arch.ef10.ena_pio_write_vi_base + i, 1692 enp->en_arch.ef10.ena_piobuf_handle[i]); 1693 if (rc != 0) 1694 break; 1695 } 1696 } 1697 1698 /* 1699 * Allocate a vAdaptor attached to our upstream vPort/pPort. 1700 * 1701 * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF 1702 * driver has yet to bring up the EVB port. See bug 56147. In this case, 1703 * retry the request several times after waiting a while. The wait time 1704 * between retries starts small (10ms) and exponentially increases. 1705 * Total wait time is a little over two seconds. Retry logic in the 1706 * client driver may mean this whole loop is repeated if it continues to 1707 * fail. 1708 */ 1709 retry = 0; 1710 delay_us = 10000; 1711 while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) { 1712 if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) || 1713 (rc != ENOENT)) { 1714 /* 1715 * Do not retry alloc for PF, or for other errors on 1716 * a VF. 1717 */ 1718 goto fail5; 1719 } 1720 1721 /* VF startup before PF is ready. Retry allocation. */ 1722 if (retry > 5) { 1723 /* Too many attempts */ 1724 rc = EINVAL; 1725 goto fail6; 1726 } 1727 EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry); 1728 EFSYS_SLEEP(delay_us); 1729 retry++; 1730 if (delay_us < 500000) 1731 delay_us <<= 2; 1732 } 1733 1734 enp->en_vport_id = EVB_PORT_ID_ASSIGNED; 1735 enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2; 1736 1737 return (0); 1738 1739fail6: 1740 EFSYS_PROBE(fail6); 1741fail5: 1742 EFSYS_PROBE(fail5); 1743fail4: 1744 EFSYS_PROBE(fail4); 1745fail3: 1746 EFSYS_PROBE(fail3); 1747fail2: 1748 EFSYS_PROBE(fail2); 1749 1750 ef10_nic_free_piobufs(enp); 1751 1752fail1: 1753 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1754 1755 return (rc); 1756} 1757 1758 __checkReturn efx_rc_t 1759ef10_nic_get_vi_pool( 1760 __in efx_nic_t *enp, 1761 __out uint32_t *vi_countp) 1762{ 1763 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1764 enp->en_family == EFX_FAMILY_MEDFORD); 1765 1766 /* 1767 * Report VIs that the client driver can use. 1768 * Do not include VIs used for PIO buffer writes. 1769 */ 1770 *vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base; 1771 1772 return (0); 1773} 1774 1775 __checkReturn efx_rc_t 1776ef10_nic_get_bar_region( 1777 __in efx_nic_t *enp, 1778 __in efx_nic_region_t region, 1779 __out uint32_t *offsetp, 1780 __out size_t *sizep) 1781{ 1782 efx_rc_t rc; 1783 1784 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1785 enp->en_family == EFX_FAMILY_MEDFORD); 1786 1787 /* 1788 * TODO: Specify host memory mapping alignment and granularity 1789 * in efx_drv_limits_t so that they can be taken into account 1790 * when allocating extra VIs for PIO writes. 1791 */ 1792 switch (region) { 1793 case EFX_REGION_VI: 1794 /* UC mapped memory BAR region for VI registers */ 1795 *offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset; 1796 *sizep = enp->en_arch.ef10.ena_uc_mem_map_size; 1797 break; 1798 1799 case EFX_REGION_PIO_WRITE_VI: 1800 /* WC mapped memory BAR region for piobuf writes */ 1801 *offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset; 1802 *sizep = enp->en_arch.ef10.ena_wc_mem_map_size; 1803 break; 1804 1805 default: 1806 rc = EINVAL; 1807 goto fail1; 1808 } 1809 1810 return (0); 1811 1812fail1: 1813 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1814 1815 return (rc); 1816} 1817 1818 void 1819ef10_nic_fini( 1820 __in efx_nic_t *enp) 1821{ 1822 uint32_t i; 1823 efx_rc_t rc; 1824 1825 (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id); 1826 enp->en_vport_id = 0; 1827 1828 /* Unlink piobufs from extra VIs in WC mapping */ 1829 if (enp->en_arch.ef10.ena_piobuf_count > 0) { 1830 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 1831 rc = efx_mcdi_unlink_piobuf(enp, 1832 enp->en_arch.ef10.ena_pio_write_vi_base + i); 1833 if (rc != 0) 1834 break; 1835 } 1836 } 1837 1838 ef10_nic_free_piobufs(enp); 1839 1840 (void) efx_mcdi_free_vis(enp); 1841 enp->en_arch.ef10.ena_vi_count = 0; 1842} 1843 1844 void 1845ef10_nic_unprobe( 1846 __in efx_nic_t *enp) 1847{ 1848#if EFSYS_OPT_MON_STATS 1849 mcdi_mon_cfg_free(enp); 1850#endif /* EFSYS_OPT_MON_STATS */ 1851 (void) efx_mcdi_drv_attach(enp, B_FALSE); 1852} 1853 1854#if EFSYS_OPT_DIAG 1855 1856 __checkReturn efx_rc_t 1857ef10_nic_register_test( 1858 __in efx_nic_t *enp) 1859{ 1860 efx_rc_t rc; 1861 1862 /* FIXME */ 1863 _NOTE(ARGUNUSED(enp)) 1864 if (B_FALSE) { 1865 rc = ENOTSUP; 1866 goto fail1; 1867 } 1868 /* FIXME */ 1869 1870 return (0); 1871 1872fail1: 1873 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1874 1875 return (rc); 1876} 1877 1878#endif /* EFSYS_OPT_DIAG */ 1879 1880 1881 1882#endif /* EFSYS_OPT_HUNTINGTON */ 1883