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