ef10_nic.c revision 293805
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/hunt_nic.c 293805 2016-01-13 06:34:51Z arybchik $"); 33 34#include "efsys.h" 35#include "efx.h" 36#include "efx_impl.h" 37#include "mcdi_mon.h" 38 39#if EFSYS_OPT_HUNTINGTON 40 41#include "ef10_tlv_layout.h" 42 43static __checkReturn efx_rc_t 44efx_mcdi_get_port_assignment( 45 __in efx_nic_t *enp, 46 __out uint32_t *portp) 47{ 48 efx_mcdi_req_t req; 49 uint8_t payload[MAX(MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN, 50 MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN)]; 51 efx_rc_t rc; 52 53 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 54 enp->en_family == EFX_FAMILY_MEDFORD); 55 56 (void) memset(payload, 0, sizeof (payload)); 57 req.emr_cmd = MC_CMD_GET_PORT_ASSIGNMENT; 58 req.emr_in_buf = payload; 59 req.emr_in_length = MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN; 60 req.emr_out_buf = payload; 61 req.emr_out_length = MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN; 62 63 efx_mcdi_execute(enp, &req); 64 65 if (req.emr_rc != 0) { 66 rc = req.emr_rc; 67 goto fail1; 68 } 69 70 if (req.emr_out_length_used < MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN) { 71 rc = EMSGSIZE; 72 goto fail2; 73 } 74 75 *portp = MCDI_OUT_DWORD(req, GET_PORT_ASSIGNMENT_OUT_PORT); 76 77 return (0); 78 79fail2: 80 EFSYS_PROBE(fail2); 81fail1: 82 EFSYS_PROBE1(fail1, efx_rc_t, rc); 83 84 return (rc); 85} 86 87static __checkReturn efx_rc_t 88efx_mcdi_get_port_modes( 89 __in efx_nic_t *enp, 90 __out uint32_t *modesp) 91{ 92 efx_mcdi_req_t req; 93 uint8_t payload[MAX(MC_CMD_GET_PORT_MODES_IN_LEN, 94 MC_CMD_GET_PORT_MODES_OUT_LEN)]; 95 efx_rc_t rc; 96 97 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 98 enp->en_family == EFX_FAMILY_MEDFORD); 99 100 (void) memset(payload, 0, sizeof (payload)); 101 req.emr_cmd = MC_CMD_GET_PORT_MODES; 102 req.emr_in_buf = payload; 103 req.emr_in_length = MC_CMD_GET_PORT_MODES_IN_LEN; 104 req.emr_out_buf = payload; 105 req.emr_out_length = MC_CMD_GET_PORT_MODES_OUT_LEN; 106 107 efx_mcdi_execute(enp, &req); 108 109 if (req.emr_rc != 0) { 110 rc = req.emr_rc; 111 goto fail1; 112 } 113 114 /* Accept pre-Medford size (8 bytes - no CurrentMode field) */ 115 if (req.emr_out_length_used < 116 MC_CMD_GET_PORT_MODES_OUT_CURRENT_MODE_OFST) { 117 rc = EMSGSIZE; 118 goto fail2; 119 } 120 121 *modesp = MCDI_OUT_DWORD(req, GET_PORT_MODES_OUT_MODES); 122 123 return (0); 124 125fail2: 126 EFSYS_PROBE(fail2); 127fail1: 128 EFSYS_PROBE1(fail1, efx_rc_t, rc); 129 130 return (rc); 131} 132 133 134static __checkReturn efx_rc_t 135efx_mcdi_vadaptor_alloc( 136 __in efx_nic_t *enp, 137 __in uint32_t port_id) 138{ 139 efx_mcdi_req_t req; 140 uint8_t payload[MAX(MC_CMD_VADAPTOR_ALLOC_IN_LEN, 141 MC_CMD_VADAPTOR_ALLOC_OUT_LEN)]; 142 efx_rc_t rc; 143 144 EFSYS_ASSERT3U(enp->en_vport_id, ==, EVB_PORT_ID_NULL); 145 146 (void) memset(payload, 0, sizeof (payload)); 147 req.emr_cmd = MC_CMD_VADAPTOR_ALLOC; 148 req.emr_in_buf = payload; 149 req.emr_in_length = MC_CMD_VADAPTOR_ALLOC_IN_LEN; 150 req.emr_out_buf = payload; 151 req.emr_out_length = MC_CMD_VADAPTOR_ALLOC_OUT_LEN; 152 153 MCDI_IN_SET_DWORD(req, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id); 154 MCDI_IN_POPULATE_DWORD_1(req, VADAPTOR_ALLOC_IN_FLAGS, 155 VADAPTOR_ALLOC_IN_FLAG_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED, 156 enp->en_nic_cfg.enc_allow_set_mac_with_installed_filters ? 1 : 0); 157 158 efx_mcdi_execute(enp, &req); 159 160 if (req.emr_rc != 0) { 161 rc = req.emr_rc; 162 goto fail1; 163 } 164 165 return (0); 166 167fail1: 168 EFSYS_PROBE1(fail1, efx_rc_t, rc); 169 170 return (rc); 171} 172 173static __checkReturn efx_rc_t 174efx_mcdi_vadaptor_free( 175 __in efx_nic_t *enp, 176 __in uint32_t port_id) 177{ 178 efx_mcdi_req_t req; 179 uint8_t payload[MAX(MC_CMD_VADAPTOR_FREE_IN_LEN, 180 MC_CMD_VADAPTOR_FREE_OUT_LEN)]; 181 efx_rc_t rc; 182 183 (void) memset(payload, 0, sizeof (payload)); 184 req.emr_cmd = MC_CMD_VADAPTOR_FREE; 185 req.emr_in_buf = payload; 186 req.emr_in_length = MC_CMD_VADAPTOR_FREE_IN_LEN; 187 req.emr_out_buf = payload; 188 req.emr_out_length = MC_CMD_VADAPTOR_FREE_OUT_LEN; 189 190 MCDI_IN_SET_DWORD(req, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id); 191 192 efx_mcdi_execute(enp, &req); 193 194 if (req.emr_rc != 0) { 195 rc = req.emr_rc; 196 goto fail1; 197 } 198 199 return (0); 200 201fail1: 202 EFSYS_PROBE1(fail1, efx_rc_t, rc); 203 204 return (rc); 205} 206 207static __checkReturn efx_rc_t 208efx_mcdi_get_mac_address_pf( 209 __in efx_nic_t *enp, 210 __out_ecount_opt(6) uint8_t mac_addrp[6]) 211{ 212 efx_mcdi_req_t req; 213 uint8_t payload[MAX(MC_CMD_GET_MAC_ADDRESSES_IN_LEN, 214 MC_CMD_GET_MAC_ADDRESSES_OUT_LEN)]; 215 efx_rc_t rc; 216 217 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 218 enp->en_family == EFX_FAMILY_MEDFORD); 219 220 (void) memset(payload, 0, sizeof (payload)); 221 req.emr_cmd = MC_CMD_GET_MAC_ADDRESSES; 222 req.emr_in_buf = payload; 223 req.emr_in_length = MC_CMD_GET_MAC_ADDRESSES_IN_LEN; 224 req.emr_out_buf = payload; 225 req.emr_out_length = MC_CMD_GET_MAC_ADDRESSES_OUT_LEN; 226 227 efx_mcdi_execute(enp, &req); 228 229 if (req.emr_rc != 0) { 230 rc = req.emr_rc; 231 goto fail1; 232 } 233 234 if (req.emr_out_length_used < MC_CMD_GET_MAC_ADDRESSES_OUT_LEN) { 235 rc = EMSGSIZE; 236 goto fail2; 237 } 238 239 if (MCDI_OUT_DWORD(req, GET_MAC_ADDRESSES_OUT_MAC_COUNT) < 1) { 240 rc = ENOENT; 241 goto fail3; 242 } 243 244 if (mac_addrp != NULL) { 245 uint8_t *addrp; 246 247 addrp = MCDI_OUT2(req, uint8_t, 248 GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE); 249 250 EFX_MAC_ADDR_COPY(mac_addrp, addrp); 251 } 252 253 return (0); 254 255fail3: 256 EFSYS_PROBE(fail3); 257fail2: 258 EFSYS_PROBE(fail2); 259fail1: 260 EFSYS_PROBE1(fail1, efx_rc_t, rc); 261 262 return (rc); 263} 264 265static __checkReturn efx_rc_t 266efx_mcdi_get_mac_address_vf( 267 __in efx_nic_t *enp, 268 __out_ecount_opt(6) uint8_t mac_addrp[6]) 269{ 270 efx_mcdi_req_t req; 271 uint8_t payload[MAX(MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN, 272 MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX)]; 273 efx_rc_t rc; 274 275 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 276 enp->en_family == EFX_FAMILY_MEDFORD); 277 278 (void) memset(payload, 0, sizeof (payload)); 279 req.emr_cmd = MC_CMD_VPORT_GET_MAC_ADDRESSES; 280 req.emr_in_buf = payload; 281 req.emr_in_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN; 282 req.emr_out_buf = payload; 283 req.emr_out_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX; 284 285 MCDI_IN_SET_DWORD(req, VPORT_GET_MAC_ADDRESSES_IN_VPORT_ID, 286 EVB_PORT_ID_ASSIGNED); 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 < 296 MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMIN) { 297 rc = EMSGSIZE; 298 goto fail2; 299 } 300 301 if (MCDI_OUT_DWORD(req, 302 VPORT_GET_MAC_ADDRESSES_OUT_MACADDR_COUNT) < 1) { 303 rc = ENOENT; 304 goto fail3; 305 } 306 307 if (mac_addrp != NULL) { 308 uint8_t *addrp; 309 310 addrp = MCDI_OUT2(req, uint8_t, 311 VPORT_GET_MAC_ADDRESSES_OUT_MACADDR); 312 313 EFX_MAC_ADDR_COPY(mac_addrp, addrp); 314 } 315 316 return (0); 317 318fail3: 319 EFSYS_PROBE(fail3); 320fail2: 321 EFSYS_PROBE(fail2); 322fail1: 323 EFSYS_PROBE1(fail1, efx_rc_t, rc); 324 325 return (rc); 326} 327 328static __checkReturn efx_rc_t 329efx_mcdi_get_clock( 330 __in efx_nic_t *enp, 331 __out uint32_t *sys_freqp) 332{ 333 efx_mcdi_req_t req; 334 uint8_t payload[MAX(MC_CMD_GET_CLOCK_IN_LEN, 335 MC_CMD_GET_CLOCK_OUT_LEN)]; 336 efx_rc_t rc; 337 338 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 339 enp->en_family == EFX_FAMILY_MEDFORD); 340 341 (void) memset(payload, 0, sizeof (payload)); 342 req.emr_cmd = MC_CMD_GET_CLOCK; 343 req.emr_in_buf = payload; 344 req.emr_in_length = MC_CMD_GET_CLOCK_IN_LEN; 345 req.emr_out_buf = payload; 346 req.emr_out_length = MC_CMD_GET_CLOCK_OUT_LEN; 347 348 efx_mcdi_execute(enp, &req); 349 350 if (req.emr_rc != 0) { 351 rc = req.emr_rc; 352 goto fail1; 353 } 354 355 if (req.emr_out_length_used < MC_CMD_GET_CLOCK_OUT_LEN) { 356 rc = EMSGSIZE; 357 goto fail2; 358 } 359 360 *sys_freqp = MCDI_OUT_DWORD(req, GET_CLOCK_OUT_SYS_FREQ); 361 if (*sys_freqp == 0) { 362 rc = EINVAL; 363 goto fail3; 364 } 365 366 return (0); 367 368fail3: 369 EFSYS_PROBE(fail3); 370fail2: 371 EFSYS_PROBE(fail2); 372fail1: 373 EFSYS_PROBE1(fail1, efx_rc_t, rc); 374 375 return (rc); 376} 377 378static __checkReturn efx_rc_t 379efx_mcdi_get_vector_cfg( 380 __in efx_nic_t *enp, 381 __out_opt uint32_t *vec_basep, 382 __out_opt uint32_t *pf_nvecp, 383 __out_opt uint32_t *vf_nvecp) 384{ 385 efx_mcdi_req_t req; 386 uint8_t payload[MAX(MC_CMD_GET_VECTOR_CFG_IN_LEN, 387 MC_CMD_GET_VECTOR_CFG_OUT_LEN)]; 388 efx_rc_t rc; 389 390 (void) memset(payload, 0, sizeof (payload)); 391 req.emr_cmd = MC_CMD_GET_VECTOR_CFG; 392 req.emr_in_buf = payload; 393 req.emr_in_length = MC_CMD_GET_VECTOR_CFG_IN_LEN; 394 req.emr_out_buf = payload; 395 req.emr_out_length = MC_CMD_GET_VECTOR_CFG_OUT_LEN; 396 397 efx_mcdi_execute(enp, &req); 398 399 if (req.emr_rc != 0) { 400 rc = req.emr_rc; 401 goto fail1; 402 } 403 404 if (req.emr_out_length_used < MC_CMD_GET_VECTOR_CFG_OUT_LEN) { 405 rc = EMSGSIZE; 406 goto fail2; 407 } 408 409 if (vec_basep != NULL) 410 *vec_basep = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VEC_BASE); 411 if (pf_nvecp != NULL) 412 *pf_nvecp = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VECS_PER_PF); 413 if (vf_nvecp != NULL) 414 *vf_nvecp = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VECS_PER_VF); 415 416 return (0); 417 418fail2: 419 EFSYS_PROBE(fail2); 420fail1: 421 EFSYS_PROBE1(fail1, efx_rc_t, rc); 422 423 return (rc); 424} 425 426static __checkReturn efx_rc_t 427efx_mcdi_get_capabilities( 428 __in efx_nic_t *enp, 429 __out efx_dword_t *flagsp) 430{ 431 efx_mcdi_req_t req; 432 uint8_t payload[MAX(MC_CMD_GET_CAPABILITIES_IN_LEN, 433 MC_CMD_GET_CAPABILITIES_OUT_LEN)]; 434 efx_rc_t rc; 435 436 (void) memset(payload, 0, sizeof (payload)); 437 req.emr_cmd = MC_CMD_GET_CAPABILITIES; 438 req.emr_in_buf = payload; 439 req.emr_in_length = MC_CMD_GET_CAPABILITIES_IN_LEN; 440 req.emr_out_buf = payload; 441 req.emr_out_length = MC_CMD_GET_CAPABILITIES_OUT_LEN; 442 443 efx_mcdi_execute(enp, &req); 444 445 if (req.emr_rc != 0) { 446 rc = req.emr_rc; 447 goto fail1; 448 } 449 450 if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_OUT_LEN) { 451 rc = EMSGSIZE; 452 goto fail2; 453 } 454 455 *flagsp = *MCDI_OUT2(req, efx_dword_t, GET_CAPABILITIES_OUT_FLAGS1); 456 457 return (0); 458 459fail2: 460 EFSYS_PROBE(fail2); 461fail1: 462 EFSYS_PROBE1(fail1, efx_rc_t, rc); 463 464 return (rc); 465} 466 467 468static __checkReturn efx_rc_t 469efx_mcdi_alloc_vis( 470 __in efx_nic_t *enp, 471 __in uint32_t min_vi_count, 472 __in uint32_t max_vi_count, 473 __out_opt uint32_t *vi_basep, 474 __out uint32_t *vi_countp) 475 476{ 477 efx_mcdi_req_t req; 478 uint8_t payload[MAX(MC_CMD_ALLOC_VIS_IN_LEN, 479 MC_CMD_ALLOC_VIS_OUT_LEN)]; 480 efx_rc_t rc; 481 482 if (vi_countp == NULL) { 483 rc = EINVAL; 484 goto fail1; 485 } 486 487 (void) memset(payload, 0, sizeof (payload)); 488 req.emr_cmd = MC_CMD_ALLOC_VIS; 489 req.emr_in_buf = payload; 490 req.emr_in_length = MC_CMD_ALLOC_VIS_IN_LEN; 491 req.emr_out_buf = payload; 492 req.emr_out_length = MC_CMD_ALLOC_VIS_OUT_LEN; 493 494 MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MIN_VI_COUNT, min_vi_count); 495 MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MAX_VI_COUNT, max_vi_count); 496 497 efx_mcdi_execute(enp, &req); 498 499 if (req.emr_rc != 0) { 500 rc = req.emr_rc; 501 goto fail2; 502 } 503 504 if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_OUT_LEN) { 505 rc = EMSGSIZE; 506 goto fail3; 507 } 508 509 if (vi_basep != NULL) 510 *vi_basep = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_BASE); 511 512 if (vi_countp != NULL) 513 *vi_countp = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_COUNT); 514 515 return (0); 516 517fail3: 518 EFSYS_PROBE(fail3); 519fail2: 520 EFSYS_PROBE(fail2); 521fail1: 522 EFSYS_PROBE1(fail1, efx_rc_t, rc); 523 524 return (rc); 525} 526 527 528static __checkReturn efx_rc_t 529efx_mcdi_free_vis( 530 __in efx_nic_t *enp) 531{ 532 efx_mcdi_req_t req; 533 efx_rc_t rc; 534 535 EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_IN_LEN == 0); 536 EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_OUT_LEN == 0); 537 538 req.emr_cmd = MC_CMD_FREE_VIS; 539 req.emr_in_buf = NULL; 540 req.emr_in_length = 0; 541 req.emr_out_buf = NULL; 542 req.emr_out_length = 0; 543 544 efx_mcdi_execute_quiet(enp, &req); 545 546 /* Ignore ELREADY (no allocated VIs, so nothing to free) */ 547 if ((req.emr_rc != 0) && (req.emr_rc != EALREADY)) { 548 rc = req.emr_rc; 549 goto fail1; 550 } 551 552 return (0); 553 554fail1: 555 EFSYS_PROBE1(fail1, efx_rc_t, rc); 556 557 return (rc); 558} 559 560 561static __checkReturn efx_rc_t 562efx_mcdi_alloc_piobuf( 563 __in efx_nic_t *enp, 564 __out efx_piobuf_handle_t *handlep) 565{ 566 efx_mcdi_req_t req; 567 uint8_t payload[MAX(MC_CMD_ALLOC_PIOBUF_IN_LEN, 568 MC_CMD_ALLOC_PIOBUF_OUT_LEN)]; 569 efx_rc_t rc; 570 571 if (handlep == NULL) { 572 rc = EINVAL; 573 goto fail1; 574 } 575 576 (void) memset(payload, 0, sizeof (payload)); 577 req.emr_cmd = MC_CMD_ALLOC_PIOBUF; 578 req.emr_in_buf = payload; 579 req.emr_in_length = MC_CMD_ALLOC_PIOBUF_IN_LEN; 580 req.emr_out_buf = payload; 581 req.emr_out_length = MC_CMD_ALLOC_PIOBUF_OUT_LEN; 582 583 efx_mcdi_execute_quiet(enp, &req); 584 585 if (req.emr_rc != 0) { 586 rc = req.emr_rc; 587 goto fail2; 588 } 589 590 if (req.emr_out_length_used < MC_CMD_ALLOC_PIOBUF_OUT_LEN) { 591 rc = EMSGSIZE; 592 goto fail3; 593 } 594 595 *handlep = MCDI_OUT_DWORD(req, ALLOC_PIOBUF_OUT_PIOBUF_HANDLE); 596 597 return (0); 598 599fail3: 600 EFSYS_PROBE(fail3); 601fail2: 602 EFSYS_PROBE(fail2); 603fail1: 604 EFSYS_PROBE1(fail1, efx_rc_t, rc); 605 606 return (rc); 607} 608 609static __checkReturn efx_rc_t 610efx_mcdi_free_piobuf( 611 __in efx_nic_t *enp, 612 __in efx_piobuf_handle_t handle) 613{ 614 efx_mcdi_req_t req; 615 uint8_t payload[MAX(MC_CMD_FREE_PIOBUF_IN_LEN, 616 MC_CMD_FREE_PIOBUF_OUT_LEN)]; 617 efx_rc_t rc; 618 619 (void) memset(payload, 0, sizeof (payload)); 620 req.emr_cmd = MC_CMD_FREE_PIOBUF; 621 req.emr_in_buf = payload; 622 req.emr_in_length = MC_CMD_FREE_PIOBUF_IN_LEN; 623 req.emr_out_buf = payload; 624 req.emr_out_length = MC_CMD_FREE_PIOBUF_OUT_LEN; 625 626 MCDI_IN_SET_DWORD(req, FREE_PIOBUF_IN_PIOBUF_HANDLE, handle); 627 628 efx_mcdi_execute_quiet(enp, &req); 629 630 if (req.emr_rc != 0) { 631 rc = req.emr_rc; 632 goto fail1; 633 } 634 635 return (0); 636 637fail1: 638 EFSYS_PROBE1(fail1, efx_rc_t, rc); 639 640 return (rc); 641} 642 643static __checkReturn efx_rc_t 644efx_mcdi_link_piobuf( 645 __in efx_nic_t *enp, 646 __in uint32_t vi_index, 647 __in efx_piobuf_handle_t handle) 648{ 649 efx_mcdi_req_t req; 650 uint8_t payload[MAX(MC_CMD_LINK_PIOBUF_IN_LEN, 651 MC_CMD_LINK_PIOBUF_OUT_LEN)]; 652 efx_rc_t rc; 653 654 (void) memset(payload, 0, sizeof (payload)); 655 req.emr_cmd = MC_CMD_LINK_PIOBUF; 656 req.emr_in_buf = payload; 657 req.emr_in_length = MC_CMD_LINK_PIOBUF_IN_LEN; 658 req.emr_out_buf = payload; 659 req.emr_out_length = MC_CMD_LINK_PIOBUF_OUT_LEN; 660 661 MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_PIOBUF_HANDLE, handle); 662 MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_TXQ_INSTANCE, vi_index); 663 664 efx_mcdi_execute(enp, &req); 665 666 if (req.emr_rc != 0) { 667 rc = req.emr_rc; 668 goto fail1; 669 } 670 671 return (0); 672 673fail1: 674 EFSYS_PROBE1(fail1, efx_rc_t, rc); 675 676 return (rc); 677} 678 679static __checkReturn efx_rc_t 680efx_mcdi_unlink_piobuf( 681 __in efx_nic_t *enp, 682 __in uint32_t vi_index) 683{ 684 efx_mcdi_req_t req; 685 uint8_t payload[MAX(MC_CMD_UNLINK_PIOBUF_IN_LEN, 686 MC_CMD_UNLINK_PIOBUF_OUT_LEN)]; 687 efx_rc_t rc; 688 689 (void) memset(payload, 0, sizeof (payload)); 690 req.emr_cmd = MC_CMD_UNLINK_PIOBUF; 691 req.emr_in_buf = payload; 692 req.emr_in_length = MC_CMD_UNLINK_PIOBUF_IN_LEN; 693 req.emr_out_buf = payload; 694 req.emr_out_length = MC_CMD_UNLINK_PIOBUF_OUT_LEN; 695 696 MCDI_IN_SET_DWORD(req, UNLINK_PIOBUF_IN_TXQ_INSTANCE, vi_index); 697 698 efx_mcdi_execute(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 void 714ef10_nic_alloc_piobufs( 715 __in efx_nic_t *enp, 716 __in uint32_t max_piobuf_count) 717{ 718 efx_piobuf_handle_t *handlep; 719 unsigned int i; 720 efx_rc_t rc; 721 722 EFSYS_ASSERT3U(max_piobuf_count, <=, 723 EFX_ARRAY_SIZE(enp->en_arch.ef10.ena_piobuf_handle)); 724 725 enp->en_arch.ef10.ena_piobuf_count = 0; 726 727 for (i = 0; i < max_piobuf_count; i++) { 728 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i]; 729 730 if ((rc = efx_mcdi_alloc_piobuf(enp, handlep)) != 0) 731 goto fail1; 732 733 enp->en_arch.ef10.ena_pio_alloc_map[i] = 0; 734 enp->en_arch.ef10.ena_piobuf_count++; 735 } 736 737 return; 738 739fail1: 740 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 741 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i]; 742 743 efx_mcdi_free_piobuf(enp, *handlep); 744 *handlep = EFX_PIOBUF_HANDLE_INVALID; 745 } 746 enp->en_arch.ef10.ena_piobuf_count = 0; 747} 748 749 750static void 751ef10_nic_free_piobufs( 752 __in efx_nic_t *enp) 753{ 754 efx_piobuf_handle_t *handlep; 755 unsigned int i; 756 757 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 758 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i]; 759 760 efx_mcdi_free_piobuf(enp, *handlep); 761 *handlep = EFX_PIOBUF_HANDLE_INVALID; 762 } 763 enp->en_arch.ef10.ena_piobuf_count = 0; 764} 765 766/* Sub-allocate a block from a piobuf */ 767 __checkReturn efx_rc_t 768ef10_nic_pio_alloc( 769 __inout efx_nic_t *enp, 770 __out uint32_t *bufnump, 771 __out efx_piobuf_handle_t *handlep, 772 __out uint32_t *blknump, 773 __out uint32_t *offsetp, 774 __out size_t *sizep) 775{ 776 efx_nic_cfg_t *encp = &enp->en_nic_cfg; 777 efx_drv_cfg_t *edcp = &enp->en_drv_cfg; 778 uint32_t blk_per_buf; 779 uint32_t buf, blk; 780 efx_rc_t rc; 781 782 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 783 enp->en_family == EFX_FAMILY_MEDFORD); 784 EFSYS_ASSERT(bufnump); 785 EFSYS_ASSERT(handlep); 786 EFSYS_ASSERT(blknump); 787 EFSYS_ASSERT(offsetp); 788 EFSYS_ASSERT(sizep); 789 790 if ((edcp->edc_pio_alloc_size == 0) || 791 (enp->en_arch.ef10.ena_piobuf_count == 0)) { 792 rc = ENOMEM; 793 goto fail1; 794 } 795 blk_per_buf = encp->enc_piobuf_size / edcp->edc_pio_alloc_size; 796 797 for (buf = 0; buf < enp->en_arch.ef10.ena_piobuf_count; buf++) { 798 uint32_t *map = &enp->en_arch.ef10.ena_pio_alloc_map[buf]; 799 800 if (~(*map) == 0) 801 continue; 802 803 EFSYS_ASSERT3U(blk_per_buf, <=, (8 * sizeof (*map))); 804 for (blk = 0; blk < blk_per_buf; blk++) { 805 if ((*map & (1u << blk)) == 0) { 806 *map |= (1u << blk); 807 goto done; 808 } 809 } 810 } 811 rc = ENOMEM; 812 goto fail2; 813 814done: 815 *handlep = enp->en_arch.ef10.ena_piobuf_handle[buf]; 816 *bufnump = buf; 817 *blknump = blk; 818 *sizep = edcp->edc_pio_alloc_size; 819 *offsetp = blk * (*sizep); 820 821 return (0); 822 823fail2: 824 EFSYS_PROBE(fail2); 825fail1: 826 EFSYS_PROBE1(fail1, efx_rc_t, rc); 827 828 return (rc); 829} 830 831/* Free a piobuf sub-allocated block */ 832 __checkReturn efx_rc_t 833ef10_nic_pio_free( 834 __inout efx_nic_t *enp, 835 __in uint32_t bufnum, 836 __in uint32_t blknum) 837{ 838 uint32_t *map; 839 efx_rc_t rc; 840 841 if ((bufnum >= enp->en_arch.ef10.ena_piobuf_count) || 842 (blknum >= (8 * sizeof (*map)))) { 843 rc = EINVAL; 844 goto fail1; 845 } 846 847 map = &enp->en_arch.ef10.ena_pio_alloc_map[bufnum]; 848 if ((*map & (1u << blknum)) == 0) { 849 rc = ENOENT; 850 goto fail2; 851 } 852 *map &= ~(1u << blknum); 853 854 return (0); 855 856fail2: 857 EFSYS_PROBE(fail2); 858fail1: 859 EFSYS_PROBE1(fail1, efx_rc_t, rc); 860 861 return (rc); 862} 863 864 __checkReturn efx_rc_t 865ef10_nic_pio_link( 866 __inout efx_nic_t *enp, 867 __in uint32_t vi_index, 868 __in efx_piobuf_handle_t handle) 869{ 870 return (efx_mcdi_link_piobuf(enp, vi_index, handle)); 871} 872 873 __checkReturn efx_rc_t 874ef10_nic_pio_unlink( 875 __inout efx_nic_t *enp, 876 __in uint32_t vi_index) 877{ 878 return (efx_mcdi_unlink_piobuf(enp, vi_index)); 879} 880 881static __checkReturn efx_rc_t 882ef10_get_datapath_caps( 883 __in efx_nic_t *enp) 884{ 885 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 886 efx_dword_t datapath_capabilities; 887 efx_rc_t rc; 888 889 if ((rc = efx_mcdi_get_capabilities(enp, &datapath_capabilities)) != 0) 890 goto fail1; 891 892 /* 893 * Huntington RXDP firmware inserts a 0 or 14 byte prefix. 894 * We only support the 14 byte prefix here. 895 */ 896 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 897 GET_CAPABILITIES_OUT_RX_PREFIX_LEN_14) != 1) { 898 rc = ENOTSUP; 899 goto fail2; 900 } 901 encp->enc_rx_prefix_size = 14; 902 903 /* Check if the firmware supports TSO */ 904 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 905 GET_CAPABILITIES_OUT_TX_TSO) == 1) 906 encp->enc_fw_assisted_tso_enabled = B_TRUE; 907 else 908 encp->enc_fw_assisted_tso_enabled = B_FALSE; 909 910 /* Check if the firmware has vadapter/vport/vswitch support */ 911 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 912 GET_CAPABILITIES_OUT_EVB) == 1) 913 encp->enc_datapath_cap_evb = B_TRUE; 914 else 915 encp->enc_datapath_cap_evb = B_FALSE; 916 917 /* Check if the firmware supports VLAN insertion */ 918 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 919 GET_CAPABILITIES_OUT_TX_VLAN_INSERTION) == 1) 920 encp->enc_hw_tx_insert_vlan_enabled = B_TRUE; 921 else 922 encp->enc_hw_tx_insert_vlan_enabled = B_FALSE; 923 924 /* Check if the firmware supports RX event batching */ 925 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 926 GET_CAPABILITIES_OUT_RX_BATCHING) == 1) { 927 encp->enc_rx_batching_enabled = B_TRUE; 928 encp->enc_rx_batch_max = 16; 929 } else { 930 encp->enc_rx_batching_enabled = B_FALSE; 931 } 932 933 /* Check if the firmware supports disabling scatter on RXQs */ 934 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 935 GET_CAPABILITIES_OUT_RX_DISABLE_SCATTER) == 1) { 936 encp->enc_rx_disable_scatter_supported = B_TRUE; 937 } else { 938 encp->enc_rx_disable_scatter_supported = B_FALSE; 939 } 940 941 /* Check if the firmware supports set mac with running filters */ 942 if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities, 943 GET_CAPABILITIES_OUT_VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED) 944 == 1) { 945 encp->enc_allow_set_mac_with_installed_filters = B_TRUE; 946 } else { 947 encp->enc_allow_set_mac_with_installed_filters = B_FALSE; 948 } 949 950 return (0); 951 952fail2: 953 EFSYS_PROBE(fail2); 954fail1: 955 EFSYS_PROBE1(fail1, efx_rc_t, rc); 956 957 return (rc); 958} 959 960/* 961 * The external port mapping is a one-based numbering of the external 962 * connectors on the board. It does not distinguish off-board separated 963 * outputs such as multi-headed cables. 964 * The number of ports that map to each external port connector 965 * on the board is determined by the chip family and the port modes to 966 * which the NIC can be configured. The mapping table lists modes with 967 * port numbering requirements in increasing order. 968 */ 969static struct { 970 efx_family_t family; 971 uint32_t modes_mask; 972 uint32_t stride; 973} __ef10_external_port_mappings[] = { 974 /* Supported modes requiring 1 output per port */ 975 { 976 EFX_FAMILY_HUNTINGTON, 977 (1 << TLV_PORT_MODE_10G) | 978 (1 << TLV_PORT_MODE_10G_10G) | 979 (1 << TLV_PORT_MODE_10G_10G_10G_10G), 980 1 981 }, 982 /* Supported modes requiring 2 outputs per port */ 983 { 984 EFX_FAMILY_HUNTINGTON, 985 (1 << TLV_PORT_MODE_40G) | 986 (1 << TLV_PORT_MODE_40G_40G) | 987 (1 << TLV_PORT_MODE_40G_10G_10G) | 988 (1 << TLV_PORT_MODE_10G_10G_40G), 989 2 990 } 991 /* 992 * NOTE: Medford modes will require 4 outputs per port: 993 * TLV_PORT_MODE_10G_10G_10G_10G_Q 994 * TLV_PORT_MODE_10G_10G_10G_10G_Q2 995 * The Q2 mode routes outputs to external port 2. Support for this 996 * will require a new field specifying the number to add after 997 * scaling by stride. This is fixed at 1 currently. 998 */ 999}; 1000 1001static __checkReturn efx_rc_t 1002ef10_external_port_mapping( 1003 __in efx_nic_t *enp, 1004 __in uint32_t port, 1005 __out uint8_t *external_portp) 1006{ 1007 efx_rc_t rc; 1008 int i; 1009 uint32_t port_modes; 1010 uint32_t matches; 1011 uint32_t stride = 1; /* default 1-1 mapping */ 1012 1013 if ((rc = efx_mcdi_get_port_modes(enp, &port_modes)) != 0) { 1014 /* No port mode information available - use default mapping */ 1015 goto out; 1016 } 1017 1018 /* 1019 * Infer the internal port -> external port mapping from 1020 * the possible port modes for this NIC. 1021 */ 1022 for (i = 0; i < EFX_ARRAY_SIZE(__ef10_external_port_mappings); ++i) { 1023 if (__ef10_external_port_mappings[i].family != 1024 enp->en_family) 1025 continue; 1026 matches = (__ef10_external_port_mappings[i].modes_mask & 1027 port_modes); 1028 if (matches != 0) { 1029 stride = __ef10_external_port_mappings[i].stride; 1030 port_modes &= ~matches; 1031 } 1032 } 1033 1034 if (port_modes != 0) { 1035 /* Some advertised modes are not supported */ 1036 rc = ENOTSUP; 1037 goto fail1; 1038 } 1039 1040out: 1041 /* 1042 * Scale as required by last matched mode and then convert to 1043 * one-based numbering 1044 */ 1045 *external_portp = (uint8_t)(port / stride) + 1; 1046 return (0); 1047 1048fail1: 1049 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1050 1051 return (rc); 1052} 1053 1054static __checkReturn efx_rc_t 1055hunt_board_cfg( 1056 __in efx_nic_t *enp) 1057{ 1058 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 1059 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1060 uint8_t mac_addr[6]; 1061 uint32_t board_type = 0; 1062 hunt_link_state_t hls; 1063 efx_port_t *epp = &(enp->en_port); 1064 uint32_t port; 1065 uint32_t pf; 1066 uint32_t vf; 1067 uint32_t mask; 1068 uint32_t flags; 1069 uint32_t sysclk; 1070 uint32_t base, nvec; 1071 efx_rc_t rc; 1072 1073 if ((rc = efx_mcdi_get_port_assignment(enp, &port)) != 0) 1074 goto fail1; 1075 1076 /* 1077 * NOTE: The MCDI protocol numbers ports from zero. 1078 * The common code MCDI interface numbers ports from one. 1079 */ 1080 emip->emi_port = port + 1; 1081 1082 if ((rc = ef10_external_port_mapping(enp, port, 1083 &encp->enc_external_port)) != 0) 1084 goto fail2; 1085 1086 /* 1087 * Get PCIe function number from firmware (used for 1088 * per-function privilege and dynamic config info). 1089 * - PCIe PF: pf = PF number, vf = 0xffff. 1090 * - PCIe VF: pf = parent PF, vf = VF number. 1091 */ 1092 if ((rc = efx_mcdi_get_function_info(enp, &pf, &vf)) != 0) 1093 goto fail3; 1094 1095 encp->enc_pf = pf; 1096 encp->enc_vf = vf; 1097 1098 /* MAC address for this function */ 1099 if (EFX_PCI_FUNCTION_IS_PF(encp)) { 1100 rc = efx_mcdi_get_mac_address_pf(enp, mac_addr); 1101 if ((rc == 0) && (mac_addr[0] & 0x02)) { 1102 /* 1103 * If the static config does not include a global MAC 1104 * address pool then the board may return a locally 1105 * administered MAC address (this should only happen on 1106 * incorrectly programmed boards). 1107 */ 1108 rc = EINVAL; 1109 } 1110 } else { 1111 rc = efx_mcdi_get_mac_address_vf(enp, mac_addr); 1112 } 1113 if (rc != 0) 1114 goto fail4; 1115 1116 EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr); 1117 1118 /* Board configuration */ 1119 rc = efx_mcdi_get_board_cfg(enp, &board_type, NULL, NULL); 1120 if (rc != 0) { 1121 /* Unprivileged functions may not be able to read board cfg */ 1122 if (rc == EACCES) 1123 board_type = 0; 1124 else 1125 goto fail5; 1126 } 1127 1128 encp->enc_board_type = board_type; 1129 encp->enc_clk_mult = 1; /* not used for Huntington */ 1130 1131 /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */ 1132 if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0) 1133 goto fail6; 1134 1135 /* Obtain the default PHY advertised capabilities */ 1136 if ((rc = hunt_phy_get_link(enp, &hls)) != 0) 1137 goto fail7; 1138 epp->ep_default_adv_cap_mask = hls.hls_adv_cap_mask; 1139 epp->ep_adv_cap_mask = hls.hls_adv_cap_mask; 1140 1141 /* 1142 * Enable firmware workarounds for hardware errata. 1143 * Expected responses are: 1144 * - 0 (zero): 1145 * Success: workaround enabled or disabled as requested. 1146 * - MC_CMD_ERR_ENOSYS (reported as ENOTSUP): 1147 * Firmware does not support the MC_CMD_WORKAROUND request. 1148 * (assume that the workaround is not supported). 1149 * - MC_CMD_ERR_ENOENT (reported as ENOENT): 1150 * Firmware does not support the requested workaround. 1151 * - MC_CMD_ERR_EPERM (reported as EACCES): 1152 * Unprivileged function cannot enable/disable workarounds. 1153 * 1154 * See efx_mcdi_request_errcode() for MCDI error translations. 1155 */ 1156 1157 /* 1158 * If the bug35388 workaround is enabled, then use an indirect access 1159 * method to avoid unsafe EVQ writes. 1160 */ 1161 rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG35388, B_TRUE, 1162 NULL); 1163 if ((rc == 0) || (rc == EACCES)) 1164 encp->enc_bug35388_workaround = B_TRUE; 1165 else if ((rc == ENOTSUP) || (rc == ENOENT)) 1166 encp->enc_bug35388_workaround = B_FALSE; 1167 else 1168 goto fail8; 1169 1170 /* 1171 * If the bug41750 workaround is enabled, then do not test interrupts, 1172 * as the test will fail (seen with Greenport controllers). 1173 */ 1174 rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG41750, B_TRUE, 1175 NULL); 1176 if (rc == 0) { 1177 encp->enc_bug41750_workaround = B_TRUE; 1178 } else if (rc == EACCES) { 1179 /* Assume a controller with 40G ports needs the workaround. */ 1180 if (epp->ep_default_adv_cap_mask & EFX_PHY_CAP_40000FDX) 1181 encp->enc_bug41750_workaround = B_TRUE; 1182 else 1183 encp->enc_bug41750_workaround = B_FALSE; 1184 } else if ((rc == ENOTSUP) || (rc == ENOENT)) { 1185 encp->enc_bug41750_workaround = B_FALSE; 1186 } else { 1187 goto fail9; 1188 } 1189 if (EFX_PCI_FUNCTION_IS_VF(encp)) { 1190 /* Interrupt testing does not work for VFs. See bug50084. */ 1191 encp->enc_bug41750_workaround = B_TRUE; 1192 } 1193 1194 /* 1195 * If the bug26807 workaround is enabled, then firmware has enabled 1196 * support for chained multicast filters. Firmware will reset (FLR) 1197 * functions which have filters in the hardware filter table when the 1198 * workaround is enabled/disabled. 1199 * 1200 * We must recheck if the workaround is enabled after inserting the 1201 * first hardware filter, in case it has been changed since this check. 1202 */ 1203 rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG26807, 1204 B_TRUE, &flags); 1205 if (rc == 0) { 1206 encp->enc_bug26807_workaround = B_TRUE; 1207 if (flags & (1 << MC_CMD_WORKAROUND_EXT_OUT_FLR_DONE_LBN)) { 1208 /* 1209 * Other functions had installed filters before the 1210 * workaround was enabled, and they have been reset 1211 * by firmware. 1212 */ 1213 EFSYS_PROBE(bug26807_workaround_flr_done); 1214 /* FIXME: bump MC warm boot count ? */ 1215 } 1216 } else if (rc == EACCES) { 1217 /* 1218 * Unprivileged functions cannot enable the workaround in older 1219 * firmware. 1220 */ 1221 encp->enc_bug26807_workaround = B_FALSE; 1222 } else if ((rc == ENOTSUP) || (rc == ENOENT)) { 1223 encp->enc_bug26807_workaround = B_FALSE; 1224 } else { 1225 goto fail10; 1226 } 1227 1228 /* Get sysclk frequency (in MHz). */ 1229 if ((rc = efx_mcdi_get_clock(enp, &sysclk)) != 0) 1230 goto fail11; 1231 1232 /* 1233 * The timer quantum is 1536 sysclk cycles, documented for the 1234 * EV_TMR_VAL field of EV_TIMER_TBL. Scale for MHz and ns units. 1235 */ 1236 encp->enc_evq_timer_quantum_ns = 1536000UL / sysclk; /* 1536 cycles */ 1237 if (encp->enc_bug35388_workaround) { 1238 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns << 1239 ERF_DD_EVQ_IND_TIMER_VAL_WIDTH) / 1000; 1240 } else { 1241 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns << 1242 FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000; 1243 } 1244 1245 /* Check capabilities of running datapath firmware */ 1246 if ((rc = ef10_get_datapath_caps(enp)) != 0) 1247 goto fail12; 1248 1249 /* Alignment for receive packet DMA buffers */ 1250 encp->enc_rx_buf_align_start = 1; 1251 encp->enc_rx_buf_align_end = 64; /* RX DMA end padding */ 1252 1253 /* Alignment for WPTR updates */ 1254 encp->enc_rx_push_align = EF10_RX_WPTR_ALIGN; 1255 1256 /* 1257 * Set resource limits for MC_CMD_ALLOC_VIS. Note that we cannot use 1258 * MC_CMD_GET_RESOURCE_LIMITS here as that reports the available 1259 * resources (allocated to this PCIe function), which is zero until 1260 * after we have allocated VIs. 1261 */ 1262 encp->enc_evq_limit = 1024; 1263 encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET; 1264 encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET; 1265 1266 encp->enc_buftbl_limit = 0xFFFFFFFF; 1267 1268 encp->enc_piobuf_limit = HUNT_PIOBUF_NBUFS; 1269 encp->enc_piobuf_size = HUNT_PIOBUF_SIZE; 1270 encp->enc_piobuf_min_alloc_size = HUNT_MIN_PIO_ALLOC_SIZE; 1271 1272 /* 1273 * Get the current privilege mask. Note that this may be modified 1274 * dynamically, so this value is informational only. DO NOT use 1275 * the privilege mask to check for sufficient privileges, as that 1276 * can result in time-of-check/time-of-use bugs. 1277 */ 1278 if ((rc = efx_mcdi_privilege_mask(enp, pf, vf, &mask)) != 0) { 1279 if (rc != ENOTSUP) 1280 goto fail13; 1281 1282 /* Fallback for old firmware without privilege mask support */ 1283 if (EFX_PCI_FUNCTION_IS_PF(encp)) { 1284 /* Assume PF has admin privilege */ 1285 mask = HUNT_LEGACY_PF_PRIVILEGE_MASK; 1286 } else { 1287 /* VF is always unprivileged by default */ 1288 mask = HUNT_LEGACY_VF_PRIVILEGE_MASK; 1289 } 1290 } 1291 1292 encp->enc_privilege_mask = mask; 1293 1294 /* Get interrupt vector limits */ 1295 if ((rc = efx_mcdi_get_vector_cfg(enp, &base, &nvec, NULL)) != 0) { 1296 if (EFX_PCI_FUNCTION_IS_PF(encp)) 1297 goto fail14; 1298 1299 /* Ignore error (cannot query vector limits from a VF). */ 1300 base = 0; 1301 nvec = 1024; 1302 } 1303 encp->enc_intr_vec_base = base; 1304 encp->enc_intr_limit = nvec; 1305 1306 /* 1307 * Maximum number of bytes into the frame the TCP header can start for 1308 * firmware assisted TSO to work. 1309 */ 1310 encp->enc_tx_tso_tcp_header_offset_limit = 208; 1311 1312 return (0); 1313 1314fail14: 1315 EFSYS_PROBE(fail14); 1316fail13: 1317 EFSYS_PROBE(fail13); 1318fail12: 1319 EFSYS_PROBE(fail12); 1320fail11: 1321 EFSYS_PROBE(fail11); 1322fail10: 1323 EFSYS_PROBE(fail10); 1324fail9: 1325 EFSYS_PROBE(fail9); 1326fail8: 1327 EFSYS_PROBE(fail8); 1328fail7: 1329 EFSYS_PROBE(fail7); 1330fail6: 1331 EFSYS_PROBE(fail6); 1332fail5: 1333 EFSYS_PROBE(fail5); 1334fail4: 1335 EFSYS_PROBE(fail4); 1336fail3: 1337 EFSYS_PROBE(fail3); 1338fail2: 1339 EFSYS_PROBE(fail2); 1340fail1: 1341 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1342 1343 return (rc); 1344} 1345 1346 1347 __checkReturn efx_rc_t 1348ef10_nic_probe( 1349 __in efx_nic_t *enp) 1350{ 1351 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1352 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1353 efx_rc_t rc; 1354 1355 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1356 enp->en_family == EFX_FAMILY_MEDFORD); 1357 1358 /* Read and clear any assertion state */ 1359 if ((rc = efx_mcdi_read_assertion(enp)) != 0) 1360 goto fail1; 1361 1362 /* Exit the assertion handler */ 1363 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 1364 if (rc != EACCES) 1365 goto fail2; 1366 1367 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0) 1368 goto fail3; 1369 1370 if ((rc = hunt_board_cfg(enp)) != 0) 1371 if (rc != EACCES) 1372 goto fail4; 1373 1374 /* 1375 * Set default driver config limits (based on board config). 1376 * 1377 * FIXME: For now allocate a fixed number of VIs which is likely to be 1378 * sufficient and small enough to allow multiple functions on the same 1379 * port. 1380 */ 1381 edcp->edc_min_vi_count = edcp->edc_max_vi_count = 1382 MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit)); 1383 1384 /* The client driver must configure and enable PIO buffer support */ 1385 edcp->edc_max_piobuf_count = 0; 1386 edcp->edc_pio_alloc_size = 0; 1387 1388#if EFSYS_OPT_MAC_STATS 1389 /* Wipe the MAC statistics */ 1390 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0) 1391 goto fail5; 1392#endif 1393 1394#if EFSYS_OPT_LOOPBACK 1395 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0) 1396 goto fail6; 1397#endif 1398 1399#if EFSYS_OPT_MON_STATS 1400 if ((rc = mcdi_mon_cfg_build(enp)) != 0) { 1401 /* Unprivileged functions do not have access to sensors */ 1402 if (rc != EACCES) 1403 goto fail7; 1404 } 1405#endif 1406 1407 encp->enc_features = enp->en_features; 1408 1409 return (0); 1410 1411#if EFSYS_OPT_MON_STATS 1412fail7: 1413 EFSYS_PROBE(fail7); 1414#endif 1415#if EFSYS_OPT_LOOPBACK 1416fail6: 1417 EFSYS_PROBE(fail6); 1418#endif 1419#if EFSYS_OPT_MAC_STATS 1420fail5: 1421 EFSYS_PROBE(fail5); 1422#endif 1423fail4: 1424 EFSYS_PROBE(fail4); 1425fail3: 1426 EFSYS_PROBE(fail3); 1427fail2: 1428 EFSYS_PROBE(fail2); 1429fail1: 1430 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1431 1432 return (rc); 1433} 1434 1435 __checkReturn efx_rc_t 1436ef10_nic_set_drv_limits( 1437 __inout efx_nic_t *enp, 1438 __in efx_drv_limits_t *edlp) 1439{ 1440 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1441 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1442 uint32_t min_evq_count, max_evq_count; 1443 uint32_t min_rxq_count, max_rxq_count; 1444 uint32_t min_txq_count, max_txq_count; 1445 efx_rc_t rc; 1446 1447 if (edlp == NULL) { 1448 rc = EINVAL; 1449 goto fail1; 1450 } 1451 1452 /* Get minimum required and maximum usable VI limits */ 1453 min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit); 1454 min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit); 1455 min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit); 1456 1457 edcp->edc_min_vi_count = 1458 MAX(min_evq_count, MAX(min_rxq_count, min_txq_count)); 1459 1460 max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit); 1461 max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit); 1462 max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit); 1463 1464 edcp->edc_max_vi_count = 1465 MAX(max_evq_count, MAX(max_rxq_count, max_txq_count)); 1466 1467 /* 1468 * Check limits for sub-allocated piobuf blocks. 1469 * PIO is optional, so don't fail if the limits are incorrect. 1470 */ 1471 if ((encp->enc_piobuf_size == 0) || 1472 (encp->enc_piobuf_limit == 0) || 1473 (edlp->edl_min_pio_alloc_size == 0) || 1474 (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) { 1475 /* Disable PIO */ 1476 edcp->edc_max_piobuf_count = 0; 1477 edcp->edc_pio_alloc_size = 0; 1478 } else { 1479 uint32_t blk_size, blk_count, blks_per_piobuf; 1480 1481 blk_size = 1482 MAX(edlp->edl_min_pio_alloc_size, 1483 encp->enc_piobuf_min_alloc_size); 1484 1485 blks_per_piobuf = encp->enc_piobuf_size / blk_size; 1486 EFSYS_ASSERT3U(blks_per_piobuf, <=, 32); 1487 1488 blk_count = (encp->enc_piobuf_limit * blks_per_piobuf); 1489 1490 /* A zero max pio alloc count means unlimited */ 1491 if ((edlp->edl_max_pio_alloc_count > 0) && 1492 (edlp->edl_max_pio_alloc_count < blk_count)) { 1493 blk_count = edlp->edl_max_pio_alloc_count; 1494 } 1495 1496 edcp->edc_pio_alloc_size = blk_size; 1497 edcp->edc_max_piobuf_count = 1498 (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf; 1499 } 1500 1501 return (0); 1502 1503fail1: 1504 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1505 1506 return (rc); 1507} 1508 1509 1510 __checkReturn efx_rc_t 1511ef10_nic_reset( 1512 __in efx_nic_t *enp) 1513{ 1514 efx_mcdi_req_t req; 1515 uint8_t payload[MAX(MC_CMD_ENTITY_RESET_IN_LEN, 1516 MC_CMD_ENTITY_RESET_OUT_LEN)]; 1517 efx_rc_t rc; 1518 1519 /* ef10_nic_reset() is called to recover from BADASSERT failures. */ 1520 if ((rc = efx_mcdi_read_assertion(enp)) != 0) 1521 goto fail1; 1522 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 1523 goto fail2; 1524 1525 (void) memset(payload, 0, sizeof (payload)); 1526 req.emr_cmd = MC_CMD_ENTITY_RESET; 1527 req.emr_in_buf = payload; 1528 req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN; 1529 req.emr_out_buf = payload; 1530 req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN; 1531 1532 MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG, 1533 ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1); 1534 1535 efx_mcdi_execute(enp, &req); 1536 1537 if (req.emr_rc != 0) { 1538 rc = req.emr_rc; 1539 goto fail3; 1540 } 1541 1542 /* Clear RX/TX DMA queue errors */ 1543 enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR); 1544 1545 return (0); 1546 1547fail3: 1548 EFSYS_PROBE(fail3); 1549fail2: 1550 EFSYS_PROBE(fail2); 1551fail1: 1552 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1553 1554 return (rc); 1555} 1556 1557 __checkReturn efx_rc_t 1558ef10_nic_init( 1559 __in efx_nic_t *enp) 1560{ 1561 efx_drv_cfg_t *edcp = &(enp->en_drv_cfg); 1562 uint32_t min_vi_count, max_vi_count; 1563 uint32_t vi_count, vi_base; 1564 uint32_t i; 1565 uint32_t retry; 1566 uint32_t delay_us; 1567 efx_rc_t rc; 1568 1569 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1570 enp->en_family == EFX_FAMILY_MEDFORD); 1571 1572 /* Enable reporting of some events (e.g. link change) */ 1573 if ((rc = efx_mcdi_log_ctrl(enp)) != 0) 1574 goto fail1; 1575 1576 /* Allocate (optional) on-chip PIO buffers */ 1577 ef10_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count); 1578 1579 /* 1580 * For best performance, PIO writes should use a write-combined 1581 * (WC) memory mapping. Using a separate WC mapping for the PIO 1582 * aperture of each VI would be a burden to drivers (and not 1583 * possible if the host page size is >4Kbyte). 1584 * 1585 * To avoid this we use a single uncached (UC) mapping for VI 1586 * register access, and a single WC mapping for extra VIs used 1587 * for PIO writes. 1588 * 1589 * Each piobuf must be linked to a VI in the WC mapping, and to 1590 * each VI that is using a sub-allocated block from the piobuf. 1591 */ 1592 min_vi_count = edcp->edc_min_vi_count; 1593 max_vi_count = 1594 edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count; 1595 1596 /* Ensure that the previously attached driver's VIs are freed */ 1597 if ((rc = efx_mcdi_free_vis(enp)) != 0) 1598 goto fail2; 1599 1600 /* 1601 * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this 1602 * fails then retrying the request for fewer VI resources may succeed. 1603 */ 1604 vi_count = 0; 1605 if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count, 1606 &vi_base, &vi_count)) != 0) 1607 goto fail3; 1608 1609 EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count); 1610 1611 if (vi_count < min_vi_count) { 1612 rc = ENOMEM; 1613 goto fail4; 1614 } 1615 1616 enp->en_arch.ef10.ena_vi_base = vi_base; 1617 enp->en_arch.ef10.ena_vi_count = vi_count; 1618 1619 if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) { 1620 /* Not enough extra VIs to map piobufs */ 1621 ef10_nic_free_piobufs(enp); 1622 } 1623 1624 enp->en_arch.ef10.ena_pio_write_vi_base = 1625 vi_count - enp->en_arch.ef10.ena_piobuf_count; 1626 1627 /* Save UC memory mapping details */ 1628 enp->en_arch.ef10.ena_uc_mem_map_offset = 0; 1629 if (enp->en_arch.ef10.ena_piobuf_count > 0) { 1630 enp->en_arch.ef10.ena_uc_mem_map_size = 1631 (ER_DZ_TX_PIOBUF_STEP * 1632 enp->en_arch.ef10.ena_pio_write_vi_base); 1633 } else { 1634 enp->en_arch.ef10.ena_uc_mem_map_size = 1635 (ER_DZ_TX_PIOBUF_STEP * 1636 enp->en_arch.ef10.ena_vi_count); 1637 } 1638 1639 /* Save WC memory mapping details */ 1640 enp->en_arch.ef10.ena_wc_mem_map_offset = 1641 enp->en_arch.ef10.ena_uc_mem_map_offset + 1642 enp->en_arch.ef10.ena_uc_mem_map_size; 1643 1644 enp->en_arch.ef10.ena_wc_mem_map_size = 1645 (ER_DZ_TX_PIOBUF_STEP * 1646 enp->en_arch.ef10.ena_piobuf_count); 1647 1648 /* Link piobufs to extra VIs in WC mapping */ 1649 if (enp->en_arch.ef10.ena_piobuf_count > 0) { 1650 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 1651 rc = efx_mcdi_link_piobuf(enp, 1652 enp->en_arch.ef10.ena_pio_write_vi_base + i, 1653 enp->en_arch.ef10.ena_piobuf_handle[i]); 1654 if (rc != 0) 1655 break; 1656 } 1657 } 1658 1659 /* 1660 * Allocate a vAdaptor attached to our upstream vPort/pPort. 1661 * 1662 * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF 1663 * driver has yet to bring up the EVB port. See bug 56147. In this case, 1664 * retry the request several times after waiting a while. The wait time 1665 * between retries starts small (10ms) and exponentially increases. 1666 * Total wait time is a little over two seconds. Retry logic in the 1667 * client driver may mean this whole loop is repeated if it continues to 1668 * fail. 1669 */ 1670 retry = 0; 1671 delay_us = 10000; 1672 while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) { 1673 if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) || 1674 (rc != ENOENT)) { 1675 /* 1676 * Do not retry alloc for PF, or for other errors on 1677 * a VF. 1678 */ 1679 goto fail5; 1680 } 1681 1682 /* VF startup before PF is ready. Retry allocation. */ 1683 if (retry > 5) { 1684 /* Too many attempts */ 1685 rc = EINVAL; 1686 goto fail6; 1687 } 1688 EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry); 1689 EFSYS_SLEEP(delay_us); 1690 retry++; 1691 if (delay_us < 500000) 1692 delay_us <<= 2; 1693 } 1694 1695 enp->en_vport_id = EVB_PORT_ID_ASSIGNED; 1696 enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2; 1697 1698 return (0); 1699 1700fail6: 1701 EFSYS_PROBE(fail6); 1702fail5: 1703 EFSYS_PROBE(fail5); 1704fail4: 1705 EFSYS_PROBE(fail4); 1706fail3: 1707 EFSYS_PROBE(fail3); 1708fail2: 1709 EFSYS_PROBE(fail2); 1710 1711 ef10_nic_free_piobufs(enp); 1712 1713fail1: 1714 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1715 1716 return (rc); 1717} 1718 1719 __checkReturn efx_rc_t 1720ef10_nic_get_vi_pool( 1721 __in efx_nic_t *enp, 1722 __out uint32_t *vi_countp) 1723{ 1724 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1725 enp->en_family == EFX_FAMILY_MEDFORD); 1726 1727 /* 1728 * Report VIs that the client driver can use. 1729 * Do not include VIs used for PIO buffer writes. 1730 */ 1731 *vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base; 1732 1733 return (0); 1734} 1735 1736 __checkReturn efx_rc_t 1737ef10_nic_get_bar_region( 1738 __in efx_nic_t *enp, 1739 __in efx_nic_region_t region, 1740 __out uint32_t *offsetp, 1741 __out size_t *sizep) 1742{ 1743 efx_rc_t rc; 1744 1745 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 1746 enp->en_family == EFX_FAMILY_MEDFORD); 1747 1748 /* 1749 * TODO: Specify host memory mapping alignment and granularity 1750 * in efx_drv_limits_t so that they can be taken into account 1751 * when allocating extra VIs for PIO writes. 1752 */ 1753 switch (region) { 1754 case EFX_REGION_VI: 1755 /* UC mapped memory BAR region for VI registers */ 1756 *offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset; 1757 *sizep = enp->en_arch.ef10.ena_uc_mem_map_size; 1758 break; 1759 1760 case EFX_REGION_PIO_WRITE_VI: 1761 /* WC mapped memory BAR region for piobuf writes */ 1762 *offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset; 1763 *sizep = enp->en_arch.ef10.ena_wc_mem_map_size; 1764 break; 1765 1766 default: 1767 rc = EINVAL; 1768 goto fail1; 1769 } 1770 1771 return (0); 1772 1773fail1: 1774 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1775 1776 return (rc); 1777} 1778 1779 void 1780ef10_nic_fini( 1781 __in efx_nic_t *enp) 1782{ 1783 uint32_t i; 1784 efx_rc_t rc; 1785 1786 (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id); 1787 enp->en_vport_id = 0; 1788 1789 /* Unlink piobufs from extra VIs in WC mapping */ 1790 if (enp->en_arch.ef10.ena_piobuf_count > 0) { 1791 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) { 1792 rc = efx_mcdi_unlink_piobuf(enp, 1793 enp->en_arch.ef10.ena_pio_write_vi_base + i); 1794 if (rc != 0) 1795 break; 1796 } 1797 } 1798 1799 ef10_nic_free_piobufs(enp); 1800 1801 (void) efx_mcdi_free_vis(enp); 1802 enp->en_arch.ef10.ena_vi_count = 0; 1803} 1804 1805 void 1806ef10_nic_unprobe( 1807 __in efx_nic_t *enp) 1808{ 1809#if EFSYS_OPT_MON_STATS 1810 mcdi_mon_cfg_free(enp); 1811#endif /* EFSYS_OPT_MON_STATS */ 1812 (void) efx_mcdi_drv_attach(enp, B_FALSE); 1813} 1814 1815#if EFSYS_OPT_DIAG 1816 1817 __checkReturn efx_rc_t 1818ef10_nic_register_test( 1819 __in efx_nic_t *enp) 1820{ 1821 efx_rc_t rc; 1822 1823 /* FIXME */ 1824 _NOTE(ARGUNUSED(enp)) 1825 if (B_FALSE) { 1826 rc = ENOTSUP; 1827 goto fail1; 1828 } 1829 /* FIXME */ 1830 1831 return (0); 1832 1833fail1: 1834 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1835 1836 return (rc); 1837} 1838 1839#endif /* EFSYS_OPT_DIAG */ 1840 1841 1842 1843#endif /* EFSYS_OPT_HUNTINGTON */ 1844