ef10_nic.c revision 301309
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: head/sys/dev/sfxge/common/ef10_nic.c 301309 2016-06-04 09:20:46Z 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 __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 435fail4: 436 EFSYS_PROBE(fail4); 437fail3: 438 EFSYS_PROBE(fail3); 439fail2: 440 EFSYS_PROBE(fail2); 441fail1: 442 EFSYS_PROBE1(fail1, efx_rc_t, rc); 443 444 return (rc); 445} 446 447 __checkReturn efx_rc_t 448efx_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 487fail2: 488 EFSYS_PROBE(fail2); 489fail1: 490 EFSYS_PROBE1(fail1, efx_rc_t, rc); 491 492 return (rc); 493} 494 495static __checkReturn efx_rc_t 496efx_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 534fail2: 535 EFSYS_PROBE(fail2); 536fail1: 537 EFSYS_PROBE1(fail1, efx_rc_t, rc); 538 539 return (rc); 540} 541 542 543static __checkReturn efx_rc_t 544efx_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 595fail3: 596 EFSYS_PROBE(fail3); 597fail2: 598 EFSYS_PROBE(fail2); 599fail1: 600 EFSYS_PROBE1(fail1, efx_rc_t, rc); 601 602 return (rc); 603} 604 605 606static __checkReturn efx_rc_t 607efx_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 632fail1: 633 EFSYS_PROBE1(fail1, efx_rc_t, rc); 634 635 return (rc); 636} 637 638 639static __checkReturn efx_rc_t 640efx_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 677fail3: 678 EFSYS_PROBE(fail3); 679fail2: 680 EFSYS_PROBE(fail2); 681fail1: 682 EFSYS_PROBE1(fail1, efx_rc_t, rc); 683 684 return (rc); 685} 686 687static __checkReturn efx_rc_t 688efx_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 715fail1: 716 EFSYS_PROBE1(fail1, efx_rc_t, rc); 717 718 return (rc); 719} 720 721static __checkReturn efx_rc_t 722efx_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 751fail1: 752 EFSYS_PROBE1(fail1, efx_rc_t, rc); 753 754 return (rc); 755} 756 757static __checkReturn efx_rc_t 758efx_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 785fail1: 786 EFSYS_PROBE1(fail1, efx_rc_t, rc); 787 788 return (rc); 789} 790 791static void 792ef10_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 816fail1: 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 827static void 828ef10_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 845ef10_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 891done: 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 900fail2: 901 EFSYS_PROBE(fail2); 902fail1: 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 910ef10_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 933fail2: 934 EFSYS_PROBE(fail2); 935fail1: 936 EFSYS_PROBE1(fail1, efx_rc_t, rc); 937 938 return (rc); 939} 940 941 __checkReturn efx_rc_t 942ef10_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 951ef10_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 959ef10_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 /* 1007 * Even if batching isn't reported as supported, we may still get 1008 * batched events. 1009 */ 1010 encp->enc_rx_batch_max = 16; 1011 1012 /* Check if the firmware supports disabling scatter on RXQs */ 1013 encp->enc_rx_disable_scatter_supported = 1014 CAP_FLAG(flags, RX_DISABLE_SCATTER) ? B_TRUE : B_FALSE; 1015 1016 /* Check if the firmware supports set mac with running filters */ 1017 encp->enc_allow_set_mac_with_installed_filters = 1018 CAP_FLAG(flags, VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED) ? 1019 B_TRUE : B_FALSE; 1020 1021 /* 1022 * Check if firmware supports the extended MC_CMD_SET_MAC, which allows 1023 * specifying which parameters to configure. 1024 */ 1025 encp->enc_enhanced_set_mac_supported = 1026 CAP_FLAG(flags, SET_MAC_ENHANCED) ? B_TRUE : B_FALSE; 1027 1028#undef CAP_FLAG 1029#undef CAP_FLAG2 1030 1031 return (0); 1032 1033fail2: 1034 EFSYS_PROBE(fail2); 1035fail1: 1036 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1037 1038 return (rc); 1039} 1040 1041 1042#define EF10_LEGACY_PF_PRIVILEGE_MASK \ 1043 (MC_CMD_PRIVILEGE_MASK_IN_GRP_ADMIN | \ 1044 MC_CMD_PRIVILEGE_MASK_IN_GRP_LINK | \ 1045 MC_CMD_PRIVILEGE_MASK_IN_GRP_ONLOAD | \ 1046 MC_CMD_PRIVILEGE_MASK_IN_GRP_PTP | \ 1047 MC_CMD_PRIVILEGE_MASK_IN_GRP_INSECURE_FILTERS | \ 1048 MC_CMD_PRIVILEGE_MASK_IN_GRP_MAC_SPOOFING | \ 1049 MC_CMD_PRIVILEGE_MASK_IN_GRP_UNICAST | \ 1050 MC_CMD_PRIVILEGE_MASK_IN_GRP_MULTICAST | \ 1051 MC_CMD_PRIVILEGE_MASK_IN_GRP_BROADCAST | \ 1052 MC_CMD_PRIVILEGE_MASK_IN_GRP_ALL_MULTICAST | \ 1053 MC_CMD_PRIVILEGE_MASK_IN_GRP_PROMISCUOUS) 1054 1055#define EF10_LEGACY_VF_PRIVILEGE_MASK 0 1056 1057 1058 __checkReturn efx_rc_t 1059ef10_get_privilege_mask( 1060 __in efx_nic_t *enp, 1061 __out uint32_t *maskp) 1062{ 1063 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1064 uint32_t mask; 1065 efx_rc_t rc; 1066 1067 if ((rc = efx_mcdi_privilege_mask(enp, encp->enc_pf, encp->enc_vf, 1068 &mask)) != 0) { 1069 if (rc != ENOTSUP) 1070 goto fail1; 1071 1072 /* Fallback for old firmware without privilege mask support */ 1073 if (EFX_PCI_FUNCTION_IS_PF(encp)) { 1074 /* Assume PF has admin privilege */ 1075 mask = EF10_LEGACY_PF_PRIVILEGE_MASK; 1076 } else { 1077 /* VF is always unprivileged by default */ 1078 mask = EF10_LEGACY_VF_PRIVILEGE_MASK; 1079 } 1080 } 1081 1082 *maskp = mask; 1083 1084 return (0); 1085 1086fail1: 1087 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1088 1089 return (rc); 1090} 1091 1092 1093/* 1094 * The external port mapping is a one-based numbering of the external 1095 * connectors on the board. It does not distinguish off-board separated 1096 * outputs such as multi-headed cables. 1097 * The number of ports that map to each external port connector 1098 * on the board is determined by the chip family and the port modes to 1099 * which the NIC can be configured. The mapping table lists modes with 1100 * port numbering requirements in increasing order. 1101 */ 1102static struct { 1103 efx_family_t family; 1104 uint32_t modes_mask; 1105 uint32_t stride; 1106} __ef10_external_port_mappings[] = { 1107 /* Supported modes requiring 1 output per port */ 1108 { 1109 EFX_FAMILY_HUNTINGTON, 1110 (1 << TLV_PORT_MODE_10G) | 1111 (1 << TLV_PORT_MODE_10G_10G) | 1112 (1 << TLV_PORT_MODE_10G_10G_10G_10G), 1113 1 1114 }, 1115 { 1116 EFX_FAMILY_MEDFORD, 1117 (1 << TLV_PORT_MODE_10G) | 1118 (1 << TLV_PORT_MODE_10G_10G) | 1119 (1 << TLV_PORT_MODE_10G_10G_10G_10G), 1120 1 1121 }, 1122 /* Supported modes requiring 2 outputs per port */ 1123 { 1124 EFX_FAMILY_HUNTINGTON, 1125 (1 << TLV_PORT_MODE_40G) | 1126 (1 << TLV_PORT_MODE_40G_40G) | 1127 (1 << TLV_PORT_MODE_40G_10G_10G) | 1128 (1 << TLV_PORT_MODE_10G_10G_40G), 1129 2 1130 }, 1131 { 1132 EFX_FAMILY_MEDFORD, 1133 (1 << TLV_PORT_MODE_40G) | 1134 (1 << TLV_PORT_MODE_40G_40G) | 1135 (1 << TLV_PORT_MODE_40G_10G_10G) | 1136 (1 << TLV_PORT_MODE_10G_10G_40G), 1137 2 1138 }, 1139 /* Supported modes requiring 4 outputs per port */ 1140 { 1141 EFX_FAMILY_MEDFORD, 1142 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q) | 1143 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q2), 1144 4 1145 }, 1146}; 1147 1148 __checkReturn efx_rc_t 1149ef10_external_port_mapping( 1150 __in efx_nic_t *enp, 1151 __in uint32_t port, 1152 __out uint8_t *external_portp) 1153{ 1154 efx_rc_t rc; 1155 int i; 1156 uint32_t port_modes; 1157 uint32_t matches; 1158 uint32_t stride = 1; /* default 1-1 mapping */ 1159 1160 if ((rc = efx_mcdi_get_port_modes(enp, &port_modes, NULL)) != 0) { 1161 /* No port mode information available - use default mapping */ 1162 goto out; 1163 } 1164 1165 /* 1166 * Infer the internal port -> external port mapping from 1167 * the possible port modes for this NIC. 1168 */ 1169 for (i = 0; i < EFX_ARRAY_SIZE(__ef10_external_port_mappings); ++i) { 1170 if (__ef10_external_port_mappings[i].family != 1171 enp->en_family) 1172 continue; 1173 matches = (__ef10_external_port_mappings[i].modes_mask & 1174 port_modes); 1175 if (matches != 0) { 1176 stride = __ef10_external_port_mappings[i].stride; 1177 port_modes &= ~matches; 1178 } 1179 } 1180 1181 if (port_modes != 0) { 1182 /* Some advertised modes are not supported */ 1183 rc = ENOTSUP; 1184 goto fail1; 1185 } 1186 1187out: 1188 /* 1189 * Scale as required by last matched mode and then convert to 1190 * one-based numbering 1191 */ 1192 *external_portp = (uint8_t)(port / stride) + 1; 1193 return (0); 1194 1195fail1: 1196 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1197 1198 return (rc); 1199} 1200 1201 1202 __checkReturn efx_rc_t 1203ef10_nic_probe( 1204 __in efx_nic_t *enp) 1205{ 1206 const efx_nic_ops_t *enop = enp->en_enop; 1207 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1208 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1209 efx_rc_t rc; 1210 1211 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1212 enp->en_family == EFX_FAMILY_MEDFORD); 1213 1214 /* Read and clear any assertion state */ 1215 if ((rc = efx_mcdi_read_assertion(enp)) != 0) 1216 goto fail1; 1217 1218 /* Exit the assertion handler */ 1219 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 1220 if (rc != EACCES) 1221 goto fail2; 1222 1223 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0) 1224 goto fail3; 1225 1226 if ((rc = enop->eno_board_cfg(enp)) != 0) 1227 if (rc != EACCES) 1228 goto fail4; 1229 1230 /* 1231 * Set default driver config limits (based on board config). 1232 * 1233 * FIXME: For now allocate a fixed number of VIs which is likely to be 1234 * sufficient and small enough to allow multiple functions on the same 1235 * port. 1236 */ 1237 edcp->edc_min_vi_count = edcp->edc_max_vi_count = 1238 MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit)); 1239 1240 /* The client driver must configure and enable PIO buffer support */ 1241 edcp->edc_max_piobuf_count = 0; 1242 edcp->edc_pio_alloc_size = 0; 1243 1244#if EFSYS_OPT_MAC_STATS 1245 /* Wipe the MAC statistics */ 1246 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0) 1247 goto fail5; 1248#endif 1249 1250#if EFSYS_OPT_LOOPBACK 1251 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0) 1252 goto fail6; 1253#endif 1254 1255#if EFSYS_OPT_MON_STATS 1256 if ((rc = mcdi_mon_cfg_build(enp)) != 0) { 1257 /* Unprivileged functions do not have access to sensors */ 1258 if (rc != EACCES) 1259 goto fail7; 1260 } 1261#endif 1262 1263 encp->enc_features = enp->en_features; 1264 1265 return (0); 1266 1267#if EFSYS_OPT_MON_STATS 1268fail7: 1269 EFSYS_PROBE(fail7); 1270#endif 1271#if EFSYS_OPT_LOOPBACK 1272fail6: 1273 EFSYS_PROBE(fail6); 1274#endif 1275#if EFSYS_OPT_MAC_STATS 1276fail5: 1277 EFSYS_PROBE(fail5); 1278#endif 1279fail4: 1280 EFSYS_PROBE(fail4); 1281fail3: 1282 EFSYS_PROBE(fail3); 1283fail2: 1284 EFSYS_PROBE(fail2); 1285fail1: 1286 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1287 1288 return (rc); 1289} 1290 1291 __checkReturn efx_rc_t 1292ef10_nic_set_drv_limits( 1293 __inout efx_nic_t *enp, 1294 __in efx_drv_limits_t *edlp) 1295{ 1296 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1297 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1298 uint32_t min_evq_count, max_evq_count; 1299 uint32_t min_rxq_count, max_rxq_count; 1300 uint32_t min_txq_count, max_txq_count; 1301 efx_rc_t rc; 1302 1303 if (edlp == NULL) { 1304 rc = EINVAL; 1305 goto fail1; 1306 } 1307 1308 /* Get minimum required and maximum usable VI limits */ 1309 min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit); 1310 min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit); 1311 min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit); 1312 1313 edcp->edc_min_vi_count = 1314 MAX(min_evq_count, MAX(min_rxq_count, min_txq_count)); 1315 1316 max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit); 1317 max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit); 1318 max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit); 1319 1320 edcp->edc_max_vi_count = 1321 MAX(max_evq_count, MAX(max_rxq_count, max_txq_count)); 1322 1323 /* 1324 * Check limits for sub-allocated piobuf blocks. 1325 * PIO is optional, so don't fail if the limits are incorrect. 1326 */ 1327 if ((encp->enc_piobuf_size == 0) || 1328 (encp->enc_piobuf_limit == 0) || 1329 (edlp->edl_min_pio_alloc_size == 0) || 1330 (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) { 1331 /* Disable PIO */ 1332 edcp->edc_max_piobuf_count = 0; 1333 edcp->edc_pio_alloc_size = 0; 1334 } else { 1335 uint32_t blk_size, blk_count, blks_per_piobuf; 1336 1337 blk_size = 1338 MAX(edlp->edl_min_pio_alloc_size, 1339 encp->enc_piobuf_min_alloc_size); 1340 1341 blks_per_piobuf = encp->enc_piobuf_size / blk_size; 1342 EFSYS_ASSERT3U(blks_per_piobuf, <=, 32); 1343 1344 blk_count = (encp->enc_piobuf_limit * blks_per_piobuf); 1345 1346 /* A zero max pio alloc count means unlimited */ 1347 if ((edlp->edl_max_pio_alloc_count > 0) && 1348 (edlp->edl_max_pio_alloc_count < blk_count)) { 1349 blk_count = edlp->edl_max_pio_alloc_count; 1350 } 1351 1352 edcp->edc_pio_alloc_size = blk_size; 1353 edcp->edc_max_piobuf_count = 1354 (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf; 1355 } 1356 1357 return (0); 1358 1359fail1: 1360 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1361 1362 return (rc); 1363} 1364 1365 1366 __checkReturn efx_rc_t 1367ef10_nic_reset( 1368 __in efx_nic_t *enp) 1369{ 1370 efx_mcdi_req_t req; 1371 uint8_t payload[MAX(MC_CMD_ENTITY_RESET_IN_LEN, 1372 MC_CMD_ENTITY_RESET_OUT_LEN)]; 1373 efx_rc_t rc; 1374 1375 /* ef10_nic_reset() is called to recover from BADASSERT failures. */ 1376 if ((rc = efx_mcdi_read_assertion(enp)) != 0) 1377 goto fail1; 1378 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 1379 goto fail2; 1380 1381 (void) memset(payload, 0, sizeof (payload)); 1382 req.emr_cmd = MC_CMD_ENTITY_RESET; 1383 req.emr_in_buf = payload; 1384 req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN; 1385 req.emr_out_buf = payload; 1386 req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN; 1387 1388 MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG, 1389 ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1); 1390 1391 efx_mcdi_execute(enp, &req); 1392 1393 if (req.emr_rc != 0) { 1394 rc = req.emr_rc; 1395 goto fail3; 1396 } 1397 1398 /* Clear RX/TX DMA queue errors */ 1399 enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR); 1400 1401 return (0); 1402 1403fail3: 1404 EFSYS_PROBE(fail3); 1405fail2: 1406 EFSYS_PROBE(fail2); 1407fail1: 1408 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1409 1410 return (rc); 1411} 1412 1413 __checkReturn efx_rc_t 1414ef10_nic_init( 1415 __in efx_nic_t *enp) 1416{ 1417 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1418 uint32_t min_vi_count, max_vi_count; 1419 uint32_t vi_count, vi_base, vi_shift; 1420 uint32_t i; 1421 uint32_t retry; 1422 uint32_t delay_us; 1423 efx_rc_t rc; 1424 1425 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1426 enp->en_family == EFX_FAMILY_MEDFORD); 1427 1428 /* Enable reporting of some events (e.g. link change) */ 1429 if ((rc = efx_mcdi_log_ctrl(enp)) != 0) 1430 goto fail1; 1431 1432 /* Allocate (optional) on-chip PIO buffers */ 1433 ef10_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count); 1434 1435 /* 1436 * For best performance, PIO writes should use a write-combined 1437 * (WC) memory mapping. Using a separate WC mapping for the PIO 1438 * aperture of each VI would be a burden to drivers (and not 1439 * possible if the host page size is >4Kbyte). 1440 * 1441 * To avoid this we use a single uncached (UC) mapping for VI 1442 * register access, and a single WC mapping for extra VIs used 1443 * for PIO writes. 1444 * 1445 * Each piobuf must be linked to a VI in the WC mapping, and to 1446 * each VI that is using a sub-allocated block from the piobuf. 1447 */ 1448 min_vi_count = edcp->edc_min_vi_count; 1449 max_vi_count = 1450 edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count; 1451 1452 /* Ensure that the previously attached driver's VIs are freed */ 1453 if ((rc = efx_mcdi_free_vis(enp)) != 0) 1454 goto fail2; 1455 1456 /* 1457 * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this 1458 * fails then retrying the request for fewer VI resources may succeed. 1459 */ 1460 vi_count = 0; 1461 if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count, 1462 &vi_base, &vi_count, &vi_shift)) != 0) 1463 goto fail3; 1464 1465 EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count); 1466 1467 if (vi_count < min_vi_count) { 1468 rc = ENOMEM; 1469 goto fail4; 1470 } 1471 1472 enp->en_arch.ef10.ena_vi_base = vi_base; 1473 enp->en_arch.ef10.ena_vi_count = vi_count; 1474 enp->en_arch.ef10.ena_vi_shift = vi_shift; 1475 1476 if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) { 1477 /* Not enough extra VIs to map piobufs */ 1478 ef10_nic_free_piobufs(enp); 1479 } 1480 1481 enp->en_arch.ef10.ena_pio_write_vi_base = 1482 vi_count - enp->en_arch.ef10.ena_piobuf_count; 1483 1484 /* Save UC memory mapping details */ 1485 enp->en_arch.ef10.ena_uc_mem_map_offset = 0; 1486 if (enp->en_arch.ef10.ena_piobuf_count > 0) { 1487 enp->en_arch.ef10.ena_uc_mem_map_size = 1488 (ER_DZ_TX_PIOBUF_STEP * 1489 enp->en_arch.ef10.ena_pio_write_vi_base); 1490 } else { 1491 enp->en_arch.ef10.ena_uc_mem_map_size = 1492 (ER_DZ_TX_PIOBUF_STEP * 1493 enp->en_arch.ef10.ena_vi_count); 1494 } 1495 1496 /* Save WC memory mapping details */ 1497 enp->en_arch.ef10.ena_wc_mem_map_offset = 1498 enp->en_arch.ef10.ena_uc_mem_map_offset + 1499 enp->en_arch.ef10.ena_uc_mem_map_size; 1500 1501 enp->en_arch.ef10.ena_wc_mem_map_size = 1502 (ER_DZ_TX_PIOBUF_STEP * 1503 enp->en_arch.ef10.ena_piobuf_count); 1504 1505 /* Link piobufs to extra VIs in WC mapping */ 1506 if (enp->en_arch.ef10.ena_piobuf_count > 0) { 1507 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 1508 rc = efx_mcdi_link_piobuf(enp, 1509 enp->en_arch.ef10.ena_pio_write_vi_base + i, 1510 enp->en_arch.ef10.ena_piobuf_handle[i]); 1511 if (rc != 0) 1512 break; 1513 } 1514 } 1515 1516 /* 1517 * Allocate a vAdaptor attached to our upstream vPort/pPort. 1518 * 1519 * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF 1520 * driver has yet to bring up the EVB port. See bug 56147. In this case, 1521 * retry the request several times after waiting a while. The wait time 1522 * between retries starts small (10ms) and exponentially increases. 1523 * Total wait time is a little over two seconds. Retry logic in the 1524 * client driver may mean this whole loop is repeated if it continues to 1525 * fail. 1526 */ 1527 retry = 0; 1528 delay_us = 10000; 1529 while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) { 1530 if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) || 1531 (rc != ENOENT)) { 1532 /* 1533 * Do not retry alloc for PF, or for other errors on 1534 * a VF. 1535 */ 1536 goto fail5; 1537 } 1538 1539 /* VF startup before PF is ready. Retry allocation. */ 1540 if (retry > 5) { 1541 /* Too many attempts */ 1542 rc = EINVAL; 1543 goto fail6; 1544 } 1545 EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry); 1546 EFSYS_SLEEP(delay_us); 1547 retry++; 1548 if (delay_us < 500000) 1549 delay_us <<= 2; 1550 } 1551 1552 enp->en_vport_id = EVB_PORT_ID_ASSIGNED; 1553 enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2; 1554 1555 return (0); 1556 1557fail6: 1558 EFSYS_PROBE(fail6); 1559fail5: 1560 EFSYS_PROBE(fail5); 1561fail4: 1562 EFSYS_PROBE(fail4); 1563fail3: 1564 EFSYS_PROBE(fail3); 1565fail2: 1566 EFSYS_PROBE(fail2); 1567 1568 ef10_nic_free_piobufs(enp); 1569 1570fail1: 1571 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1572 1573 return (rc); 1574} 1575 1576 __checkReturn efx_rc_t 1577ef10_nic_get_vi_pool( 1578 __in efx_nic_t *enp, 1579 __out uint32_t *vi_countp) 1580{ 1581 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1582 enp->en_family == EFX_FAMILY_MEDFORD); 1583 1584 /* 1585 * Report VIs that the client driver can use. 1586 * Do not include VIs used for PIO buffer writes. 1587 */ 1588 *vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base; 1589 1590 return (0); 1591} 1592 1593 __checkReturn efx_rc_t 1594ef10_nic_get_bar_region( 1595 __in efx_nic_t *enp, 1596 __in efx_nic_region_t region, 1597 __out uint32_t *offsetp, 1598 __out size_t *sizep) 1599{ 1600 efx_rc_t rc; 1601 1602 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1603 enp->en_family == EFX_FAMILY_MEDFORD); 1604 1605 /* 1606 * TODO: Specify host memory mapping alignment and granularity 1607 * in efx_drv_limits_t so that they can be taken into account 1608 * when allocating extra VIs for PIO writes. 1609 */ 1610 switch (region) { 1611 case EFX_REGION_VI: 1612 /* UC mapped memory BAR region for VI registers */ 1613 *offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset; 1614 *sizep = enp->en_arch.ef10.ena_uc_mem_map_size; 1615 break; 1616 1617 case EFX_REGION_PIO_WRITE_VI: 1618 /* WC mapped memory BAR region for piobuf writes */ 1619 *offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset; 1620 *sizep = enp->en_arch.ef10.ena_wc_mem_map_size; 1621 break; 1622 1623 default: 1624 rc = EINVAL; 1625 goto fail1; 1626 } 1627 1628 return (0); 1629 1630fail1: 1631 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1632 1633 return (rc); 1634} 1635 1636 void 1637ef10_nic_fini( 1638 __in efx_nic_t *enp) 1639{ 1640 uint32_t i; 1641 efx_rc_t rc; 1642 1643 (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id); 1644 enp->en_vport_id = 0; 1645 1646 /* Unlink piobufs from extra VIs in WC mapping */ 1647 if (enp->en_arch.ef10.ena_piobuf_count > 0) { 1648 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 1649 rc = efx_mcdi_unlink_piobuf(enp, 1650 enp->en_arch.ef10.ena_pio_write_vi_base + i); 1651 if (rc != 0) 1652 break; 1653 } 1654 } 1655 1656 ef10_nic_free_piobufs(enp); 1657 1658 (void) efx_mcdi_free_vis(enp); 1659 enp->en_arch.ef10.ena_vi_count = 0; 1660} 1661 1662 void 1663ef10_nic_unprobe( 1664 __in efx_nic_t *enp) 1665{ 1666#if EFSYS_OPT_MON_STATS 1667 mcdi_mon_cfg_free(enp); 1668#endif /* EFSYS_OPT_MON_STATS */ 1669 (void) efx_mcdi_drv_attach(enp, B_FALSE); 1670} 1671 1672#if EFSYS_OPT_DIAG 1673 1674 __checkReturn efx_rc_t 1675ef10_nic_register_test( 1676 __in efx_nic_t *enp) 1677{ 1678 efx_rc_t rc; 1679 1680 /* FIXME */ 1681 _NOTE(ARGUNUSED(enp)) 1682 _NOTE(CONSTANTCONDITION) 1683 if (B_FALSE) { 1684 rc = ENOTSUP; 1685 goto fail1; 1686 } 1687 /* FIXME */ 1688 1689 return (0); 1690 1691fail1: 1692 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1693 1694 return (rc); 1695} 1696 1697#endif /* EFSYS_OPT_DIAG */ 1698 1699 1700#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 1701