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 goto fail13; 1244 1245 encp->enc_privilege_mask = mask; 1246 1247 /* Get interrupt vector limits */ 1248 if ((rc = efx_mcdi_get_vector_cfg(enp, &base, &nvec, NULL)) != 0) { 1249 if (EFX_PCI_FUNCTION_IS_PF(encp)) 1250 goto fail14; 1251 1252 /* Ignore error (cannot query vector limits from a VF). */ 1253 base = 0; 1254 nvec = 1024; 1255 } 1256 encp->enc_intr_vec_base = base; 1257 encp->enc_intr_limit = nvec; 1258 1259 /* 1260 * Maximum number of bytes into the frame the TCP header can start for 1261 * firmware assisted TSO to work. 1262 */ 1263 encp->enc_tx_tso_tcp_header_offset_limit = 208; 1264 1265 return (0); 1266 1267 fail14: 1268 EFSYS_PROBE(fail14); 1269 fail13: 1270 EFSYS_PROBE(fail13); 1271 fail12: 1272 EFSYS_PROBE(fail12); 1273 fail11: 1274 EFSYS_PROBE(fail11); 1275 fail10: 1276 EFSYS_PROBE(fail10); 1277 fail9: 1278 EFSYS_PROBE(fail9); 1279 fail8: 1280 EFSYS_PROBE(fail8); 1281 fail7: 1282 EFSYS_PROBE(fail7); 1283 fail6: 1284 EFSYS_PROBE(fail6); 1285 fail5: 1286 EFSYS_PROBE(fail5); 1287 fail4: 1288 EFSYS_PROBE(fail4); 1289 fail3: 1290 EFSYS_PROBE(fail3); 1291 fail2: 1292 EFSYS_PROBE(fail2); 1293 fail1: 1294 EFSYS_PROBE1(fail1, int, rc); 1295 1296 return (rc); 1297 } 1298 1299 1300 __checkReturn int 1301 hunt_nic_probe( 1302 __in efx_nic_t *enp) 1303 { 1304 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1305 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1306 int rc; 1307 1308 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_HUNTINGTON); 1309 1310 /* Read and clear any assertion state */ 1311 if ((rc = efx_mcdi_read_assertion(enp)) != 0) 1312 goto fail1; 1313 1314 /* Exit the assertion handler */ 1315 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 1316 if (rc != EACCES) 1317 goto fail2; 1318 1319 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0) 1320 goto fail3; 1321 1322 if ((rc = hunt_board_cfg(enp)) != 0) 1323 if (rc != EACCES) 1324 goto fail4; 1325 1326 /* 1327 * Set default driver config limits (based on board config). 1328 * 1329 * FIXME: For now allocate a fixed number of VIs which is likely to be 1330 * sufficient and small enough to allow multiple functions on the same 1331 * port. 1332 */ 1333 edcp->edc_min_vi_count = edcp->edc_max_vi_count = 1334 MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit)); 1335 1336 /* The client driver must configure and enable PIO buffer support */ 1337 edcp->edc_max_piobuf_count = 0; 1338 edcp->edc_pio_alloc_size = 0; 1339 1340 #if EFSYS_OPT_MAC_STATS 1341 /* Wipe the MAC statistics */ 1342 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0) 1343 goto fail5; 1344 #endif 1345 1346 #if EFSYS_OPT_LOOPBACK 1347 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0) 1348 goto fail6; 1349 #endif 1350 1351 #if EFSYS_OPT_MON_STATS 1352 if ((rc = mcdi_mon_cfg_build(enp)) != 0) { 1353 /* Unprivileged functions do not have access to sensors */ 1354 if (rc != EACCES) 1355 goto fail7; 1356 } 1357 #endif 1358 1359 encp->enc_features = enp->en_features; 1360 1361 return (0); 1362 1363 #if EFSYS_OPT_MON_STATS 1364 fail7: 1365 EFSYS_PROBE(fail7); 1366 #endif 1367 #if EFSYS_OPT_LOOPBACK 1368 fail6: 1369 EFSYS_PROBE(fail6); 1370 #endif 1371 #if EFSYS_OPT_MAC_STATS 1372 fail5: 1373 EFSYS_PROBE(fail5); 1374 #endif 1375 fail4: 1376 EFSYS_PROBE(fail4); 1377 fail3: 1378 EFSYS_PROBE(fail3); 1379 fail2: 1380 EFSYS_PROBE(fail2); 1381 fail1: 1382 EFSYS_PROBE1(fail1, int, rc); 1383 1384 return (rc); 1385 } 1386 1387 __checkReturn int 1388 hunt_nic_set_drv_limits( 1389 __inout efx_nic_t *enp, 1390 __in efx_drv_limits_t *edlp) 1391 { 1392 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1393 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1394 uint32_t min_evq_count, max_evq_count; 1395 uint32_t min_rxq_count, max_rxq_count; 1396 uint32_t min_txq_count, max_txq_count; 1397 int rc; 1398 1399 if (edlp == NULL) { 1400 rc = EINVAL; 1401 goto fail1; 1402 } 1403 1404 /* Get minimum required and maximum usable VI limits */ 1405 min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit); 1406 min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit); 1407 min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit); 1408 1409 edcp->edc_min_vi_count = 1410 MAX(min_evq_count, MAX(min_rxq_count, min_txq_count)); 1411 1412 max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit); 1413 max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit); 1414 max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit); 1415 1416 edcp->edc_max_vi_count = 1417 MAX(max_evq_count, MAX(max_rxq_count, max_txq_count)); 1418 1419 /* 1420 * Check limits for sub-allocated piobuf blocks. 1421 * PIO is optional, so don't fail if the limits are incorrect. 1422 */ 1423 if ((encp->enc_piobuf_size == 0) || 1424 (encp->enc_piobuf_limit == 0) || 1425 (edlp->edl_min_pio_alloc_size == 0) || 1426 (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) { 1427 /* Disable PIO */ 1428 edcp->edc_max_piobuf_count = 0; 1429 edcp->edc_pio_alloc_size = 0; 1430 } else { 1431 uint32_t blk_size, blk_count, blks_per_piobuf; 1432 1433 blk_size = 1434 MAX(edlp->edl_min_pio_alloc_size, HUNT_MIN_PIO_ALLOC_SIZE); 1435 1436 blks_per_piobuf = encp->enc_piobuf_size / blk_size; 1437 EFSYS_ASSERT3U(blks_per_piobuf, <=, 32); 1438 1439 blk_count = (encp->enc_piobuf_limit * blks_per_piobuf); 1440 1441 /* A zero max pio alloc count means unlimited */ 1442 if ((edlp->edl_max_pio_alloc_count > 0) && 1443 (edlp->edl_max_pio_alloc_count < blk_count)) { 1444 blk_count = edlp->edl_max_pio_alloc_count; 1445 } 1446 1447 edcp->edc_pio_alloc_size = blk_size; 1448 edcp->edc_max_piobuf_count = 1449 (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf; 1450 } 1451 1452 return (0); 1453 1454 fail1: 1455 EFSYS_PROBE1(fail1, int, rc); 1456 1457 return (rc); 1458 } 1459 1460 1461 __checkReturn int 1462 hunt_nic_reset( 1463 __in efx_nic_t *enp) 1464 { 1465 efx_mcdi_req_t req; 1466 uint8_t payload[MAX(MC_CMD_ENTITY_RESET_IN_LEN, 1467 MC_CMD_ENTITY_RESET_OUT_LEN)]; 1468 int rc; 1469 1470 /* hunt_nic_reset() is called to recover from BADASSERT failures. */ 1471 if ((rc = efx_mcdi_read_assertion(enp)) != 0) 1472 goto fail1; 1473 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 1474 goto fail2; 1475 1476 (void) memset(payload, 0, sizeof (payload)); 1477 req.emr_cmd = MC_CMD_ENTITY_RESET; 1478 req.emr_in_buf = payload; 1479 req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN; 1480 req.emr_out_buf = payload; 1481 req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN; 1482 1483 MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG, 1484 ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1); 1485 1486 efx_mcdi_execute(enp, &req); 1487 1488 if (req.emr_rc != 0) { 1489 rc = req.emr_rc; 1490 goto fail3; 1491 } 1492 1493 /* Clear RX/TX DMA queue errors */ 1494 enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR); 1495 1496 return (0); 1497 1498 fail3: 1499 EFSYS_PROBE(fail3); 1500 fail2: 1501 EFSYS_PROBE(fail2); 1502 fail1: 1503 EFSYS_PROBE1(fail1, int, rc); 1504 1505 return (rc); 1506 } 1507 1508 __checkReturn int 1509 hunt_nic_init( 1510 __in efx_nic_t *enp) 1511 { 1512 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1513 uint32_t min_vi_count, max_vi_count; 1514 uint32_t vi_count, vi_base; 1515 uint32_t i; 1516 int rc; 1517 1518 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_HUNTINGTON); 1519 1520 /* Enable reporting of some events (e.g. link change) */ 1521 if ((rc = efx_mcdi_log_ctrl(enp)) != 0) 1522 goto fail1; 1523 1524 /* Allocate (optional) on-chip PIO buffers */ 1525 hunt_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count); 1526 1527 /* 1528 * For best performance, PIO writes should use a write-combined 1529 * (WC) memory mapping. Using a separate WC mapping for the PIO 1530 * aperture of each VI would be a burden to drivers (and not 1531 * possible if the host page size is >4Kbyte). 1532 * 1533 * To avoid this we use a single uncached (UC) mapping for VI 1534 * register access, and a single WC mapping for extra VIs used 1535 * for PIO writes. 1536 * 1537 * Each piobuf must be linked to a VI in the WC mapping, and to 1538 * each VI that is using a sub-allocated block from the piobuf. 1539 */ 1540 min_vi_count = edcp->edc_min_vi_count; 1541 max_vi_count = edcp->edc_max_vi_count + enp->en_u.hunt.enu_piobuf_count; 1542 1543 /* Ensure that the previously attached driver's VIs are freed */ 1544 if ((rc = efx_mcdi_free_vis(enp)) != 0) 1545 goto fail2; 1546 1547 /* 1548 * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this 1549 * fails then retrying the request for fewer VI resources may succeed. 1550 */ 1551 vi_count = 0; 1552 if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count, 1553 &vi_base, &vi_count)) != 0) 1554 goto fail3; 1555 1556 EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count); 1557 1558 if (vi_count < min_vi_count) { 1559 rc = ENOMEM; 1560 goto fail4; 1561 } 1562 1563 enp->en_u.hunt.enu_vi_base = vi_base; 1564 enp->en_u.hunt.enu_vi_count = vi_count; 1565 1566 if (vi_count < min_vi_count + enp->en_u.hunt.enu_piobuf_count) { 1567 /* Not enough extra VIs to map piobufs */ 1568 hunt_nic_free_piobufs(enp); 1569 } 1570 1571 enp->en_u.hunt.enu_pio_write_vi_base = 1572 vi_count - enp->en_u.hunt.enu_piobuf_count; 1573 1574 /* Save UC memory mapping details */ 1575 enp->en_u.hunt.enu_uc_mem_map_offset = 0; 1576 if (enp->en_u.hunt.enu_piobuf_count > 0) { 1577 enp->en_u.hunt.enu_uc_mem_map_size = 1578 (ER_DZ_TX_PIOBUF_STEP * 1579 enp->en_u.hunt.enu_pio_write_vi_base); 1580 } else { 1581 enp->en_u.hunt.enu_uc_mem_map_size = 1582 (ER_DZ_TX_PIOBUF_STEP * 1583 enp->en_u.hunt.enu_vi_count); 1584 } 1585 1586 /* Save WC memory mapping details */ 1587 enp->en_u.hunt.enu_wc_mem_map_offset = 1588 enp->en_u.hunt.enu_uc_mem_map_offset + 1589 enp->en_u.hunt.enu_uc_mem_map_size; 1590 1591 enp->en_u.hunt.enu_wc_mem_map_size = 1592 (ER_DZ_TX_PIOBUF_STEP * 1593 enp->en_u.hunt.enu_piobuf_count); 1594 1595 /* Link piobufs to extra VIs in WC mapping */ 1596 if (enp->en_u.hunt.enu_piobuf_count > 0) { 1597 for (i = 0; i < enp->en_u.hunt.enu_piobuf_count; i++) { 1598 rc = efx_mcdi_link_piobuf(enp, 1599 enp->en_u.hunt.enu_pio_write_vi_base + i, 1600 enp->en_u.hunt.enu_piobuf_handle[i]); 1601 if (rc != 0) 1602 break; 1603 } 1604 } 1605 1606 /* Allocate a vAdapter attached to our upstream vPort/pPort */ 1607 if ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) 1608 goto fail5; 1609 1610 enp->en_vport_id = EVB_PORT_ID_ASSIGNED; 1611 1612 return (0); 1613 1614 fail5: 1615 EFSYS_PROBE(fail5); 1616 fail4: 1617 EFSYS_PROBE(fail4); 1618 fail3: 1619 EFSYS_PROBE(fail3); 1620 fail2: 1621 EFSYS_PROBE(fail2); 1622 1623 hunt_nic_free_piobufs(enp); 1624 1625 fail1: 1626 EFSYS_PROBE1(fail1, int, rc); 1627 1628 return (rc); 1629 } 1630 1631 __checkReturn int 1632 hunt_nic_get_vi_pool( 1633 __in efx_nic_t *enp, 1634 __out uint32_t *vi_countp) 1635 { 1636 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_HUNTINGTON); 1637 1638 /* 1639 * Report VIs that the client driver can use. 1640 * Do not include VIs used for PIO buffer writes. 1641 */ 1642 *vi_countp = enp->en_u.hunt.enu_pio_write_vi_base; 1643 1644 return (0); 1645 } 1646 1647 __checkReturn int 1648 hunt_nic_get_bar_region( 1649 __in efx_nic_t *enp, 1650 __in efx_nic_region_t region, 1651 __out uint32_t *offsetp, 1652 __out size_t *sizep) 1653 { 1654 int rc; 1655 1656 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_HUNTINGTON); 1657 1658 /* 1659 * TODO: Specify host memory mapping alignment and granularity 1660 * in efx_drv_limits_t so that they can be taken into account 1661 * when allocating extra VIs for PIO writes. 1662 */ 1663 switch (region) { 1664 case EFX_REGION_VI: 1665 /* UC mapped memory BAR region for VI registers */ 1666 *offsetp = enp->en_u.hunt.enu_uc_mem_map_offset; 1667 *sizep = enp->en_u.hunt.enu_uc_mem_map_size; 1668 break; 1669 1670 case EFX_REGION_PIO_WRITE_VI: 1671 /* WC mapped memory BAR region for piobuf writes */ 1672 *offsetp = enp->en_u.hunt.enu_wc_mem_map_offset; 1673 *sizep = enp->en_u.hunt.enu_wc_mem_map_size; 1674 break; 1675 1676 default: 1677 rc = EINVAL; 1678 goto fail1; 1679 } 1680 1681 return (0); 1682 1683 fail1: 1684 EFSYS_PROBE1(fail1, int, rc); 1685 1686 return (rc); 1687 } 1688 1689 void 1690 hunt_nic_fini( 1691 __in efx_nic_t *enp) 1692 { 1693 (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id); 1694 enp->en_vport_id = 0; 1695 1696 /* FIXME: do we need to unlink piobufs ? */ 1697 hunt_nic_free_piobufs(enp); 1698 1699 (void) efx_mcdi_free_vis(enp); 1700 enp->en_u.hunt.enu_vi_count = 0; 1701 } 1702 1703 void 1704 hunt_nic_unprobe( 1705 __in efx_nic_t *enp) 1706 { 1707 #if EFSYS_OPT_MON_STATS 1708 mcdi_mon_cfg_free(enp); 1709 #endif /* EFSYS_OPT_MON_STATS */ 1710 (void) efx_mcdi_drv_attach(enp, B_FALSE); 1711 } 1712 1713 #if EFSYS_OPT_DIAG 1714 1715 __checkReturn int 1716 hunt_nic_register_test( 1717 __in efx_nic_t *enp) 1718 { 1719 int rc; 1720 1721 /* FIXME */ 1722 _NOTE(ARGUNUSED(enp)) 1723 if (B_FALSE) { 1724 rc = ENOTSUP; 1725 goto fail1; 1726 } 1727 /* FIXME */ 1728 1729 return (0); 1730 1731 fail1: 1732 EFSYS_PROBE1(fail1, int, rc); 1733 1734 return (rc); 1735 } 1736 1737 #endif /* EFSYS_OPT_DIAG */ 1738 1739 1740 1741 #endif /* EFSYS_OPT_HUNTINGTON */ 1742