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