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