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