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