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