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