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