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 { 502 efx_mcdi_req_t req; 503 uint8_t payload[MAX(MC_CMD_GET_CAPABILITIES_IN_LEN, 504 MC_CMD_GET_CAPABILITIES_V2_OUT_LEN)]; 505 efx_rc_t rc; 506 507 (void) memset(payload, 0, sizeof (payload)); 508 req.emr_cmd = MC_CMD_GET_CAPABILITIES; 509 req.emr_in_buf = payload; 510 req.emr_in_length = MC_CMD_GET_CAPABILITIES_IN_LEN; 511 req.emr_out_buf = payload; 512 req.emr_out_length = MC_CMD_GET_CAPABILITIES_V2_OUT_LEN; 513 514 efx_mcdi_execute(enp, &req); 515 516 if (req.emr_rc != 0) { 517 rc = req.emr_rc; 518 goto fail1; 519 } 520 521 if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_OUT_LEN) { 522 rc = EMSGSIZE; 523 goto fail2; 524 } 525 526 *flagsp = MCDI_OUT_DWORD(req, GET_CAPABILITIES_OUT_FLAGS1); 527 528 if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_V2_OUT_LEN) 529 *flags2p = 0; 530 else 531 *flags2p = MCDI_OUT_DWORD(req, GET_CAPABILITIES_V2_OUT_FLAGS2); 532 533 return (0); 534 535 fail2: 536 EFSYS_PROBE(fail2); 537 fail1: 538 EFSYS_PROBE1(fail1, efx_rc_t, rc); 539 540 return (rc); 541 } 542 543 544 static __checkReturn efx_rc_t 545 efx_mcdi_alloc_vis( 546 __in efx_nic_t *enp, 547 __in uint32_t min_vi_count, 548 __in uint32_t max_vi_count, 549 __out uint32_t *vi_basep, 550 __out uint32_t *vi_countp, 551 __out uint32_t *vi_shiftp) 552 { 553 efx_mcdi_req_t req; 554 uint8_t payload[MAX(MC_CMD_ALLOC_VIS_IN_LEN, 555 MC_CMD_ALLOC_VIS_OUT_LEN)]; 556 efx_rc_t rc; 557 558 if (vi_countp == NULL) { 559 rc = EINVAL; 560 goto fail1; 561 } 562 563 (void) memset(payload, 0, sizeof (payload)); 564 req.emr_cmd = MC_CMD_ALLOC_VIS; 565 req.emr_in_buf = payload; 566 req.emr_in_length = MC_CMD_ALLOC_VIS_IN_LEN; 567 req.emr_out_buf = payload; 568 req.emr_out_length = MC_CMD_ALLOC_VIS_OUT_LEN; 569 570 MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MIN_VI_COUNT, min_vi_count); 571 MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MAX_VI_COUNT, max_vi_count); 572 573 efx_mcdi_execute(enp, &req); 574 575 if (req.emr_rc != 0) { 576 rc = req.emr_rc; 577 goto fail2; 578 } 579 580 if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_OUT_LEN) { 581 rc = EMSGSIZE; 582 goto fail3; 583 } 584 585 *vi_basep = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_BASE); 586 *vi_countp = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_COUNT); 587 588 /* Report VI_SHIFT if available (always zero for Huntington) */ 589 if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_EXT_OUT_LEN) 590 *vi_shiftp = 0; 591 else 592 *vi_shiftp = MCDI_OUT_DWORD(req, ALLOC_VIS_EXT_OUT_VI_SHIFT); 593 594 return (0); 595 596 fail3: 597 EFSYS_PROBE(fail3); 598 fail2: 599 EFSYS_PROBE(fail2); 600 fail1: 601 EFSYS_PROBE1(fail1, efx_rc_t, rc); 602 603 return (rc); 604 } 605 606 607 static __checkReturn efx_rc_t 608 efx_mcdi_free_vis( 609 __in efx_nic_t *enp) 610 { 611 efx_mcdi_req_t req; 612 efx_rc_t rc; 613 614 EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_IN_LEN == 0); 615 EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_OUT_LEN == 0); 616 617 req.emr_cmd = MC_CMD_FREE_VIS; 618 req.emr_in_buf = NULL; 619 req.emr_in_length = 0; 620 req.emr_out_buf = NULL; 621 req.emr_out_length = 0; 622 623 efx_mcdi_execute_quiet(enp, &req); 624 625 /* Ignore ELREADY (no allocated VIs, so nothing to free) */ 626 if ((req.emr_rc != 0) && (req.emr_rc != EALREADY)) { 627 rc = req.emr_rc; 628 goto fail1; 629 } 630 631 return (0); 632 633 fail1: 634 EFSYS_PROBE1(fail1, efx_rc_t, rc); 635 636 return (rc); 637 } 638 639 640 static __checkReturn efx_rc_t 641 efx_mcdi_alloc_piobuf( 642 __in efx_nic_t *enp, 643 __out efx_piobuf_handle_t *handlep) 644 { 645 efx_mcdi_req_t req; 646 uint8_t payload[MAX(MC_CMD_ALLOC_PIOBUF_IN_LEN, 647 MC_CMD_ALLOC_PIOBUF_OUT_LEN)]; 648 efx_rc_t rc; 649 650 if (handlep == NULL) { 651 rc = EINVAL; 652 goto fail1; 653 } 654 655 (void) memset(payload, 0, sizeof (payload)); 656 req.emr_cmd = MC_CMD_ALLOC_PIOBUF; 657 req.emr_in_buf = payload; 658 req.emr_in_length = MC_CMD_ALLOC_PIOBUF_IN_LEN; 659 req.emr_out_buf = payload; 660 req.emr_out_length = MC_CMD_ALLOC_PIOBUF_OUT_LEN; 661 662 efx_mcdi_execute_quiet(enp, &req); 663 664 if (req.emr_rc != 0) { 665 rc = req.emr_rc; 666 goto fail2; 667 } 668 669 if (req.emr_out_length_used < MC_CMD_ALLOC_PIOBUF_OUT_LEN) { 670 rc = EMSGSIZE; 671 goto fail3; 672 } 673 674 *handlep = MCDI_OUT_DWORD(req, ALLOC_PIOBUF_OUT_PIOBUF_HANDLE); 675 676 return (0); 677 678 fail3: 679 EFSYS_PROBE(fail3); 680 fail2: 681 EFSYS_PROBE(fail2); 682 fail1: 683 EFSYS_PROBE1(fail1, efx_rc_t, rc); 684 685 return (rc); 686 } 687 688 static __checkReturn efx_rc_t 689 efx_mcdi_free_piobuf( 690 __in efx_nic_t *enp, 691 __in efx_piobuf_handle_t handle) 692 { 693 efx_mcdi_req_t req; 694 uint8_t payload[MAX(MC_CMD_FREE_PIOBUF_IN_LEN, 695 MC_CMD_FREE_PIOBUF_OUT_LEN)]; 696 efx_rc_t rc; 697 698 (void) memset(payload, 0, sizeof (payload)); 699 req.emr_cmd = MC_CMD_FREE_PIOBUF; 700 req.emr_in_buf = payload; 701 req.emr_in_length = MC_CMD_FREE_PIOBUF_IN_LEN; 702 req.emr_out_buf = payload; 703 req.emr_out_length = MC_CMD_FREE_PIOBUF_OUT_LEN; 704 705 MCDI_IN_SET_DWORD(req, FREE_PIOBUF_IN_PIOBUF_HANDLE, handle); 706 707 efx_mcdi_execute_quiet(enp, &req); 708 709 if (req.emr_rc != 0) { 710 rc = req.emr_rc; 711 goto fail1; 712 } 713 714 return (0); 715 716 fail1: 717 EFSYS_PROBE1(fail1, efx_rc_t, rc); 718 719 return (rc); 720 } 721 722 static __checkReturn efx_rc_t 723 efx_mcdi_link_piobuf( 724 __in efx_nic_t *enp, 725 __in uint32_t vi_index, 726 __in efx_piobuf_handle_t handle) 727 { 728 efx_mcdi_req_t req; 729 uint8_t payload[MAX(MC_CMD_LINK_PIOBUF_IN_LEN, 730 MC_CMD_LINK_PIOBUF_OUT_LEN)]; 731 efx_rc_t rc; 732 733 (void) memset(payload, 0, sizeof (payload)); 734 req.emr_cmd = MC_CMD_LINK_PIOBUF; 735 req.emr_in_buf = payload; 736 req.emr_in_length = MC_CMD_LINK_PIOBUF_IN_LEN; 737 req.emr_out_buf = payload; 738 req.emr_out_length = MC_CMD_LINK_PIOBUF_OUT_LEN; 739 740 MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_PIOBUF_HANDLE, handle); 741 MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_TXQ_INSTANCE, vi_index); 742 743 efx_mcdi_execute(enp, &req); 744 745 if (req.emr_rc != 0) { 746 rc = req.emr_rc; 747 goto fail1; 748 } 749 750 return (0); 751 752 fail1: 753 EFSYS_PROBE1(fail1, efx_rc_t, rc); 754 755 return (rc); 756 } 757 758 static __checkReturn efx_rc_t 759 efx_mcdi_unlink_piobuf( 760 __in efx_nic_t *enp, 761 __in uint32_t vi_index) 762 { 763 efx_mcdi_req_t req; 764 uint8_t payload[MAX(MC_CMD_UNLINK_PIOBUF_IN_LEN, 765 MC_CMD_UNLINK_PIOBUF_OUT_LEN)]; 766 efx_rc_t rc; 767 768 (void) memset(payload, 0, sizeof (payload)); 769 req.emr_cmd = MC_CMD_UNLINK_PIOBUF; 770 req.emr_in_buf = payload; 771 req.emr_in_length = MC_CMD_UNLINK_PIOBUF_IN_LEN; 772 req.emr_out_buf = payload; 773 req.emr_out_length = MC_CMD_UNLINK_PIOBUF_OUT_LEN; 774 775 MCDI_IN_SET_DWORD(req, UNLINK_PIOBUF_IN_TXQ_INSTANCE, vi_index); 776 777 efx_mcdi_execute_quiet(enp, &req); 778 779 if (req.emr_rc != 0) { 780 rc = req.emr_rc; 781 goto fail1; 782 } 783 784 return (0); 785 786 fail1: 787 EFSYS_PROBE1(fail1, efx_rc_t, rc); 788 789 return (rc); 790 } 791 792 static void 793 ef10_nic_alloc_piobufs( 794 __in efx_nic_t *enp, 795 __in uint32_t max_piobuf_count) 796 { 797 efx_piobuf_handle_t *handlep; 798 unsigned int i; 799 800 EFSYS_ASSERT3U(max_piobuf_count, <=, 801 EFX_ARRAY_SIZE(enp->en_arch.ef10.ena_piobuf_handle)); 802 803 enp->en_arch.ef10.ena_piobuf_count = 0; 804 805 for (i = 0; i < max_piobuf_count; i++) { 806 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i]; 807 808 if (efx_mcdi_alloc_piobuf(enp, handlep) != 0) 809 goto fail1; 810 811 enp->en_arch.ef10.ena_pio_alloc_map[i] = 0; 812 enp->en_arch.ef10.ena_piobuf_count++; 813 } 814 815 return; 816 817 fail1: 818 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 819 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i]; 820 821 efx_mcdi_free_piobuf(enp, *handlep); 822 *handlep = EFX_PIOBUF_HANDLE_INVALID; 823 } 824 enp->en_arch.ef10.ena_piobuf_count = 0; 825 } 826 827 828 static void 829 ef10_nic_free_piobufs( 830 __in efx_nic_t *enp) 831 { 832 efx_piobuf_handle_t *handlep; 833 unsigned int i; 834 835 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 836 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i]; 837 838 efx_mcdi_free_piobuf(enp, *handlep); 839 *handlep = EFX_PIOBUF_HANDLE_INVALID; 840 } 841 enp->en_arch.ef10.ena_piobuf_count = 0; 842 } 843 844 /* Sub-allocate a block from a piobuf */ 845 __checkReturn efx_rc_t 846 ef10_nic_pio_alloc( 847 __inout efx_nic_t *enp, 848 __out uint32_t *bufnump, 849 __out efx_piobuf_handle_t *handlep, 850 __out uint32_t *blknump, 851 __out uint32_t *offsetp, 852 __out size_t *sizep) 853 { 854 efx_nic_cfg_t *encp = &enp->en_nic_cfg; 855 efx_drv_cfg_t *edcp = &enp->en_drv_cfg; 856 uint32_t blk_per_buf; 857 uint32_t buf, blk; 858 efx_rc_t rc; 859 860 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 861 enp->en_family == EFX_FAMILY_MEDFORD); 862 EFSYS_ASSERT(bufnump); 863 EFSYS_ASSERT(handlep); 864 EFSYS_ASSERT(blknump); 865 EFSYS_ASSERT(offsetp); 866 EFSYS_ASSERT(sizep); 867 868 if ((edcp->edc_pio_alloc_size == 0) || 869 (enp->en_arch.ef10.ena_piobuf_count == 0)) { 870 rc = ENOMEM; 871 goto fail1; 872 } 873 blk_per_buf = encp->enc_piobuf_size / edcp->edc_pio_alloc_size; 874 875 for (buf = 0; buf < enp->en_arch.ef10.ena_piobuf_count; buf++) { 876 uint32_t *map = &enp->en_arch.ef10.ena_pio_alloc_map[buf]; 877 878 if (~(*map) == 0) 879 continue; 880 881 EFSYS_ASSERT3U(blk_per_buf, <=, (8 * sizeof (*map))); 882 for (blk = 0; blk < blk_per_buf; blk++) { 883 if ((*map & (1u << blk)) == 0) { 884 *map |= (1u << blk); 885 goto done; 886 } 887 } 888 } 889 rc = ENOMEM; 890 goto fail2; 891 892 done: 893 *handlep = enp->en_arch.ef10.ena_piobuf_handle[buf]; 894 *bufnump = buf; 895 *blknump = blk; 896 *sizep = edcp->edc_pio_alloc_size; 897 *offsetp = blk * (*sizep); 898 899 return (0); 900 901 fail2: 902 EFSYS_PROBE(fail2); 903 fail1: 904 EFSYS_PROBE1(fail1, efx_rc_t, rc); 905 906 return (rc); 907 } 908 909 /* Free a piobuf sub-allocated block */ 910 __checkReturn efx_rc_t 911 ef10_nic_pio_free( 912 __inout efx_nic_t *enp, 913 __in uint32_t bufnum, 914 __in uint32_t blknum) 915 { 916 uint32_t *map; 917 efx_rc_t rc; 918 919 if ((bufnum >= enp->en_arch.ef10.ena_piobuf_count) || 920 (blknum >= (8 * sizeof (*map)))) { 921 rc = EINVAL; 922 goto fail1; 923 } 924 925 map = &enp->en_arch.ef10.ena_pio_alloc_map[bufnum]; 926 if ((*map & (1u << blknum)) == 0) { 927 rc = ENOENT; 928 goto fail2; 929 } 930 *map &= ~(1u << blknum); 931 932 return (0); 933 934 fail2: 935 EFSYS_PROBE(fail2); 936 fail1: 937 EFSYS_PROBE1(fail1, efx_rc_t, rc); 938 939 return (rc); 940 } 941 942 __checkReturn efx_rc_t 943 ef10_nic_pio_link( 944 __inout efx_nic_t *enp, 945 __in uint32_t vi_index, 946 __in efx_piobuf_handle_t handle) 947 { 948 return (efx_mcdi_link_piobuf(enp, vi_index, handle)); 949 } 950 951 __checkReturn efx_rc_t 952 ef10_nic_pio_unlink( 953 __inout efx_nic_t *enp, 954 __in uint32_t vi_index) 955 { 956 return (efx_mcdi_unlink_piobuf(enp, vi_index)); 957 } 958 959 __checkReturn efx_rc_t 960 ef10_get_datapath_caps( 961 __in efx_nic_t *enp) 962 { 963 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 964 uint32_t flags; 965 uint32_t flags2; 966 efx_rc_t rc; 967 968 if ((rc = efx_mcdi_get_capabilities(enp, &flags, &flags2)) != 0) 969 goto fail1; 970 971 #define CAP_FLAG(flags1, field) \ 972 ((flags1) & (1 << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## field ## _LBN))) 973 974 #define CAP_FLAG2(flags2, field) \ 975 ((flags2) & (1 << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## field ## _LBN))) 976 977 /* 978 * Huntington RXDP firmware inserts a 0 or 14 byte prefix. 979 * We only support the 14 byte prefix here. 980 */ 981 if (CAP_FLAG(flags, RX_PREFIX_LEN_14) == 0) { 982 rc = ENOTSUP; 983 goto fail2; 984 } 985 encp->enc_rx_prefix_size = 14; 986 987 /* Check if the firmware supports TSO */ 988 encp->enc_fw_assisted_tso_enabled = 989 CAP_FLAG(flags, TX_TSO) ? B_TRUE : B_FALSE; 990 991 /* Check if the firmware supports FATSOv2 */ 992 encp->enc_fw_assisted_tso_v2_enabled = 993 CAP_FLAG2(flags2, TX_TSO_V2) ? B_TRUE : B_FALSE; 994 995 /* Check if the firmware has vadapter/vport/vswitch support */ 996 encp->enc_datapath_cap_evb = 997 CAP_FLAG(flags, EVB) ? B_TRUE : B_FALSE; 998 999 /* Check if the firmware supports VLAN insertion */ 1000 encp->enc_hw_tx_insert_vlan_enabled = 1001 CAP_FLAG(flags, TX_VLAN_INSERTION) ? B_TRUE : B_FALSE; 1002 1003 /* Check if the firmware supports RX event batching */ 1004 encp->enc_rx_batching_enabled = 1005 CAP_FLAG(flags, RX_BATCHING) ? B_TRUE : B_FALSE; 1006 1007 /* 1008 * Even if batching isn't reported as supported, we may still get 1009 * batched events. 1010 */ 1011 encp->enc_rx_batch_max = 16; 1012 1013 /* Check if the firmware supports disabling scatter on RXQs */ 1014 encp->enc_rx_disable_scatter_supported = 1015 CAP_FLAG(flags, RX_DISABLE_SCATTER) ? B_TRUE : B_FALSE; 1016 1017 /* Check if the firmware supports set mac with running filters */ 1018 encp->enc_allow_set_mac_with_installed_filters = 1019 CAP_FLAG(flags, VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED) ? 1020 B_TRUE : B_FALSE; 1021 1022 /* 1023 * Check if firmware supports the extended MC_CMD_SET_MAC, which allows 1024 * specifying which parameters to configure. 1025 */ 1026 encp->enc_enhanced_set_mac_supported = 1027 CAP_FLAG(flags, SET_MAC_ENHANCED) ? B_TRUE : B_FALSE; 1028 1029 /* 1030 * Check if firmware supports version 2 of MC_CMD_INIT_EVQ, which allows 1031 * us to let the firmware choose the settings to use on an EVQ. 1032 */ 1033 encp->enc_init_evq_v2_supported = 1034 CAP_FLAG2(flags2, INIT_EVQ_V2) ? B_TRUE : B_FALSE; 1035 1036 #undef CAP_FLAG 1037 #undef CAP_FLAG2 1038 1039 return (0); 1040 1041 fail2: 1042 EFSYS_PROBE(fail2); 1043 fail1: 1044 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1045 1046 return (rc); 1047 } 1048 1049 1050 #define EF10_LEGACY_PF_PRIVILEGE_MASK \ 1051 (MC_CMD_PRIVILEGE_MASK_IN_GRP_ADMIN | \ 1052 MC_CMD_PRIVILEGE_MASK_IN_GRP_LINK | \ 1053 MC_CMD_PRIVILEGE_MASK_IN_GRP_ONLOAD | \ 1054 MC_CMD_PRIVILEGE_MASK_IN_GRP_PTP | \ 1055 MC_CMD_PRIVILEGE_MASK_IN_GRP_INSECURE_FILTERS | \ 1056 MC_CMD_PRIVILEGE_MASK_IN_GRP_MAC_SPOOFING | \ 1057 MC_CMD_PRIVILEGE_MASK_IN_GRP_UNICAST | \ 1058 MC_CMD_PRIVILEGE_MASK_IN_GRP_MULTICAST | \ 1059 MC_CMD_PRIVILEGE_MASK_IN_GRP_BROADCAST | \ 1060 MC_CMD_PRIVILEGE_MASK_IN_GRP_ALL_MULTICAST | \ 1061 MC_CMD_PRIVILEGE_MASK_IN_GRP_PROMISCUOUS) 1062 1063 #define EF10_LEGACY_VF_PRIVILEGE_MASK 0 1064 1065 1066 __checkReturn efx_rc_t 1067 ef10_get_privilege_mask( 1068 __in efx_nic_t *enp, 1069 __out uint32_t *maskp) 1070 { 1071 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1072 uint32_t mask; 1073 efx_rc_t rc; 1074 1075 if ((rc = efx_mcdi_privilege_mask(enp, encp->enc_pf, encp->enc_vf, 1076 &mask)) != 0) { 1077 if (rc != ENOTSUP) 1078 goto fail1; 1079 1080 /* Fallback for old firmware without privilege mask support */ 1081 if (EFX_PCI_FUNCTION_IS_PF(encp)) { 1082 /* Assume PF has admin privilege */ 1083 mask = EF10_LEGACY_PF_PRIVILEGE_MASK; 1084 } else { 1085 /* VF is always unprivileged by default */ 1086 mask = EF10_LEGACY_VF_PRIVILEGE_MASK; 1087 } 1088 } 1089 1090 *maskp = mask; 1091 1092 return (0); 1093 1094 fail1: 1095 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1096 1097 return (rc); 1098 } 1099 1100 1101 /* 1102 * Table of mapping schemes from port number to the number of the external 1103 * connector on the board. The external numbering does not distinguish 1104 * off-board separated outputs such as from multi-headed cables. 1105 * 1106 * The count of adjacent port numbers that map to each external port 1107 * and the offset in the numbering, is determined by the chip family and 1108 * current port mode. 1109 * 1110 * For the Huntington family, the current port mode cannot be discovered, 1111 * so the mapping used is instead the last match in the table to the full 1112 * set of port modes to which the NIC can be configured. Therefore the 1113 * ordering of entries in the the mapping table is significant. 1114 */ 1115 static struct { 1116 efx_family_t family; 1117 uint32_t modes_mask; 1118 int32_t count; 1119 int32_t offset; 1120 } __ef10_external_port_mappings[] = { 1121 /* Supported modes with 1 output per external port */ 1122 { 1123 EFX_FAMILY_HUNTINGTON, 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 1 1129 }, 1130 { 1131 EFX_FAMILY_MEDFORD, 1132 (1 << TLV_PORT_MODE_10G) | 1133 (1 << TLV_PORT_MODE_10G_10G), 1134 1, 1135 1 1136 }, 1137 /* Supported modes with 2 outputs per external port */ 1138 { 1139 EFX_FAMILY_HUNTINGTON, 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 1 1146 }, 1147 { 1148 EFX_FAMILY_MEDFORD, 1149 (1 << TLV_PORT_MODE_40G) | 1150 (1 << TLV_PORT_MODE_40G_40G) | 1151 (1 << TLV_PORT_MODE_40G_10G_10G) | 1152 (1 << TLV_PORT_MODE_10G_10G_40G) | 1153 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2), 1154 2, 1155 1 1156 }, 1157 /* Supported modes with 4 outputs per external port */ 1158 { 1159 EFX_FAMILY_MEDFORD, 1160 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q) | 1161 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q1), 1162 4, 1163 1, 1164 }, 1165 { 1166 EFX_FAMILY_MEDFORD, 1167 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q2), 1168 4, 1169 2 1170 }, 1171 }; 1172 1173 __checkReturn efx_rc_t 1174 ef10_external_port_mapping( 1175 __in efx_nic_t *enp, 1176 __in uint32_t port, 1177 __out uint8_t *external_portp) 1178 { 1179 efx_rc_t rc; 1180 int i; 1181 uint32_t port_modes; 1182 uint32_t matches; 1183 uint32_t current; 1184 int32_t count = 1; /* Default 1-1 mapping */ 1185 int32_t offset = 1; /* Default starting external port number */ 1186 1187 if ((rc = efx_mcdi_get_port_modes(enp, &port_modes, ¤t)) != 0) { 1188 /* 1189 * No current port mode information 1190 * - infer mapping from available modes 1191 */ 1192 if ((rc = efx_mcdi_get_port_modes(enp, 1193 &port_modes, NULL)) != 0) { 1194 /* 1195 * No port mode information available 1196 * - use default mapping 1197 */ 1198 goto out; 1199 } 1200 } else { 1201 /* Only need to scan the current mode */ 1202 port_modes = 1 << current; 1203 } 1204 1205 /* 1206 * Infer the internal port -> external port mapping from 1207 * the possible port modes for this NIC. 1208 */ 1209 for (i = 0; i < EFX_ARRAY_SIZE(__ef10_external_port_mappings); ++i) { 1210 if (__ef10_external_port_mappings[i].family != 1211 enp->en_family) 1212 continue; 1213 matches = (__ef10_external_port_mappings[i].modes_mask & 1214 port_modes); 1215 if (matches != 0) { 1216 count = __ef10_external_port_mappings[i].count; 1217 offset = __ef10_external_port_mappings[i].offset; 1218 port_modes &= ~matches; 1219 } 1220 } 1221 1222 if (port_modes != 0) { 1223 /* Some advertised modes are not supported */ 1224 rc = ENOTSUP; 1225 goto fail1; 1226 } 1227 1228 out: 1229 /* 1230 * Scale as required by last matched mode and then convert to 1231 * correctly offset numbering 1232 */ 1233 *external_portp = (uint8_t)((port / count) + offset); 1234 return (0); 1235 1236 fail1: 1237 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1238 1239 return (rc); 1240 } 1241 1242 1243 __checkReturn efx_rc_t 1244 ef10_nic_probe( 1245 __in efx_nic_t *enp) 1246 { 1247 const efx_nic_ops_t *enop = enp->en_enop; 1248 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1249 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1250 efx_rc_t rc; 1251 1252 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1253 enp->en_family == EFX_FAMILY_MEDFORD); 1254 1255 /* Read and clear any assertion state */ 1256 if ((rc = efx_mcdi_read_assertion(enp)) != 0) 1257 goto fail1; 1258 1259 /* Exit the assertion handler */ 1260 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 1261 if (rc != EACCES) 1262 goto fail2; 1263 1264 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0) 1265 goto fail3; 1266 1267 if ((rc = enop->eno_board_cfg(enp)) != 0) 1268 if (rc != EACCES) 1269 goto fail4; 1270 1271 /* 1272 * Set default driver config limits (based on board config). 1273 * 1274 * FIXME: For now allocate a fixed number of VIs which is likely to be 1275 * sufficient and small enough to allow multiple functions on the same 1276 * port. 1277 */ 1278 edcp->edc_min_vi_count = edcp->edc_max_vi_count = 1279 MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit)); 1280 1281 /* The client driver must configure and enable PIO buffer support */ 1282 edcp->edc_max_piobuf_count = 0; 1283 edcp->edc_pio_alloc_size = 0; 1284 1285 #if EFSYS_OPT_MAC_STATS 1286 /* Wipe the MAC statistics */ 1287 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0) 1288 goto fail5; 1289 #endif 1290 1291 #if EFSYS_OPT_LOOPBACK 1292 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0) 1293 goto fail6; 1294 #endif 1295 1296 #if EFSYS_OPT_MON_STATS 1297 if ((rc = mcdi_mon_cfg_build(enp)) != 0) { 1298 /* Unprivileged functions do not have access to sensors */ 1299 if (rc != EACCES) 1300 goto fail7; 1301 } 1302 #endif 1303 1304 encp->enc_features = enp->en_features; 1305 1306 return (0); 1307 1308 #if EFSYS_OPT_MON_STATS 1309 fail7: 1310 EFSYS_PROBE(fail7); 1311 #endif 1312 #if EFSYS_OPT_LOOPBACK 1313 fail6: 1314 EFSYS_PROBE(fail6); 1315 #endif 1316 #if EFSYS_OPT_MAC_STATS 1317 fail5: 1318 EFSYS_PROBE(fail5); 1319 #endif 1320 fail4: 1321 EFSYS_PROBE(fail4); 1322 fail3: 1323 EFSYS_PROBE(fail3); 1324 fail2: 1325 EFSYS_PROBE(fail2); 1326 fail1: 1327 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1328 1329 return (rc); 1330 } 1331 1332 __checkReturn efx_rc_t 1333 ef10_nic_set_drv_limits( 1334 __inout efx_nic_t *enp, 1335 __in efx_drv_limits_t *edlp) 1336 { 1337 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1338 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1339 uint32_t min_evq_count, max_evq_count; 1340 uint32_t min_rxq_count, max_rxq_count; 1341 uint32_t min_txq_count, max_txq_count; 1342 efx_rc_t rc; 1343 1344 if (edlp == NULL) { 1345 rc = EINVAL; 1346 goto fail1; 1347 } 1348 1349 /* Get minimum required and maximum usable VI limits */ 1350 min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit); 1351 min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit); 1352 min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit); 1353 1354 edcp->edc_min_vi_count = 1355 MAX(min_evq_count, MAX(min_rxq_count, min_txq_count)); 1356 1357 max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit); 1358 max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit); 1359 max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit); 1360 1361 edcp->edc_max_vi_count = 1362 MAX(max_evq_count, MAX(max_rxq_count, max_txq_count)); 1363 1364 /* 1365 * Check limits for sub-allocated piobuf blocks. 1366 * PIO is optional, so don't fail if the limits are incorrect. 1367 */ 1368 if ((encp->enc_piobuf_size == 0) || 1369 (encp->enc_piobuf_limit == 0) || 1370 (edlp->edl_min_pio_alloc_size == 0) || 1371 (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) { 1372 /* Disable PIO */ 1373 edcp->edc_max_piobuf_count = 0; 1374 edcp->edc_pio_alloc_size = 0; 1375 } else { 1376 uint32_t blk_size, blk_count, blks_per_piobuf; 1377 1378 blk_size = 1379 MAX(edlp->edl_min_pio_alloc_size, 1380 encp->enc_piobuf_min_alloc_size); 1381 1382 blks_per_piobuf = encp->enc_piobuf_size / blk_size; 1383 EFSYS_ASSERT3U(blks_per_piobuf, <=, 32); 1384 1385 blk_count = (encp->enc_piobuf_limit * blks_per_piobuf); 1386 1387 /* A zero max pio alloc count means unlimited */ 1388 if ((edlp->edl_max_pio_alloc_count > 0) && 1389 (edlp->edl_max_pio_alloc_count < blk_count)) { 1390 blk_count = edlp->edl_max_pio_alloc_count; 1391 } 1392 1393 edcp->edc_pio_alloc_size = blk_size; 1394 edcp->edc_max_piobuf_count = 1395 (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf; 1396 } 1397 1398 return (0); 1399 1400 fail1: 1401 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1402 1403 return (rc); 1404 } 1405 1406 1407 __checkReturn efx_rc_t 1408 ef10_nic_reset( 1409 __in efx_nic_t *enp) 1410 { 1411 efx_mcdi_req_t req; 1412 uint8_t payload[MAX(MC_CMD_ENTITY_RESET_IN_LEN, 1413 MC_CMD_ENTITY_RESET_OUT_LEN)]; 1414 efx_rc_t rc; 1415 1416 /* ef10_nic_reset() is called to recover from BADASSERT failures. */ 1417 if ((rc = efx_mcdi_read_assertion(enp)) != 0) 1418 goto fail1; 1419 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 1420 goto fail2; 1421 1422 (void) memset(payload, 0, sizeof (payload)); 1423 req.emr_cmd = MC_CMD_ENTITY_RESET; 1424 req.emr_in_buf = payload; 1425 req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN; 1426 req.emr_out_buf = payload; 1427 req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN; 1428 1429 MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG, 1430 ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1); 1431 1432 efx_mcdi_execute(enp, &req); 1433 1434 if (req.emr_rc != 0) { 1435 rc = req.emr_rc; 1436 goto fail3; 1437 } 1438 1439 /* Clear RX/TX DMA queue errors */ 1440 enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR); 1441 1442 return (0); 1443 1444 fail3: 1445 EFSYS_PROBE(fail3); 1446 fail2: 1447 EFSYS_PROBE(fail2); 1448 fail1: 1449 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1450 1451 return (rc); 1452 } 1453 1454 __checkReturn efx_rc_t 1455 ef10_nic_init( 1456 __in efx_nic_t *enp) 1457 { 1458 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1459 uint32_t min_vi_count, max_vi_count; 1460 uint32_t vi_count, vi_base, vi_shift; 1461 uint32_t i; 1462 uint32_t retry; 1463 uint32_t delay_us; 1464 efx_rc_t rc; 1465 1466 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1467 enp->en_family == EFX_FAMILY_MEDFORD); 1468 1469 /* Enable reporting of some events (e.g. link change) */ 1470 if ((rc = efx_mcdi_log_ctrl(enp)) != 0) 1471 goto fail1; 1472 1473 /* Allocate (optional) on-chip PIO buffers */ 1474 ef10_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count); 1475 1476 /* 1477 * For best performance, PIO writes should use a write-combined 1478 * (WC) memory mapping. Using a separate WC mapping for the PIO 1479 * aperture of each VI would be a burden to drivers (and not 1480 * possible if the host page size is >4Kbyte). 1481 * 1482 * To avoid this we use a single uncached (UC) mapping for VI 1483 * register access, and a single WC mapping for extra VIs used 1484 * for PIO writes. 1485 * 1486 * Each piobuf must be linked to a VI in the WC mapping, and to 1487 * each VI that is using a sub-allocated block from the piobuf. 1488 */ 1489 min_vi_count = edcp->edc_min_vi_count; 1490 max_vi_count = 1491 edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count; 1492 1493 /* Ensure that the previously attached driver's VIs are freed */ 1494 if ((rc = efx_mcdi_free_vis(enp)) != 0) 1495 goto fail2; 1496 1497 /* 1498 * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this 1499 * fails then retrying the request for fewer VI resources may succeed. 1500 */ 1501 vi_count = 0; 1502 if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count, 1503 &vi_base, &vi_count, &vi_shift)) != 0) 1504 goto fail3; 1505 1506 EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count); 1507 1508 if (vi_count < min_vi_count) { 1509 rc = ENOMEM; 1510 goto fail4; 1511 } 1512 1513 enp->en_arch.ef10.ena_vi_base = vi_base; 1514 enp->en_arch.ef10.ena_vi_count = vi_count; 1515 enp->en_arch.ef10.ena_vi_shift = vi_shift; 1516 1517 if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) { 1518 /* Not enough extra VIs to map piobufs */ 1519 ef10_nic_free_piobufs(enp); 1520 } 1521 1522 enp->en_arch.ef10.ena_pio_write_vi_base = 1523 vi_count - enp->en_arch.ef10.ena_piobuf_count; 1524 1525 /* Save UC memory mapping details */ 1526 enp->en_arch.ef10.ena_uc_mem_map_offset = 0; 1527 if (enp->en_arch.ef10.ena_piobuf_count > 0) { 1528 enp->en_arch.ef10.ena_uc_mem_map_size = 1529 (ER_DZ_TX_PIOBUF_STEP * 1530 enp->en_arch.ef10.ena_pio_write_vi_base); 1531 } else { 1532 enp->en_arch.ef10.ena_uc_mem_map_size = 1533 (ER_DZ_TX_PIOBUF_STEP * 1534 enp->en_arch.ef10.ena_vi_count); 1535 } 1536 1537 /* Save WC memory mapping details */ 1538 enp->en_arch.ef10.ena_wc_mem_map_offset = 1539 enp->en_arch.ef10.ena_uc_mem_map_offset + 1540 enp->en_arch.ef10.ena_uc_mem_map_size; 1541 1542 enp->en_arch.ef10.ena_wc_mem_map_size = 1543 (ER_DZ_TX_PIOBUF_STEP * 1544 enp->en_arch.ef10.ena_piobuf_count); 1545 1546 /* Link piobufs to extra VIs in WC mapping */ 1547 if (enp->en_arch.ef10.ena_piobuf_count > 0) { 1548 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 1549 rc = efx_mcdi_link_piobuf(enp, 1550 enp->en_arch.ef10.ena_pio_write_vi_base + i, 1551 enp->en_arch.ef10.ena_piobuf_handle[i]); 1552 if (rc != 0) 1553 break; 1554 } 1555 } 1556 1557 /* 1558 * Allocate a vAdaptor attached to our upstream vPort/pPort. 1559 * 1560 * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF 1561 * driver has yet to bring up the EVB port. See bug 56147. In this case, 1562 * retry the request several times after waiting a while. The wait time 1563 * between retries starts small (10ms) and exponentially increases. 1564 * Total wait time is a little over two seconds. Retry logic in the 1565 * client driver may mean this whole loop is repeated if it continues to 1566 * fail. 1567 */ 1568 retry = 0; 1569 delay_us = 10000; 1570 while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) { 1571 if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) || 1572 (rc != ENOENT)) { 1573 /* 1574 * Do not retry alloc for PF, or for other errors on 1575 * a VF. 1576 */ 1577 goto fail5; 1578 } 1579 1580 /* VF startup before PF is ready. Retry allocation. */ 1581 if (retry > 5) { 1582 /* Too many attempts */ 1583 rc = EINVAL; 1584 goto fail6; 1585 } 1586 EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry); 1587 EFSYS_SLEEP(delay_us); 1588 retry++; 1589 if (delay_us < 500000) 1590 delay_us <<= 2; 1591 } 1592 1593 enp->en_vport_id = EVB_PORT_ID_ASSIGNED; 1594 enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2; 1595 1596 return (0); 1597 1598 fail6: 1599 EFSYS_PROBE(fail6); 1600 fail5: 1601 EFSYS_PROBE(fail5); 1602 fail4: 1603 EFSYS_PROBE(fail4); 1604 fail3: 1605 EFSYS_PROBE(fail3); 1606 fail2: 1607 EFSYS_PROBE(fail2); 1608 1609 ef10_nic_free_piobufs(enp); 1610 1611 fail1: 1612 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1613 1614 return (rc); 1615 } 1616 1617 __checkReturn efx_rc_t 1618 ef10_nic_get_vi_pool( 1619 __in efx_nic_t *enp, 1620 __out uint32_t *vi_countp) 1621 { 1622 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1623 enp->en_family == EFX_FAMILY_MEDFORD); 1624 1625 /* 1626 * Report VIs that the client driver can use. 1627 * Do not include VIs used for PIO buffer writes. 1628 */ 1629 *vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base; 1630 1631 return (0); 1632 } 1633 1634 __checkReturn efx_rc_t 1635 ef10_nic_get_bar_region( 1636 __in efx_nic_t *enp, 1637 __in efx_nic_region_t region, 1638 __out uint32_t *offsetp, 1639 __out size_t *sizep) 1640 { 1641 efx_rc_t rc; 1642 1643 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1644 enp->en_family == EFX_FAMILY_MEDFORD); 1645 1646 /* 1647 * TODO: Specify host memory mapping alignment and granularity 1648 * in efx_drv_limits_t so that they can be taken into account 1649 * when allocating extra VIs for PIO writes. 1650 */ 1651 switch (region) { 1652 case EFX_REGION_VI: 1653 /* UC mapped memory BAR region for VI registers */ 1654 *offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset; 1655 *sizep = enp->en_arch.ef10.ena_uc_mem_map_size; 1656 break; 1657 1658 case EFX_REGION_PIO_WRITE_VI: 1659 /* WC mapped memory BAR region for piobuf writes */ 1660 *offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset; 1661 *sizep = enp->en_arch.ef10.ena_wc_mem_map_size; 1662 break; 1663 1664 default: 1665 rc = EINVAL; 1666 goto fail1; 1667 } 1668 1669 return (0); 1670 1671 fail1: 1672 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1673 1674 return (rc); 1675 } 1676 1677 void 1678 ef10_nic_fini( 1679 __in efx_nic_t *enp) 1680 { 1681 uint32_t i; 1682 efx_rc_t rc; 1683 1684 (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id); 1685 enp->en_vport_id = 0; 1686 1687 /* Unlink piobufs from extra VIs in WC mapping */ 1688 if (enp->en_arch.ef10.ena_piobuf_count > 0) { 1689 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 1690 rc = efx_mcdi_unlink_piobuf(enp, 1691 enp->en_arch.ef10.ena_pio_write_vi_base + i); 1692 if (rc != 0) 1693 break; 1694 } 1695 } 1696 1697 ef10_nic_free_piobufs(enp); 1698 1699 (void) efx_mcdi_free_vis(enp); 1700 enp->en_arch.ef10.ena_vi_count = 0; 1701 } 1702 1703 void 1704 ef10_nic_unprobe( 1705 __in efx_nic_t *enp) 1706 { 1707 #if EFSYS_OPT_MON_STATS 1708 mcdi_mon_cfg_free(enp); 1709 #endif /* EFSYS_OPT_MON_STATS */ 1710 (void) efx_mcdi_drv_attach(enp, B_FALSE); 1711 } 1712 1713 #if EFSYS_OPT_DIAG 1714 1715 __checkReturn efx_rc_t 1716 ef10_nic_register_test( 1717 __in efx_nic_t *enp) 1718 { 1719 efx_rc_t rc; 1720 1721 /* FIXME */ 1722 _NOTE(ARGUNUSED(enp)) 1723 _NOTE(CONSTANTCONDITION) 1724 if (B_FALSE) { 1725 rc = ENOTSUP; 1726 goto fail1; 1727 } 1728 /* FIXME */ 1729 1730 return (0); 1731 1732 fail1: 1733 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1734 1735 return (rc); 1736 } 1737 1738 #endif /* EFSYS_OPT_DIAG */ 1739 1740 1741 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 1742