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