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