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