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