1 /*- 2 * Copyright (c) 2008-2016 Solarflare Communications Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * The views and conclusions contained in the software and documentation are 27 * those of the authors and should not be interpreted as representing official 28 * policies, either expressed or implied, of the FreeBSD Project. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include "efx.h" 35 #include "efx_impl.h" 36 37 #if EFSYS_OPT_MCDI 38 39 /* 40 * There are three versions of the MCDI interface: 41 * - MCDIv0: Siena BootROM. Transport uses MCDIv1 headers. 42 * - MCDIv1: Siena firmware and Huntington BootROM. 43 * - MCDIv2: EF10 firmware (Huntington/Medford) and Medford BootROM. 44 * Transport uses MCDIv2 headers. 45 * 46 * MCDIv2 Header NOT_EPOCH flag 47 * ---------------------------- 48 * A new epoch begins at initial startup or after an MC reboot, and defines when 49 * the MC should reject stale MCDI requests. 50 * 51 * The first MCDI request sent by the host should contain NOT_EPOCH=0, and all 52 * subsequent requests (until the next MC reboot) should contain NOT_EPOCH=1. 53 * 54 * After rebooting the MC will fail all requests with NOT_EPOCH=1 by writing a 55 * response with ERROR=1 and DATALEN=0 until a request is seen with NOT_EPOCH=0. 56 */ 57 58 59 60 #if EFSYS_OPT_SIENA 61 62 static const efx_mcdi_ops_t __efx_mcdi_siena_ops = { 63 siena_mcdi_init, /* emco_init */ 64 siena_mcdi_send_request, /* emco_send_request */ 65 siena_mcdi_poll_reboot, /* emco_poll_reboot */ 66 siena_mcdi_poll_response, /* emco_poll_response */ 67 siena_mcdi_read_response, /* emco_read_response */ 68 siena_mcdi_fini, /* emco_fini */ 69 siena_mcdi_feature_supported, /* emco_feature_supported */ 70 }; 71 72 #endif /* EFSYS_OPT_SIENA */ 73 74 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 75 76 static const efx_mcdi_ops_t __efx_mcdi_ef10_ops = { 77 ef10_mcdi_init, /* emco_init */ 78 ef10_mcdi_send_request, /* emco_send_request */ 79 ef10_mcdi_poll_reboot, /* emco_poll_reboot */ 80 ef10_mcdi_poll_response, /* emco_poll_response */ 81 ef10_mcdi_read_response, /* emco_read_response */ 82 ef10_mcdi_fini, /* emco_fini */ 83 ef10_mcdi_feature_supported, /* emco_feature_supported */ 84 }; 85 86 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 87 88 89 90 __checkReturn efx_rc_t 91 efx_mcdi_init( 92 __in efx_nic_t *enp, 93 __in const efx_mcdi_transport_t *emtp) 94 { 95 const efx_mcdi_ops_t *emcop; 96 efx_rc_t rc; 97 98 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 99 EFSYS_ASSERT3U(enp->en_mod_flags, ==, 0); 100 101 switch (enp->en_family) { 102 #if EFSYS_OPT_SIENA 103 case EFX_FAMILY_SIENA: 104 emcop = &__efx_mcdi_siena_ops; 105 break; 106 #endif /* EFSYS_OPT_SIENA */ 107 108 #if EFSYS_OPT_HUNTINGTON 109 case EFX_FAMILY_HUNTINGTON: 110 emcop = &__efx_mcdi_ef10_ops; 111 break; 112 #endif /* EFSYS_OPT_HUNTINGTON */ 113 114 #if EFSYS_OPT_MEDFORD 115 case EFX_FAMILY_MEDFORD: 116 emcop = &__efx_mcdi_ef10_ops; 117 break; 118 #endif /* EFSYS_OPT_MEDFORD */ 119 120 default: 121 EFSYS_ASSERT(0); 122 rc = ENOTSUP; 123 goto fail1; 124 } 125 126 if (enp->en_features & EFX_FEATURE_MCDI_DMA) { 127 /* MCDI requires a DMA buffer in host memory */ 128 if ((emtp == NULL) || (emtp->emt_dma_mem) == NULL) { 129 rc = EINVAL; 130 goto fail2; 131 } 132 } 133 enp->en_mcdi.em_emtp = emtp; 134 135 if (emcop != NULL && emcop->emco_init != NULL) { 136 if ((rc = emcop->emco_init(enp, emtp)) != 0) 137 goto fail3; 138 } 139 140 enp->en_mcdi.em_emcop = emcop; 141 enp->en_mod_flags |= EFX_MOD_MCDI; 142 143 return (0); 144 145 fail3: 146 EFSYS_PROBE(fail3); 147 fail2: 148 EFSYS_PROBE(fail2); 149 fail1: 150 EFSYS_PROBE1(fail1, efx_rc_t, rc); 151 152 enp->en_mcdi.em_emcop = NULL; 153 enp->en_mcdi.em_emtp = NULL; 154 enp->en_mod_flags &= ~EFX_MOD_MCDI; 155 156 return (rc); 157 } 158 159 void 160 efx_mcdi_fini( 161 __in efx_nic_t *enp) 162 { 163 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 164 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 165 166 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 167 EFSYS_ASSERT3U(enp->en_mod_flags, ==, EFX_MOD_MCDI); 168 169 if (emcop != NULL && emcop->emco_fini != NULL) 170 emcop->emco_fini(enp); 171 172 emip->emi_port = 0; 173 emip->emi_aborted = 0; 174 175 enp->en_mcdi.em_emcop = NULL; 176 enp->en_mod_flags &= ~EFX_MOD_MCDI; 177 } 178 179 void 180 efx_mcdi_new_epoch( 181 __in efx_nic_t *enp) 182 { 183 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 184 int state; 185 186 /* Start a new epoch (allow fresh MCDI requests to succeed) */ 187 EFSYS_LOCK(enp->en_eslp, state); 188 emip->emi_new_epoch = B_TRUE; 189 EFSYS_UNLOCK(enp->en_eslp, state); 190 } 191 192 static void 193 efx_mcdi_send_request( 194 __in efx_nic_t *enp, 195 __in void *hdrp, 196 __in size_t hdr_len, 197 __in void *sdup, 198 __in size_t sdu_len) 199 { 200 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 201 202 emcop->emco_send_request(enp, hdrp, hdr_len, sdup, sdu_len); 203 } 204 205 static efx_rc_t 206 efx_mcdi_poll_reboot( 207 __in efx_nic_t *enp) 208 { 209 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 210 efx_rc_t rc; 211 212 rc = emcop->emco_poll_reboot(enp); 213 return (rc); 214 } 215 216 static boolean_t 217 efx_mcdi_poll_response( 218 __in efx_nic_t *enp) 219 { 220 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 221 boolean_t available; 222 223 available = emcop->emco_poll_response(enp); 224 return (available); 225 } 226 227 static void 228 efx_mcdi_read_response( 229 __in efx_nic_t *enp, 230 __out void *bufferp, 231 __in size_t offset, 232 __in size_t length) 233 { 234 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 235 236 emcop->emco_read_response(enp, bufferp, offset, length); 237 } 238 239 void 240 efx_mcdi_request_start( 241 __in efx_nic_t *enp, 242 __in efx_mcdi_req_t *emrp, 243 __in boolean_t ev_cpl) 244 { 245 #if EFSYS_OPT_MCDI_LOGGING 246 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 247 #endif 248 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 249 efx_dword_t hdr[2]; 250 size_t hdr_len; 251 unsigned int max_version; 252 unsigned int seq; 253 unsigned int xflags; 254 boolean_t new_epoch; 255 int state; 256 257 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 258 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); 259 EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); 260 261 /* 262 * efx_mcdi_request_start() is naturally serialised against both 263 * efx_mcdi_request_poll() and efx_mcdi_ev_cpl()/efx_mcdi_ev_death(), 264 * by virtue of there only being one outstanding MCDI request. 265 * Unfortunately, upper layers may also call efx_mcdi_request_abort() 266 * at any time, to timeout a pending mcdi request, That request may 267 * then subsequently complete, meaning efx_mcdi_ev_cpl() or 268 * efx_mcdi_ev_death() may end up running in parallel with 269 * efx_mcdi_request_start(). This race is handled by ensuring that 270 * %emi_pending_req, %emi_ev_cpl and %emi_seq are protected by the 271 * en_eslp lock. 272 */ 273 EFSYS_LOCK(enp->en_eslp, state); 274 EFSYS_ASSERT(emip->emi_pending_req == NULL); 275 emip->emi_pending_req = emrp; 276 emip->emi_ev_cpl = ev_cpl; 277 emip->emi_poll_cnt = 0; 278 seq = emip->emi_seq++ & EFX_MASK32(MCDI_HEADER_SEQ); 279 new_epoch = emip->emi_new_epoch; 280 max_version = emip->emi_max_version; 281 EFSYS_UNLOCK(enp->en_eslp, state); 282 283 xflags = 0; 284 if (ev_cpl) 285 xflags |= MCDI_HEADER_XFLAGS_EVREQ; 286 287 /* 288 * Huntington firmware supports MCDIv2, but the Huntington BootROM only 289 * supports MCDIv1. Use MCDIv1 headers for MCDIv1 commands where 290 * possible to support this. 291 */ 292 if ((max_version >= 2) && 293 ((emrp->emr_cmd > MC_CMD_CMD_SPACE_ESCAPE_7) || 294 (emrp->emr_in_length > MCDI_CTL_SDU_LEN_MAX_V1))) { 295 /* Construct MCDI v2 header */ 296 hdr_len = sizeof (hdr); 297 EFX_POPULATE_DWORD_8(hdr[0], 298 MCDI_HEADER_CODE, MC_CMD_V2_EXTN, 299 MCDI_HEADER_RESYNC, 1, 300 MCDI_HEADER_DATALEN, 0, 301 MCDI_HEADER_SEQ, seq, 302 MCDI_HEADER_NOT_EPOCH, new_epoch ? 0 : 1, 303 MCDI_HEADER_ERROR, 0, 304 MCDI_HEADER_RESPONSE, 0, 305 MCDI_HEADER_XFLAGS, xflags); 306 307 EFX_POPULATE_DWORD_2(hdr[1], 308 MC_CMD_V2_EXTN_IN_EXTENDED_CMD, emrp->emr_cmd, 309 MC_CMD_V2_EXTN_IN_ACTUAL_LEN, emrp->emr_in_length); 310 } else { 311 /* Construct MCDI v1 header */ 312 hdr_len = sizeof (hdr[0]); 313 EFX_POPULATE_DWORD_8(hdr[0], 314 MCDI_HEADER_CODE, emrp->emr_cmd, 315 MCDI_HEADER_RESYNC, 1, 316 MCDI_HEADER_DATALEN, emrp->emr_in_length, 317 MCDI_HEADER_SEQ, seq, 318 MCDI_HEADER_NOT_EPOCH, new_epoch ? 0 : 1, 319 MCDI_HEADER_ERROR, 0, 320 MCDI_HEADER_RESPONSE, 0, 321 MCDI_HEADER_XFLAGS, xflags); 322 } 323 324 #if EFSYS_OPT_MCDI_LOGGING 325 if (emtp->emt_logger != NULL) { 326 emtp->emt_logger(emtp->emt_context, EFX_LOG_MCDI_REQUEST, 327 &hdr, hdr_len, 328 emrp->emr_in_buf, emrp->emr_in_length); 329 } 330 #endif /* EFSYS_OPT_MCDI_LOGGING */ 331 332 efx_mcdi_send_request(enp, &hdr[0], hdr_len, 333 emrp->emr_in_buf, emrp->emr_in_length); 334 } 335 336 337 static void 338 efx_mcdi_read_response_header( 339 __in efx_nic_t *enp, 340 __inout efx_mcdi_req_t *emrp) 341 { 342 #if EFSYS_OPT_MCDI_LOGGING 343 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 344 #endif /* EFSYS_OPT_MCDI_LOGGING */ 345 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 346 efx_dword_t hdr[2]; 347 unsigned int hdr_len; 348 unsigned int data_len; 349 unsigned int seq; 350 unsigned int cmd; 351 unsigned int error; 352 efx_rc_t rc; 353 354 EFSYS_ASSERT(emrp != NULL); 355 356 efx_mcdi_read_response(enp, &hdr[0], 0, sizeof (hdr[0])); 357 hdr_len = sizeof (hdr[0]); 358 359 cmd = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE); 360 seq = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_SEQ); 361 error = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_ERROR); 362 363 if (cmd != MC_CMD_V2_EXTN) { 364 data_len = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_DATALEN); 365 } else { 366 efx_mcdi_read_response(enp, &hdr[1], hdr_len, sizeof (hdr[1])); 367 hdr_len += sizeof (hdr[1]); 368 369 cmd = EFX_DWORD_FIELD(hdr[1], MC_CMD_V2_EXTN_IN_EXTENDED_CMD); 370 data_len = 371 EFX_DWORD_FIELD(hdr[1], MC_CMD_V2_EXTN_IN_ACTUAL_LEN); 372 } 373 374 if (error && (data_len == 0)) { 375 /* The MC has rebooted since the request was sent. */ 376 EFSYS_SPIN(EFX_MCDI_STATUS_SLEEP_US); 377 efx_mcdi_poll_reboot(enp); 378 rc = EIO; 379 goto fail1; 380 } 381 if ((cmd != emrp->emr_cmd) || 382 (seq != ((emip->emi_seq - 1) & EFX_MASK32(MCDI_HEADER_SEQ)))) { 383 /* Response is for a different request */ 384 rc = EIO; 385 goto fail2; 386 } 387 if (error) { 388 efx_dword_t err[2]; 389 unsigned int err_len = MIN(data_len, sizeof (err)); 390 int err_code = MC_CMD_ERR_EPROTO; 391 int err_arg = 0; 392 393 /* Read error code (and arg num for MCDI v2 commands) */ 394 efx_mcdi_read_response(enp, &err, hdr_len, err_len); 395 396 if (err_len >= (MC_CMD_ERR_CODE_OFST + sizeof (efx_dword_t))) 397 err_code = EFX_DWORD_FIELD(err[0], EFX_DWORD_0); 398 #ifdef WITH_MCDI_V2 399 if (err_len >= (MC_CMD_ERR_ARG_OFST + sizeof (efx_dword_t))) 400 err_arg = EFX_DWORD_FIELD(err[1], EFX_DWORD_0); 401 #endif 402 emrp->emr_err_code = err_code; 403 emrp->emr_err_arg = err_arg; 404 405 #if EFSYS_OPT_MCDI_PROXY_AUTH 406 if ((err_code == MC_CMD_ERR_PROXY_PENDING) && 407 (err_len == sizeof (err))) { 408 /* 409 * The MCDI request would normally fail with EPERM, but 410 * firmware has forwarded it to an authorization agent 411 * attached to a privileged PF. 412 * 413 * Save the authorization request handle. The client 414 * must wait for a PROXY_RESPONSE event, or timeout. 415 */ 416 emrp->emr_proxy_handle = err_arg; 417 } 418 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH */ 419 420 #if EFSYS_OPT_MCDI_LOGGING 421 if (emtp->emt_logger != NULL) { 422 emtp->emt_logger(emtp->emt_context, 423 EFX_LOG_MCDI_RESPONSE, 424 &hdr, hdr_len, 425 &err, err_len); 426 } 427 #endif /* EFSYS_OPT_MCDI_LOGGING */ 428 429 if (!emrp->emr_quiet) { 430 EFSYS_PROBE3(mcdi_err_arg, int, emrp->emr_cmd, 431 int, err_code, int, err_arg); 432 } 433 434 rc = efx_mcdi_request_errcode(err_code); 435 goto fail3; 436 } 437 438 emrp->emr_rc = 0; 439 emrp->emr_out_length_used = data_len; 440 #if EFSYS_OPT_MCDI_PROXY_AUTH 441 emrp->emr_proxy_handle = 0; 442 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH */ 443 return; 444 445 fail3: 446 fail2: 447 fail1: 448 emrp->emr_rc = rc; 449 emrp->emr_out_length_used = 0; 450 } 451 452 static void 453 efx_mcdi_finish_response( 454 __in efx_nic_t *enp, 455 __in efx_mcdi_req_t *emrp) 456 { 457 #if EFSYS_OPT_MCDI_LOGGING 458 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 459 #endif /* EFSYS_OPT_MCDI_LOGGING */ 460 efx_dword_t hdr[2]; 461 unsigned int hdr_len; 462 size_t bytes; 463 464 if (emrp->emr_out_buf == NULL) 465 return; 466 467 /* Read the command header to detect MCDI response format */ 468 hdr_len = sizeof (hdr[0]); 469 efx_mcdi_read_response(enp, &hdr[0], 0, hdr_len); 470 if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE) == MC_CMD_V2_EXTN) { 471 /* 472 * Read the actual payload length. The length given in the event 473 * is only correct for responses with the V1 format. 474 */ 475 efx_mcdi_read_response(enp, &hdr[1], hdr_len, sizeof (hdr[1])); 476 hdr_len += sizeof (hdr[1]); 477 478 emrp->emr_out_length_used = EFX_DWORD_FIELD(hdr[1], 479 MC_CMD_V2_EXTN_IN_ACTUAL_LEN); 480 } 481 482 /* Copy payload out into caller supplied buffer */ 483 bytes = MIN(emrp->emr_out_length_used, emrp->emr_out_length); 484 efx_mcdi_read_response(enp, emrp->emr_out_buf, hdr_len, bytes); 485 486 #if EFSYS_OPT_MCDI_LOGGING 487 if (emtp->emt_logger != NULL) { 488 emtp->emt_logger(emtp->emt_context, 489 EFX_LOG_MCDI_RESPONSE, 490 &hdr, hdr_len, 491 emrp->emr_out_buf, bytes); 492 } 493 #endif /* EFSYS_OPT_MCDI_LOGGING */ 494 } 495 496 497 __checkReturn boolean_t 498 efx_mcdi_request_poll( 499 __in efx_nic_t *enp) 500 { 501 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 502 efx_mcdi_req_t *emrp; 503 int state; 504 efx_rc_t rc; 505 506 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 507 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); 508 EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); 509 510 /* Serialise against post-watchdog efx_mcdi_ev* */ 511 EFSYS_LOCK(enp->en_eslp, state); 512 513 EFSYS_ASSERT(emip->emi_pending_req != NULL); 514 EFSYS_ASSERT(!emip->emi_ev_cpl); 515 emrp = emip->emi_pending_req; 516 517 /* Check for reboot atomically w.r.t efx_mcdi_request_start */ 518 if (emip->emi_poll_cnt++ == 0) { 519 if ((rc = efx_mcdi_poll_reboot(enp)) != 0) { 520 emip->emi_pending_req = NULL; 521 EFSYS_UNLOCK(enp->en_eslp, state); 522 523 /* Reboot/Assertion */ 524 if (rc == EIO || rc == EINTR) 525 efx_mcdi_raise_exception(enp, emrp, rc); 526 527 goto fail1; 528 } 529 } 530 531 /* Check if a response is available */ 532 if (efx_mcdi_poll_response(enp) == B_FALSE) { 533 EFSYS_UNLOCK(enp->en_eslp, state); 534 return (B_FALSE); 535 } 536 537 /* Read the response header */ 538 efx_mcdi_read_response_header(enp, emrp); 539 540 /* Request complete */ 541 emip->emi_pending_req = NULL; 542 543 /* Ensure stale MCDI requests fail after an MC reboot. */ 544 emip->emi_new_epoch = B_FALSE; 545 546 EFSYS_UNLOCK(enp->en_eslp, state); 547 548 if ((rc = emrp->emr_rc) != 0) 549 goto fail2; 550 551 efx_mcdi_finish_response(enp, emrp); 552 return (B_TRUE); 553 554 fail2: 555 if (!emrp->emr_quiet) 556 EFSYS_PROBE(fail2); 557 fail1: 558 if (!emrp->emr_quiet) 559 EFSYS_PROBE1(fail1, efx_rc_t, rc); 560 561 return (B_TRUE); 562 } 563 564 __checkReturn boolean_t 565 efx_mcdi_request_abort( 566 __in efx_nic_t *enp) 567 { 568 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 569 efx_mcdi_req_t *emrp; 570 boolean_t aborted; 571 int state; 572 573 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 574 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); 575 EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); 576 577 /* 578 * efx_mcdi_ev_* may have already completed this event, and be 579 * spinning/blocked on the upper layer lock. So it *is* legitimate 580 * to for emi_pending_req to be NULL. If there is a pending event 581 * completed request, then provide a "credit" to allow 582 * efx_mcdi_ev_cpl() to accept a single spurious completion. 583 */ 584 EFSYS_LOCK(enp->en_eslp, state); 585 emrp = emip->emi_pending_req; 586 aborted = (emrp != NULL); 587 if (aborted) { 588 emip->emi_pending_req = NULL; 589 590 /* Error the request */ 591 emrp->emr_out_length_used = 0; 592 emrp->emr_rc = ETIMEDOUT; 593 594 /* Provide a credit for seqno/emr_pending_req mismatches */ 595 if (emip->emi_ev_cpl) 596 ++emip->emi_aborted; 597 598 /* 599 * The upper layer has called us, so we don't 600 * need to complete the request. 601 */ 602 } 603 EFSYS_UNLOCK(enp->en_eslp, state); 604 605 return (aborted); 606 } 607 608 __checkReturn efx_rc_t 609 efx_mcdi_request_errcode( 610 __in unsigned int err) 611 { 612 613 switch (err) { 614 /* MCDI v1 */ 615 case MC_CMD_ERR_EPERM: 616 return (EACCES); 617 case MC_CMD_ERR_ENOENT: 618 return (ENOENT); 619 case MC_CMD_ERR_EINTR: 620 return (EINTR); 621 case MC_CMD_ERR_EACCES: 622 return (EACCES); 623 case MC_CMD_ERR_EBUSY: 624 return (EBUSY); 625 case MC_CMD_ERR_EINVAL: 626 return (EINVAL); 627 case MC_CMD_ERR_EDEADLK: 628 return (EDEADLK); 629 case MC_CMD_ERR_ENOSYS: 630 return (ENOTSUP); 631 case MC_CMD_ERR_ETIME: 632 return (ETIMEDOUT); 633 case MC_CMD_ERR_ENOTSUP: 634 return (ENOTSUP); 635 case MC_CMD_ERR_EALREADY: 636 return (EALREADY); 637 638 /* MCDI v2 */ 639 case MC_CMD_ERR_EEXIST: 640 return (EEXIST); 641 #ifdef MC_CMD_ERR_EAGAIN 642 case MC_CMD_ERR_EAGAIN: 643 return (EAGAIN); 644 #endif 645 #ifdef MC_CMD_ERR_ENOSPC 646 case MC_CMD_ERR_ENOSPC: 647 return (ENOSPC); 648 #endif 649 650 case MC_CMD_ERR_ALLOC_FAIL: 651 return (ENOMEM); 652 case MC_CMD_ERR_NO_VADAPTOR: 653 return (ENOENT); 654 case MC_CMD_ERR_NO_EVB_PORT: 655 return (ENOENT); 656 case MC_CMD_ERR_NO_VSWITCH: 657 return (ENODEV); 658 case MC_CMD_ERR_VLAN_LIMIT: 659 return (EINVAL); 660 case MC_CMD_ERR_BAD_PCI_FUNC: 661 return (ENODEV); 662 case MC_CMD_ERR_BAD_VLAN_MODE: 663 return (EINVAL); 664 case MC_CMD_ERR_BAD_VSWITCH_TYPE: 665 return (EINVAL); 666 case MC_CMD_ERR_BAD_VPORT_TYPE: 667 return (EINVAL); 668 case MC_CMD_ERR_MAC_EXIST: 669 return (EEXIST); 670 671 case MC_CMD_ERR_PROXY_PENDING: 672 return (EAGAIN); 673 674 default: 675 EFSYS_PROBE1(mc_pcol_error, int, err); 676 return (EIO); 677 } 678 } 679 680 void 681 efx_mcdi_raise_exception( 682 __in efx_nic_t *enp, 683 __in_opt efx_mcdi_req_t *emrp, 684 __in int rc) 685 { 686 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 687 efx_mcdi_exception_t exception; 688 689 /* Reboot or Assertion failure only */ 690 EFSYS_ASSERT(rc == EIO || rc == EINTR); 691 692 /* 693 * If MC_CMD_REBOOT causes a reboot (dependent on parameters), 694 * then the EIO is not worthy of an exception. 695 */ 696 if (emrp != NULL && emrp->emr_cmd == MC_CMD_REBOOT && rc == EIO) 697 return; 698 699 exception = (rc == EIO) 700 ? EFX_MCDI_EXCEPTION_MC_REBOOT 701 : EFX_MCDI_EXCEPTION_MC_BADASSERT; 702 703 emtp->emt_exception(emtp->emt_context, exception); 704 } 705 706 void 707 efx_mcdi_execute( 708 __in efx_nic_t *enp, 709 __inout efx_mcdi_req_t *emrp) 710 { 711 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 712 713 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); 714 EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); 715 716 emrp->emr_quiet = B_FALSE; 717 emtp->emt_execute(emtp->emt_context, emrp); 718 } 719 720 void 721 efx_mcdi_execute_quiet( 722 __in efx_nic_t *enp, 723 __inout efx_mcdi_req_t *emrp) 724 { 725 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 726 727 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); 728 EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); 729 730 emrp->emr_quiet = B_TRUE; 731 emtp->emt_execute(emtp->emt_context, emrp); 732 } 733 734 void 735 efx_mcdi_ev_cpl( 736 __in efx_nic_t *enp, 737 __in unsigned int seq, 738 __in unsigned int outlen, 739 __in int errcode) 740 { 741 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 742 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 743 efx_mcdi_req_t *emrp; 744 int state; 745 746 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); 747 EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); 748 749 /* 750 * Serialise against efx_mcdi_request_poll()/efx_mcdi_request_start() 751 * when we're completing an aborted request. 752 */ 753 EFSYS_LOCK(enp->en_eslp, state); 754 if (emip->emi_pending_req == NULL || !emip->emi_ev_cpl || 755 (seq != ((emip->emi_seq - 1) & EFX_MASK32(MCDI_HEADER_SEQ)))) { 756 EFSYS_ASSERT(emip->emi_aborted > 0); 757 if (emip->emi_aborted > 0) 758 --emip->emi_aborted; 759 EFSYS_UNLOCK(enp->en_eslp, state); 760 return; 761 } 762 763 emrp = emip->emi_pending_req; 764 emip->emi_pending_req = NULL; 765 EFSYS_UNLOCK(enp->en_eslp, state); 766 767 if (emip->emi_max_version >= 2) { 768 /* MCDIv2 response details do not fit into an event. */ 769 efx_mcdi_read_response_header(enp, emrp); 770 } else { 771 if (errcode != 0) { 772 if (!emrp->emr_quiet) { 773 EFSYS_PROBE2(mcdi_err, int, emrp->emr_cmd, 774 int, errcode); 775 } 776 emrp->emr_out_length_used = 0; 777 emrp->emr_rc = efx_mcdi_request_errcode(errcode); 778 } else { 779 emrp->emr_out_length_used = outlen; 780 emrp->emr_rc = 0; 781 } 782 } 783 if (errcode == 0) { 784 efx_mcdi_finish_response(enp, emrp); 785 } 786 787 emtp->emt_ev_cpl(emtp->emt_context); 788 } 789 790 #if EFSYS_OPT_MCDI_PROXY_AUTH 791 792 __checkReturn efx_rc_t 793 efx_mcdi_get_proxy_handle( 794 __in efx_nic_t *enp, 795 __in efx_mcdi_req_t *emrp, 796 __out uint32_t *handlep) 797 { 798 efx_rc_t rc; 799 800 /* 801 * Return proxy handle from MCDI request that returned with error 802 * MC_MCD_ERR_PROXY_PENDING. This handle is used to wait for a matching 803 * PROXY_RESPONSE event. 804 */ 805 if ((emrp == NULL) || (handlep == NULL)) { 806 rc = EINVAL; 807 goto fail1; 808 } 809 if ((emrp->emr_rc != 0) && 810 (emrp->emr_err_code == MC_CMD_ERR_PROXY_PENDING)) { 811 *handlep = emrp->emr_proxy_handle; 812 rc = 0; 813 } else { 814 *handlep = 0; 815 rc = ENOENT; 816 } 817 return (rc); 818 819 fail1: 820 EFSYS_PROBE1(fail1, efx_rc_t, rc); 821 return (rc); 822 } 823 824 void 825 efx_mcdi_ev_proxy_response( 826 __in efx_nic_t *enp, 827 __in unsigned int handle, 828 __in unsigned int status) 829 { 830 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 831 efx_rc_t rc; 832 833 /* 834 * Handle results of an authorization request for a privileged MCDI 835 * command. If authorization was granted then we must re-issue the 836 * original MCDI request. If authorization failed or timed out, 837 * then the original MCDI request should be completed with the 838 * result code from this event. 839 */ 840 rc = (status == 0) ? 0 : efx_mcdi_request_errcode(status); 841 842 emtp->emt_ev_proxy_response(emtp->emt_context, handle, rc); 843 } 844 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH */ 845 846 void 847 efx_mcdi_ev_death( 848 __in efx_nic_t *enp, 849 __in int rc) 850 { 851 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 852 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 853 efx_mcdi_req_t *emrp = NULL; 854 boolean_t ev_cpl; 855 int state; 856 857 /* 858 * The MCDI request (if there is one) has been terminated, either 859 * by a BADASSERT or REBOOT event. 860 * 861 * If there is an outstanding event-completed MCDI operation, then we 862 * will never receive the completion event (because both MCDI 863 * completions and BADASSERT events are sent to the same evq). So 864 * complete this MCDI op. 865 * 866 * This function might run in parallel with efx_mcdi_request_poll() 867 * for poll completed mcdi requests, and also with 868 * efx_mcdi_request_start() for post-watchdog completions. 869 */ 870 EFSYS_LOCK(enp->en_eslp, state); 871 emrp = emip->emi_pending_req; 872 ev_cpl = emip->emi_ev_cpl; 873 if (emrp != NULL && emip->emi_ev_cpl) { 874 emip->emi_pending_req = NULL; 875 876 emrp->emr_out_length_used = 0; 877 emrp->emr_rc = rc; 878 ++emip->emi_aborted; 879 } 880 881 /* 882 * Since we're running in parallel with a request, consume the 883 * status word before dropping the lock. 884 */ 885 if (rc == EIO || rc == EINTR) { 886 EFSYS_SPIN(EFX_MCDI_STATUS_SLEEP_US); 887 (void) efx_mcdi_poll_reboot(enp); 888 emip->emi_new_epoch = B_TRUE; 889 } 890 891 EFSYS_UNLOCK(enp->en_eslp, state); 892 893 efx_mcdi_raise_exception(enp, emrp, rc); 894 895 if (emrp != NULL && ev_cpl) 896 emtp->emt_ev_cpl(emtp->emt_context); 897 } 898 899 __checkReturn efx_rc_t 900 efx_mcdi_version( 901 __in efx_nic_t *enp, 902 __out_ecount_opt(4) uint16_t versionp[4], 903 __out_opt uint32_t *buildp, 904 __out_opt efx_mcdi_boot_t *statusp) 905 { 906 efx_mcdi_req_t req; 907 uint8_t payload[MAX(MAX(MC_CMD_GET_VERSION_IN_LEN, 908 MC_CMD_GET_VERSION_OUT_LEN), 909 MAX(MC_CMD_GET_BOOT_STATUS_IN_LEN, 910 MC_CMD_GET_BOOT_STATUS_OUT_LEN))]; 911 efx_word_t *ver_words; 912 uint16_t version[4]; 913 uint32_t build; 914 efx_mcdi_boot_t status; 915 efx_rc_t rc; 916 917 EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); 918 919 (void) memset(payload, 0, sizeof (payload)); 920 req.emr_cmd = MC_CMD_GET_VERSION; 921 req.emr_in_buf = payload; 922 req.emr_in_length = MC_CMD_GET_VERSION_IN_LEN; 923 req.emr_out_buf = payload; 924 req.emr_out_length = MC_CMD_GET_VERSION_OUT_LEN; 925 926 efx_mcdi_execute(enp, &req); 927 928 if (req.emr_rc != 0) { 929 rc = req.emr_rc; 930 goto fail1; 931 } 932 933 /* bootrom support */ 934 if (req.emr_out_length_used == MC_CMD_GET_VERSION_V0_OUT_LEN) { 935 version[0] = version[1] = version[2] = version[3] = 0; 936 build = MCDI_OUT_DWORD(req, GET_VERSION_OUT_FIRMWARE); 937 938 goto version; 939 } 940 941 if (req.emr_out_length_used < MC_CMD_GET_VERSION_OUT_LEN) { 942 rc = EMSGSIZE; 943 goto fail2; 944 } 945 946 ver_words = MCDI_OUT2(req, efx_word_t, GET_VERSION_OUT_VERSION); 947 version[0] = EFX_WORD_FIELD(ver_words[0], EFX_WORD_0); 948 version[1] = EFX_WORD_FIELD(ver_words[1], EFX_WORD_0); 949 version[2] = EFX_WORD_FIELD(ver_words[2], EFX_WORD_0); 950 version[3] = EFX_WORD_FIELD(ver_words[3], EFX_WORD_0); 951 build = MCDI_OUT_DWORD(req, GET_VERSION_OUT_FIRMWARE); 952 953 version: 954 /* The bootrom doesn't understand BOOT_STATUS */ 955 if (MC_FW_VERSION_IS_BOOTLOADER(build)) { 956 status = EFX_MCDI_BOOT_ROM; 957 goto out; 958 } 959 960 (void) memset(payload, 0, sizeof (payload)); 961 req.emr_cmd = MC_CMD_GET_BOOT_STATUS; 962 req.emr_in_buf = payload; 963 req.emr_in_length = MC_CMD_GET_BOOT_STATUS_IN_LEN; 964 req.emr_out_buf = payload; 965 req.emr_out_length = MC_CMD_GET_BOOT_STATUS_OUT_LEN; 966 967 efx_mcdi_execute_quiet(enp, &req); 968 969 if (req.emr_rc == EACCES) { 970 /* Unprivileged functions cannot access BOOT_STATUS */ 971 status = EFX_MCDI_BOOT_PRIMARY; 972 version[0] = version[1] = version[2] = version[3] = 0; 973 build = 0; 974 goto out; 975 } 976 977 if (req.emr_rc != 0) { 978 rc = req.emr_rc; 979 goto fail3; 980 } 981 982 if (req.emr_out_length_used < MC_CMD_GET_BOOT_STATUS_OUT_LEN) { 983 rc = EMSGSIZE; 984 goto fail4; 985 } 986 987 if (MCDI_OUT_DWORD_FIELD(req, GET_BOOT_STATUS_OUT_FLAGS, 988 GET_BOOT_STATUS_OUT_FLAGS_PRIMARY)) 989 status = EFX_MCDI_BOOT_PRIMARY; 990 else 991 status = EFX_MCDI_BOOT_SECONDARY; 992 993 out: 994 if (versionp != NULL) 995 memcpy(versionp, version, sizeof (version)); 996 if (buildp != NULL) 997 *buildp = build; 998 if (statusp != NULL) 999 *statusp = status; 1000 1001 return (0); 1002 1003 fail4: 1004 EFSYS_PROBE(fail4); 1005 fail3: 1006 EFSYS_PROBE(fail3); 1007 fail2: 1008 EFSYS_PROBE(fail2); 1009 fail1: 1010 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1011 1012 return (rc); 1013 } 1014 1015 static __checkReturn efx_rc_t 1016 efx_mcdi_do_reboot( 1017 __in efx_nic_t *enp, 1018 __in boolean_t after_assertion) 1019 { 1020 uint8_t payload[MAX(MC_CMD_REBOOT_IN_LEN, MC_CMD_REBOOT_OUT_LEN)]; 1021 efx_mcdi_req_t req; 1022 efx_rc_t rc; 1023 1024 /* 1025 * We could require the caller to have caused en_mod_flags=0 to 1026 * call this function. This doesn't help the other port though, 1027 * who's about to get the MC ripped out from underneath them. 1028 * Since they have to cope with the subsequent fallout of MCDI 1029 * failures, we should as well. 1030 */ 1031 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1032 1033 (void) memset(payload, 0, sizeof (payload)); 1034 req.emr_cmd = MC_CMD_REBOOT; 1035 req.emr_in_buf = payload; 1036 req.emr_in_length = MC_CMD_REBOOT_IN_LEN; 1037 req.emr_out_buf = payload; 1038 req.emr_out_length = MC_CMD_REBOOT_OUT_LEN; 1039 1040 MCDI_IN_SET_DWORD(req, REBOOT_IN_FLAGS, 1041 (after_assertion ? MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION : 0)); 1042 1043 efx_mcdi_execute_quiet(enp, &req); 1044 1045 if (req.emr_rc == EACCES) { 1046 /* Unprivileged functions cannot reboot the MC. */ 1047 goto out; 1048 } 1049 1050 /* A successful reboot request returns EIO. */ 1051 if (req.emr_rc != 0 && req.emr_rc != EIO) { 1052 rc = req.emr_rc; 1053 goto fail1; 1054 } 1055 1056 out: 1057 return (0); 1058 1059 fail1: 1060 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1061 1062 return (rc); 1063 } 1064 1065 __checkReturn efx_rc_t 1066 efx_mcdi_reboot( 1067 __in efx_nic_t *enp) 1068 { 1069 return (efx_mcdi_do_reboot(enp, B_FALSE)); 1070 } 1071 1072 __checkReturn efx_rc_t 1073 efx_mcdi_exit_assertion_handler( 1074 __in efx_nic_t *enp) 1075 { 1076 return (efx_mcdi_do_reboot(enp, B_TRUE)); 1077 } 1078 1079 __checkReturn efx_rc_t 1080 efx_mcdi_read_assertion( 1081 __in efx_nic_t *enp) 1082 { 1083 efx_mcdi_req_t req; 1084 uint8_t payload[MAX(MC_CMD_GET_ASSERTS_IN_LEN, 1085 MC_CMD_GET_ASSERTS_OUT_LEN)]; 1086 const char *reason; 1087 unsigned int flags; 1088 unsigned int index; 1089 unsigned int ofst; 1090 int retry; 1091 efx_rc_t rc; 1092 1093 /* 1094 * Before we attempt to chat to the MC, we should verify that the MC 1095 * isn't in it's assertion handler, either due to a previous reboot, 1096 * or because we're reinitializing due to an eec_exception(). 1097 * 1098 * Use GET_ASSERTS to read any assertion state that may be present. 1099 * Retry this command twice. Once because a boot-time assertion failure 1100 * might cause the 1st MCDI request to fail. And once again because 1101 * we might race with efx_mcdi_exit_assertion_handler() running on 1102 * partner port(s) on the same NIC. 1103 */ 1104 retry = 2; 1105 do { 1106 (void) memset(payload, 0, sizeof (payload)); 1107 req.emr_cmd = MC_CMD_GET_ASSERTS; 1108 req.emr_in_buf = payload; 1109 req.emr_in_length = MC_CMD_GET_ASSERTS_IN_LEN; 1110 req.emr_out_buf = payload; 1111 req.emr_out_length = MC_CMD_GET_ASSERTS_OUT_LEN; 1112 1113 MCDI_IN_SET_DWORD(req, GET_ASSERTS_IN_CLEAR, 1); 1114 efx_mcdi_execute_quiet(enp, &req); 1115 1116 } while ((req.emr_rc == EINTR || req.emr_rc == EIO) && retry-- > 0); 1117 1118 if (req.emr_rc != 0) { 1119 if (req.emr_rc == EACCES) { 1120 /* Unprivileged functions cannot clear assertions. */ 1121 goto out; 1122 } 1123 rc = req.emr_rc; 1124 goto fail1; 1125 } 1126 1127 if (req.emr_out_length_used < MC_CMD_GET_ASSERTS_OUT_LEN) { 1128 rc = EMSGSIZE; 1129 goto fail2; 1130 } 1131 1132 /* Print out any assertion state recorded */ 1133 flags = MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_GLOBAL_FLAGS); 1134 if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS) 1135 return (0); 1136 1137 reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL) 1138 ? "system-level assertion" 1139 : (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL) 1140 ? "thread-level assertion" 1141 : (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED) 1142 ? "watchdog reset" 1143 : (flags == MC_CMD_GET_ASSERTS_FLAGS_ADDR_TRAP) 1144 ? "illegal address trap" 1145 : "unknown assertion"; 1146 EFSYS_PROBE3(mcpu_assertion, 1147 const char *, reason, unsigned int, 1148 MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_SAVED_PC_OFFS), 1149 unsigned int, 1150 MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_THREAD_OFFS)); 1151 1152 /* Print out the registers (r1 ... r31) */ 1153 ofst = MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST; 1154 for (index = 1; 1155 index < 1 + MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_NUM; 1156 index++) { 1157 EFSYS_PROBE2(mcpu_register, unsigned int, index, unsigned int, 1158 EFX_DWORD_FIELD(*MCDI_OUT(req, efx_dword_t, ofst), 1159 EFX_DWORD_0)); 1160 ofst += sizeof (efx_dword_t); 1161 } 1162 EFSYS_ASSERT(ofst <= MC_CMD_GET_ASSERTS_OUT_LEN); 1163 1164 out: 1165 return (0); 1166 1167 fail2: 1168 EFSYS_PROBE(fail2); 1169 fail1: 1170 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1171 1172 return (rc); 1173 } 1174 1175 1176 /* 1177 * Internal routines for for specific MCDI requests. 1178 */ 1179 1180 __checkReturn efx_rc_t 1181 efx_mcdi_drv_attach( 1182 __in efx_nic_t *enp, 1183 __in boolean_t attach) 1184 { 1185 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1186 efx_mcdi_req_t req; 1187 uint8_t payload[MAX(MC_CMD_DRV_ATTACH_IN_LEN, 1188 MC_CMD_DRV_ATTACH_EXT_OUT_LEN)]; 1189 uint32_t flags; 1190 efx_rc_t rc; 1191 1192 (void) memset(payload, 0, sizeof (payload)); 1193 req.emr_cmd = MC_CMD_DRV_ATTACH; 1194 req.emr_in_buf = payload; 1195 req.emr_in_length = MC_CMD_DRV_ATTACH_IN_LEN; 1196 req.emr_out_buf = payload; 1197 req.emr_out_length = MC_CMD_DRV_ATTACH_EXT_OUT_LEN; 1198 1199 /* 1200 * Use DONT_CARE for the datapath firmware type to ensure that the 1201 * driver can attach to an unprivileged function. The datapath firmware 1202 * type to use is controlled by the 'sfboot' utility. 1203 */ 1204 MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_NEW_STATE, attach ? 1 : 0); 1205 MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_UPDATE, 1); 1206 MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_FIRMWARE_ID, MC_CMD_FW_DONT_CARE); 1207 1208 efx_mcdi_execute(enp, &req); 1209 1210 if (req.emr_rc != 0) { 1211 rc = req.emr_rc; 1212 goto fail1; 1213 } 1214 1215 if (req.emr_out_length_used < MC_CMD_DRV_ATTACH_OUT_LEN) { 1216 rc = EMSGSIZE; 1217 goto fail2; 1218 } 1219 1220 if (attach == B_FALSE) { 1221 flags = 0; 1222 } else if (enp->en_family == EFX_FAMILY_SIENA) { 1223 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 1224 1225 /* Create synthetic privileges for Siena functions */ 1226 flags = EFX_NIC_FUNC_LINKCTRL | EFX_NIC_FUNC_TRUSTED; 1227 if (emip->emi_port == 1) 1228 flags |= EFX_NIC_FUNC_PRIMARY; 1229 } else { 1230 EFX_STATIC_ASSERT(EFX_NIC_FUNC_PRIMARY == 1231 (1u << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY)); 1232 EFX_STATIC_ASSERT(EFX_NIC_FUNC_LINKCTRL == 1233 (1u << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL)); 1234 EFX_STATIC_ASSERT(EFX_NIC_FUNC_TRUSTED == 1235 (1u << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_TRUSTED)); 1236 1237 /* Save function privilege flags (EF10 and later) */ 1238 if (req.emr_out_length_used < MC_CMD_DRV_ATTACH_EXT_OUT_LEN) { 1239 rc = EMSGSIZE; 1240 goto fail3; 1241 } 1242 flags = MCDI_OUT_DWORD(req, DRV_ATTACH_EXT_OUT_FUNC_FLAGS); 1243 } 1244 encp->enc_func_flags = flags; 1245 1246 return (0); 1247 1248 fail3: 1249 EFSYS_PROBE(fail3); 1250 fail2: 1251 EFSYS_PROBE(fail2); 1252 fail1: 1253 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1254 1255 return (rc); 1256 } 1257 1258 __checkReturn efx_rc_t 1259 efx_mcdi_get_board_cfg( 1260 __in efx_nic_t *enp, 1261 __out_opt uint32_t *board_typep, 1262 __out_opt efx_dword_t *capabilitiesp, 1263 __out_ecount_opt(6) uint8_t mac_addrp[6]) 1264 { 1265 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 1266 efx_mcdi_req_t req; 1267 uint8_t payload[MAX(MC_CMD_GET_BOARD_CFG_IN_LEN, 1268 MC_CMD_GET_BOARD_CFG_OUT_LENMIN)]; 1269 efx_rc_t rc; 1270 1271 (void) memset(payload, 0, sizeof (payload)); 1272 req.emr_cmd = MC_CMD_GET_BOARD_CFG; 1273 req.emr_in_buf = payload; 1274 req.emr_in_length = MC_CMD_GET_BOARD_CFG_IN_LEN; 1275 req.emr_out_buf = payload; 1276 req.emr_out_length = MC_CMD_GET_BOARD_CFG_OUT_LENMIN; 1277 1278 efx_mcdi_execute(enp, &req); 1279 1280 if (req.emr_rc != 0) { 1281 rc = req.emr_rc; 1282 goto fail1; 1283 } 1284 1285 if (req.emr_out_length_used < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) { 1286 rc = EMSGSIZE; 1287 goto fail2; 1288 } 1289 1290 if (mac_addrp != NULL) { 1291 uint8_t *addrp; 1292 1293 if (emip->emi_port == 1) { 1294 addrp = MCDI_OUT2(req, uint8_t, 1295 GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0); 1296 } else if (emip->emi_port == 2) { 1297 addrp = MCDI_OUT2(req, uint8_t, 1298 GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1); 1299 } else { 1300 rc = EINVAL; 1301 goto fail3; 1302 } 1303 1304 EFX_MAC_ADDR_COPY(mac_addrp, addrp); 1305 } 1306 1307 if (capabilitiesp != NULL) { 1308 if (emip->emi_port == 1) { 1309 *capabilitiesp = *MCDI_OUT2(req, efx_dword_t, 1310 GET_BOARD_CFG_OUT_CAPABILITIES_PORT0); 1311 } else if (emip->emi_port == 2) { 1312 *capabilitiesp = *MCDI_OUT2(req, efx_dword_t, 1313 GET_BOARD_CFG_OUT_CAPABILITIES_PORT1); 1314 } else { 1315 rc = EINVAL; 1316 goto fail4; 1317 } 1318 } 1319 1320 if (board_typep != NULL) { 1321 *board_typep = MCDI_OUT_DWORD(req, 1322 GET_BOARD_CFG_OUT_BOARD_TYPE); 1323 } 1324 1325 return (0); 1326 1327 fail4: 1328 EFSYS_PROBE(fail4); 1329 fail3: 1330 EFSYS_PROBE(fail3); 1331 fail2: 1332 EFSYS_PROBE(fail2); 1333 fail1: 1334 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1335 1336 return (rc); 1337 } 1338 1339 __checkReturn efx_rc_t 1340 efx_mcdi_get_resource_limits( 1341 __in efx_nic_t *enp, 1342 __out_opt uint32_t *nevqp, 1343 __out_opt uint32_t *nrxqp, 1344 __out_opt uint32_t *ntxqp) 1345 { 1346 efx_mcdi_req_t req; 1347 uint8_t payload[MAX(MC_CMD_GET_RESOURCE_LIMITS_IN_LEN, 1348 MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN)]; 1349 efx_rc_t rc; 1350 1351 (void) memset(payload, 0, sizeof (payload)); 1352 req.emr_cmd = MC_CMD_GET_RESOURCE_LIMITS; 1353 req.emr_in_buf = payload; 1354 req.emr_in_length = MC_CMD_GET_RESOURCE_LIMITS_IN_LEN; 1355 req.emr_out_buf = payload; 1356 req.emr_out_length = MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN; 1357 1358 efx_mcdi_execute(enp, &req); 1359 1360 if (req.emr_rc != 0) { 1361 rc = req.emr_rc; 1362 goto fail1; 1363 } 1364 1365 if (req.emr_out_length_used < MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN) { 1366 rc = EMSGSIZE; 1367 goto fail2; 1368 } 1369 1370 if (nevqp != NULL) 1371 *nevqp = MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_EVQ); 1372 if (nrxqp != NULL) 1373 *nrxqp = MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_RXQ); 1374 if (ntxqp != NULL) 1375 *ntxqp = MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_TXQ); 1376 1377 return (0); 1378 1379 fail2: 1380 EFSYS_PROBE(fail2); 1381 fail1: 1382 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1383 1384 return (rc); 1385 } 1386 1387 __checkReturn efx_rc_t 1388 efx_mcdi_get_phy_cfg( 1389 __in efx_nic_t *enp) 1390 { 1391 efx_port_t *epp = &(enp->en_port); 1392 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1393 efx_mcdi_req_t req; 1394 uint8_t payload[MAX(MC_CMD_GET_PHY_CFG_IN_LEN, 1395 MC_CMD_GET_PHY_CFG_OUT_LEN)]; 1396 efx_rc_t rc; 1397 1398 (void) memset(payload, 0, sizeof (payload)); 1399 req.emr_cmd = MC_CMD_GET_PHY_CFG; 1400 req.emr_in_buf = payload; 1401 req.emr_in_length = MC_CMD_GET_PHY_CFG_IN_LEN; 1402 req.emr_out_buf = payload; 1403 req.emr_out_length = MC_CMD_GET_PHY_CFG_OUT_LEN; 1404 1405 efx_mcdi_execute(enp, &req); 1406 1407 if (req.emr_rc != 0) { 1408 rc = req.emr_rc; 1409 goto fail1; 1410 } 1411 1412 if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN) { 1413 rc = EMSGSIZE; 1414 goto fail2; 1415 } 1416 1417 encp->enc_phy_type = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_TYPE); 1418 #if EFSYS_OPT_NAMES 1419 (void) strncpy(encp->enc_phy_name, 1420 MCDI_OUT2(req, char, GET_PHY_CFG_OUT_NAME), 1421 MIN(sizeof (encp->enc_phy_name) - 1, 1422 MC_CMD_GET_PHY_CFG_OUT_NAME_LEN)); 1423 #endif /* EFSYS_OPT_NAMES */ 1424 (void) memset(encp->enc_phy_revision, 0, 1425 sizeof (encp->enc_phy_revision)); 1426 memcpy(encp->enc_phy_revision, 1427 MCDI_OUT2(req, char, GET_PHY_CFG_OUT_REVISION), 1428 MIN(sizeof (encp->enc_phy_revision) - 1, 1429 MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN)); 1430 #if EFSYS_OPT_PHY_LED_CONTROL 1431 encp->enc_led_mask = ((1 << EFX_PHY_LED_DEFAULT) | 1432 (1 << EFX_PHY_LED_OFF) | 1433 (1 << EFX_PHY_LED_ON)); 1434 #endif /* EFSYS_OPT_PHY_LED_CONTROL */ 1435 1436 /* Get the media type of the fixed port, if recognised. */ 1437 EFX_STATIC_ASSERT(MC_CMD_MEDIA_XAUI == EFX_PHY_MEDIA_XAUI); 1438 EFX_STATIC_ASSERT(MC_CMD_MEDIA_CX4 == EFX_PHY_MEDIA_CX4); 1439 EFX_STATIC_ASSERT(MC_CMD_MEDIA_KX4 == EFX_PHY_MEDIA_KX4); 1440 EFX_STATIC_ASSERT(MC_CMD_MEDIA_XFP == EFX_PHY_MEDIA_XFP); 1441 EFX_STATIC_ASSERT(MC_CMD_MEDIA_SFP_PLUS == EFX_PHY_MEDIA_SFP_PLUS); 1442 EFX_STATIC_ASSERT(MC_CMD_MEDIA_BASE_T == EFX_PHY_MEDIA_BASE_T); 1443 EFX_STATIC_ASSERT(MC_CMD_MEDIA_QSFP_PLUS == EFX_PHY_MEDIA_QSFP_PLUS); 1444 epp->ep_fixed_port_type = 1445 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_MEDIA_TYPE); 1446 if (epp->ep_fixed_port_type >= EFX_PHY_MEDIA_NTYPES) 1447 epp->ep_fixed_port_type = EFX_PHY_MEDIA_INVALID; 1448 1449 epp->ep_phy_cap_mask = 1450 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_SUPPORTED_CAP); 1451 #if EFSYS_OPT_PHY_FLAGS 1452 encp->enc_phy_flags_mask = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_FLAGS); 1453 #endif /* EFSYS_OPT_PHY_FLAGS */ 1454 1455 encp->enc_port = (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_PRT); 1456 1457 /* Populate internal state */ 1458 encp->enc_mcdi_mdio_channel = 1459 (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_CHANNEL); 1460 1461 #if EFSYS_OPT_PHY_STATS 1462 encp->enc_mcdi_phy_stat_mask = 1463 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_STATS_MASK); 1464 #endif /* EFSYS_OPT_PHY_STATS */ 1465 1466 #if EFSYS_OPT_BIST 1467 encp->enc_bist_mask = 0; 1468 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 1469 GET_PHY_CFG_OUT_BIST_CABLE_SHORT)) 1470 encp->enc_bist_mask |= (1 << EFX_BIST_TYPE_PHY_CABLE_SHORT); 1471 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 1472 GET_PHY_CFG_OUT_BIST_CABLE_LONG)) 1473 encp->enc_bist_mask |= (1 << EFX_BIST_TYPE_PHY_CABLE_LONG); 1474 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 1475 GET_PHY_CFG_OUT_BIST)) 1476 encp->enc_bist_mask |= (1 << EFX_BIST_TYPE_PHY_NORMAL); 1477 #endif /* EFSYS_OPT_BIST */ 1478 1479 return (0); 1480 1481 fail2: 1482 EFSYS_PROBE(fail2); 1483 fail1: 1484 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1485 1486 return (rc); 1487 } 1488 1489 __checkReturn efx_rc_t 1490 efx_mcdi_firmware_update_supported( 1491 __in efx_nic_t *enp, 1492 __out boolean_t *supportedp) 1493 { 1494 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 1495 efx_rc_t rc; 1496 1497 if (emcop != NULL) { 1498 if ((rc = emcop->emco_feature_supported(enp, 1499 EFX_MCDI_FEATURE_FW_UPDATE, supportedp)) != 0) 1500 goto fail1; 1501 } else { 1502 /* Earlier devices always supported updates */ 1503 *supportedp = B_TRUE; 1504 } 1505 1506 return (0); 1507 1508 fail1: 1509 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1510 1511 return (rc); 1512 } 1513 1514 __checkReturn efx_rc_t 1515 efx_mcdi_macaddr_change_supported( 1516 __in efx_nic_t *enp, 1517 __out boolean_t *supportedp) 1518 { 1519 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 1520 efx_rc_t rc; 1521 1522 if (emcop != NULL) { 1523 if ((rc = emcop->emco_feature_supported(enp, 1524 EFX_MCDI_FEATURE_MACADDR_CHANGE, supportedp)) != 0) 1525 goto fail1; 1526 } else { 1527 /* Earlier devices always supported MAC changes */ 1528 *supportedp = B_TRUE; 1529 } 1530 1531 return (0); 1532 1533 fail1: 1534 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1535 1536 return (rc); 1537 } 1538 1539 __checkReturn efx_rc_t 1540 efx_mcdi_link_control_supported( 1541 __in efx_nic_t *enp, 1542 __out boolean_t *supportedp) 1543 { 1544 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 1545 efx_rc_t rc; 1546 1547 if (emcop != NULL) { 1548 if ((rc = emcop->emco_feature_supported(enp, 1549 EFX_MCDI_FEATURE_LINK_CONTROL, supportedp)) != 0) 1550 goto fail1; 1551 } else { 1552 /* Earlier devices always supported link control */ 1553 *supportedp = B_TRUE; 1554 } 1555 1556 return (0); 1557 1558 fail1: 1559 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1560 1561 return (rc); 1562 } 1563 1564 __checkReturn efx_rc_t 1565 efx_mcdi_mac_spoofing_supported( 1566 __in efx_nic_t *enp, 1567 __out boolean_t *supportedp) 1568 { 1569 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 1570 efx_rc_t rc; 1571 1572 if (emcop != NULL) { 1573 if ((rc = emcop->emco_feature_supported(enp, 1574 EFX_MCDI_FEATURE_MAC_SPOOFING, supportedp)) != 0) 1575 goto fail1; 1576 } else { 1577 /* Earlier devices always supported MAC spoofing */ 1578 *supportedp = B_TRUE; 1579 } 1580 1581 return (0); 1582 1583 fail1: 1584 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1585 1586 return (rc); 1587 } 1588 1589 #if EFSYS_OPT_BIST 1590 1591 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 1592 /* 1593 * Enter bist offline mode. This is a fw mode which puts the NIC into a state 1594 * where memory BIST tests can be run and not much else can interfere or happen. 1595 * A reboot is required to exit this mode. 1596 */ 1597 __checkReturn efx_rc_t 1598 efx_mcdi_bist_enable_offline( 1599 __in efx_nic_t *enp) 1600 { 1601 efx_mcdi_req_t req; 1602 efx_rc_t rc; 1603 1604 EFX_STATIC_ASSERT(MC_CMD_ENABLE_OFFLINE_BIST_IN_LEN == 0); 1605 EFX_STATIC_ASSERT(MC_CMD_ENABLE_OFFLINE_BIST_OUT_LEN == 0); 1606 1607 req.emr_cmd = MC_CMD_ENABLE_OFFLINE_BIST; 1608 req.emr_in_buf = NULL; 1609 req.emr_in_length = 0; 1610 req.emr_out_buf = NULL; 1611 req.emr_out_length = 0; 1612 1613 efx_mcdi_execute(enp, &req); 1614 1615 if (req.emr_rc != 0) { 1616 rc = req.emr_rc; 1617 goto fail1; 1618 } 1619 1620 return (0); 1621 1622 fail1: 1623 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1624 1625 return (rc); 1626 } 1627 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 1628 1629 __checkReturn efx_rc_t 1630 efx_mcdi_bist_start( 1631 __in efx_nic_t *enp, 1632 __in efx_bist_type_t type) 1633 { 1634 efx_mcdi_req_t req; 1635 uint8_t payload[MAX(MC_CMD_START_BIST_IN_LEN, 1636 MC_CMD_START_BIST_OUT_LEN)]; 1637 efx_rc_t rc; 1638 1639 (void) memset(payload, 0, sizeof (payload)); 1640 req.emr_cmd = MC_CMD_START_BIST; 1641 req.emr_in_buf = payload; 1642 req.emr_in_length = MC_CMD_START_BIST_IN_LEN; 1643 req.emr_out_buf = payload; 1644 req.emr_out_length = MC_CMD_START_BIST_OUT_LEN; 1645 1646 switch (type) { 1647 case EFX_BIST_TYPE_PHY_NORMAL: 1648 MCDI_IN_SET_DWORD(req, START_BIST_IN_TYPE, MC_CMD_PHY_BIST); 1649 break; 1650 case EFX_BIST_TYPE_PHY_CABLE_SHORT: 1651 MCDI_IN_SET_DWORD(req, START_BIST_IN_TYPE, 1652 MC_CMD_PHY_BIST_CABLE_SHORT); 1653 break; 1654 case EFX_BIST_TYPE_PHY_CABLE_LONG: 1655 MCDI_IN_SET_DWORD(req, START_BIST_IN_TYPE, 1656 MC_CMD_PHY_BIST_CABLE_LONG); 1657 break; 1658 case EFX_BIST_TYPE_MC_MEM: 1659 MCDI_IN_SET_DWORD(req, START_BIST_IN_TYPE, 1660 MC_CMD_MC_MEM_BIST); 1661 break; 1662 case EFX_BIST_TYPE_SAT_MEM: 1663 MCDI_IN_SET_DWORD(req, START_BIST_IN_TYPE, 1664 MC_CMD_PORT_MEM_BIST); 1665 break; 1666 case EFX_BIST_TYPE_REG: 1667 MCDI_IN_SET_DWORD(req, START_BIST_IN_TYPE, 1668 MC_CMD_REG_BIST); 1669 break; 1670 default: 1671 EFSYS_ASSERT(0); 1672 } 1673 1674 efx_mcdi_execute(enp, &req); 1675 1676 if (req.emr_rc != 0) { 1677 rc = req.emr_rc; 1678 goto fail1; 1679 } 1680 1681 return (0); 1682 1683 fail1: 1684 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1685 1686 return (rc); 1687 } 1688 1689 #endif /* EFSYS_OPT_BIST */ 1690 1691 1692 /* Enable logging of some events (e.g. link state changes) */ 1693 __checkReturn efx_rc_t 1694 efx_mcdi_log_ctrl( 1695 __in efx_nic_t *enp) 1696 { 1697 efx_mcdi_req_t req; 1698 uint8_t payload[MAX(MC_CMD_LOG_CTRL_IN_LEN, 1699 MC_CMD_LOG_CTRL_OUT_LEN)]; 1700 efx_rc_t rc; 1701 1702 (void) memset(payload, 0, sizeof (payload)); 1703 req.emr_cmd = MC_CMD_LOG_CTRL; 1704 req.emr_in_buf = payload; 1705 req.emr_in_length = MC_CMD_LOG_CTRL_IN_LEN; 1706 req.emr_out_buf = payload; 1707 req.emr_out_length = MC_CMD_LOG_CTRL_OUT_LEN; 1708 1709 MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST, 1710 MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ); 1711 MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST_EVQ, 0); 1712 1713 efx_mcdi_execute(enp, &req); 1714 1715 if (req.emr_rc != 0) { 1716 rc = req.emr_rc; 1717 goto fail1; 1718 } 1719 1720 return (0); 1721 1722 fail1: 1723 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1724 1725 return (rc); 1726 } 1727 1728 1729 #if EFSYS_OPT_MAC_STATS 1730 1731 typedef enum efx_stats_action_e 1732 { 1733 EFX_STATS_CLEAR, 1734 EFX_STATS_UPLOAD, 1735 EFX_STATS_ENABLE_NOEVENTS, 1736 EFX_STATS_ENABLE_EVENTS, 1737 EFX_STATS_DISABLE, 1738 } efx_stats_action_t; 1739 1740 static __checkReturn efx_rc_t 1741 efx_mcdi_mac_stats( 1742 __in efx_nic_t *enp, 1743 __in_opt efsys_mem_t *esmp, 1744 __in efx_stats_action_t action) 1745 { 1746 efx_mcdi_req_t req; 1747 uint8_t payload[MAX(MC_CMD_MAC_STATS_IN_LEN, 1748 MC_CMD_MAC_STATS_OUT_DMA_LEN)]; 1749 int clear = (action == EFX_STATS_CLEAR); 1750 int upload = (action == EFX_STATS_UPLOAD); 1751 int enable = (action == EFX_STATS_ENABLE_NOEVENTS); 1752 int events = (action == EFX_STATS_ENABLE_EVENTS); 1753 int disable = (action == EFX_STATS_DISABLE); 1754 efx_rc_t rc; 1755 1756 (void) memset(payload, 0, sizeof (payload)); 1757 req.emr_cmd = MC_CMD_MAC_STATS; 1758 req.emr_in_buf = payload; 1759 req.emr_in_length = MC_CMD_MAC_STATS_IN_LEN; 1760 req.emr_out_buf = payload; 1761 req.emr_out_length = MC_CMD_MAC_STATS_OUT_DMA_LEN; 1762 1763 MCDI_IN_POPULATE_DWORD_6(req, MAC_STATS_IN_CMD, 1764 MAC_STATS_IN_DMA, upload, 1765 MAC_STATS_IN_CLEAR, clear, 1766 MAC_STATS_IN_PERIODIC_CHANGE, enable | events | disable, 1767 MAC_STATS_IN_PERIODIC_ENABLE, enable | events, 1768 MAC_STATS_IN_PERIODIC_NOEVENT, !events, 1769 MAC_STATS_IN_PERIOD_MS, (enable | events) ? 1000: 0); 1770 1771 if (esmp != NULL) { 1772 int bytes = MC_CMD_MAC_NSTATS * sizeof (uint64_t); 1773 1774 EFX_STATIC_ASSERT(MC_CMD_MAC_NSTATS * sizeof (uint64_t) <= 1775 EFX_MAC_STATS_SIZE); 1776 1777 MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_ADDR_LO, 1778 EFSYS_MEM_ADDR(esmp) & 0xffffffff); 1779 MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_ADDR_HI, 1780 EFSYS_MEM_ADDR(esmp) >> 32); 1781 MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_LEN, bytes); 1782 } else { 1783 EFSYS_ASSERT(!upload && !enable && !events); 1784 } 1785 1786 /* 1787 * NOTE: Do not use EVB_PORT_ID_ASSIGNED when disabling periodic stats, 1788 * as this may fail (and leave periodic DMA enabled) if the 1789 * vadapter has already been deleted. 1790 */ 1791 MCDI_IN_SET_DWORD(req, MAC_STATS_IN_PORT_ID, 1792 (disable ? EVB_PORT_ID_NULL : enp->en_vport_id)); 1793 1794 efx_mcdi_execute(enp, &req); 1795 1796 if (req.emr_rc != 0) { 1797 /* EF10: Expect ENOENT if no DMA queues are initialised */ 1798 if ((req.emr_rc != ENOENT) || 1799 (enp->en_rx_qcount + enp->en_tx_qcount != 0)) { 1800 rc = req.emr_rc; 1801 goto fail1; 1802 } 1803 } 1804 1805 return (0); 1806 1807 fail1: 1808 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1809 1810 return (rc); 1811 } 1812 1813 __checkReturn efx_rc_t 1814 efx_mcdi_mac_stats_clear( 1815 __in efx_nic_t *enp) 1816 { 1817 efx_rc_t rc; 1818 1819 if ((rc = efx_mcdi_mac_stats(enp, NULL, EFX_STATS_CLEAR)) != 0) 1820 goto fail1; 1821 1822 return (0); 1823 1824 fail1: 1825 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1826 1827 return (rc); 1828 } 1829 1830 __checkReturn efx_rc_t 1831 efx_mcdi_mac_stats_upload( 1832 __in efx_nic_t *enp, 1833 __in efsys_mem_t *esmp) 1834 { 1835 efx_rc_t rc; 1836 1837 /* 1838 * The MC DMAs aggregate statistics for our convenience, so we can 1839 * avoid having to pull the statistics buffer into the cache to 1840 * maintain cumulative statistics. 1841 */ 1842 if ((rc = efx_mcdi_mac_stats(enp, esmp, EFX_STATS_UPLOAD)) != 0) 1843 goto fail1; 1844 1845 return (0); 1846 1847 fail1: 1848 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1849 1850 return (rc); 1851 } 1852 1853 __checkReturn efx_rc_t 1854 efx_mcdi_mac_stats_periodic( 1855 __in efx_nic_t *enp, 1856 __in efsys_mem_t *esmp, 1857 __in uint16_t period, 1858 __in boolean_t events) 1859 { 1860 efx_rc_t rc; 1861 1862 /* 1863 * The MC DMAs aggregate statistics for our convenience, so we can 1864 * avoid having to pull the statistics buffer into the cache to 1865 * maintain cumulative statistics. 1866 * Huntington uses a fixed 1sec period, so use that on Siena too. 1867 */ 1868 if (period == 0) 1869 rc = efx_mcdi_mac_stats(enp, NULL, EFX_STATS_DISABLE); 1870 else if (events) 1871 rc = efx_mcdi_mac_stats(enp, esmp, EFX_STATS_ENABLE_EVENTS); 1872 else 1873 rc = efx_mcdi_mac_stats(enp, esmp, EFX_STATS_ENABLE_NOEVENTS); 1874 1875 if (rc != 0) 1876 goto fail1; 1877 1878 return (0); 1879 1880 fail1: 1881 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1882 1883 return (rc); 1884 } 1885 1886 #endif /* EFSYS_OPT_MAC_STATS */ 1887 1888 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 1889 1890 /* 1891 * This function returns the pf and vf number of a function. If it is a pf the 1892 * vf number is 0xffff. The vf number is the index of the vf on that 1893 * function. So if you have 3 vfs on pf 0 the 3 vfs will return (pf=0,vf=0), 1894 * (pf=0,vf=1), (pf=0,vf=2) aand the pf will return (pf=0, vf=0xffff). 1895 */ 1896 __checkReturn efx_rc_t 1897 efx_mcdi_get_function_info( 1898 __in efx_nic_t *enp, 1899 __out uint32_t *pfp, 1900 __out_opt uint32_t *vfp) 1901 { 1902 efx_mcdi_req_t req; 1903 uint8_t payload[MAX(MC_CMD_GET_FUNCTION_INFO_IN_LEN, 1904 MC_CMD_GET_FUNCTION_INFO_OUT_LEN)]; 1905 efx_rc_t rc; 1906 1907 (void) memset(payload, 0, sizeof (payload)); 1908 req.emr_cmd = MC_CMD_GET_FUNCTION_INFO; 1909 req.emr_in_buf = payload; 1910 req.emr_in_length = MC_CMD_GET_FUNCTION_INFO_IN_LEN; 1911 req.emr_out_buf = payload; 1912 req.emr_out_length = MC_CMD_GET_FUNCTION_INFO_OUT_LEN; 1913 1914 efx_mcdi_execute(enp, &req); 1915 1916 if (req.emr_rc != 0) { 1917 rc = req.emr_rc; 1918 goto fail1; 1919 } 1920 1921 if (req.emr_out_length_used < MC_CMD_GET_FUNCTION_INFO_OUT_LEN) { 1922 rc = EMSGSIZE; 1923 goto fail2; 1924 } 1925 1926 *pfp = MCDI_OUT_DWORD(req, GET_FUNCTION_INFO_OUT_PF); 1927 if (vfp != NULL) 1928 *vfp = MCDI_OUT_DWORD(req, GET_FUNCTION_INFO_OUT_VF); 1929 1930 return (0); 1931 1932 fail2: 1933 EFSYS_PROBE(fail2); 1934 fail1: 1935 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1936 1937 return (rc); 1938 } 1939 1940 __checkReturn efx_rc_t 1941 efx_mcdi_privilege_mask( 1942 __in efx_nic_t *enp, 1943 __in uint32_t pf, 1944 __in uint32_t vf, 1945 __out uint32_t *maskp) 1946 { 1947 efx_mcdi_req_t req; 1948 uint8_t payload[MAX(MC_CMD_PRIVILEGE_MASK_IN_LEN, 1949 MC_CMD_PRIVILEGE_MASK_OUT_LEN)]; 1950 efx_rc_t rc; 1951 1952 (void) memset(payload, 0, sizeof (payload)); 1953 req.emr_cmd = MC_CMD_PRIVILEGE_MASK; 1954 req.emr_in_buf = payload; 1955 req.emr_in_length = MC_CMD_PRIVILEGE_MASK_IN_LEN; 1956 req.emr_out_buf = payload; 1957 req.emr_out_length = MC_CMD_PRIVILEGE_MASK_OUT_LEN; 1958 1959 MCDI_IN_POPULATE_DWORD_2(req, PRIVILEGE_MASK_IN_FUNCTION, 1960 PRIVILEGE_MASK_IN_FUNCTION_PF, pf, 1961 PRIVILEGE_MASK_IN_FUNCTION_VF, vf); 1962 1963 efx_mcdi_execute(enp, &req); 1964 1965 if (req.emr_rc != 0) { 1966 rc = req.emr_rc; 1967 goto fail1; 1968 } 1969 1970 if (req.emr_out_length_used < MC_CMD_PRIVILEGE_MASK_OUT_LEN) { 1971 rc = EMSGSIZE; 1972 goto fail2; 1973 } 1974 1975 *maskp = MCDI_OUT_DWORD(req, PRIVILEGE_MASK_OUT_OLD_MASK); 1976 1977 return (0); 1978 1979 fail2: 1980 EFSYS_PROBE(fail2); 1981 fail1: 1982 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1983 1984 return (rc); 1985 } 1986 1987 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 1988 1989 __checkReturn efx_rc_t 1990 efx_mcdi_set_workaround( 1991 __in efx_nic_t *enp, 1992 __in uint32_t type, 1993 __in boolean_t enabled, 1994 __out_opt uint32_t *flagsp) 1995 { 1996 efx_mcdi_req_t req; 1997 uint8_t payload[MAX(MC_CMD_WORKAROUND_IN_LEN, 1998 MC_CMD_WORKAROUND_EXT_OUT_LEN)]; 1999 efx_rc_t rc; 2000 2001 (void) memset(payload, 0, sizeof (payload)); 2002 req.emr_cmd = MC_CMD_WORKAROUND; 2003 req.emr_in_buf = payload; 2004 req.emr_in_length = MC_CMD_WORKAROUND_IN_LEN; 2005 req.emr_out_buf = payload; 2006 req.emr_out_length = MC_CMD_WORKAROUND_OUT_LEN; 2007 2008 MCDI_IN_SET_DWORD(req, WORKAROUND_IN_TYPE, type); 2009 MCDI_IN_SET_DWORD(req, WORKAROUND_IN_ENABLED, enabled ? 1 : 0); 2010 2011 efx_mcdi_execute_quiet(enp, &req); 2012 2013 if (req.emr_rc != 0) { 2014 rc = req.emr_rc; 2015 goto fail1; 2016 } 2017 2018 if (flagsp != NULL) { 2019 if (req.emr_out_length_used >= MC_CMD_WORKAROUND_EXT_OUT_LEN) 2020 *flagsp = MCDI_OUT_DWORD(req, WORKAROUND_EXT_OUT_FLAGS); 2021 else 2022 *flagsp = 0; 2023 } 2024 2025 return (0); 2026 2027 fail1: 2028 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2029 2030 return (rc); 2031 } 2032 2033 2034 __checkReturn efx_rc_t 2035 efx_mcdi_get_workarounds( 2036 __in efx_nic_t *enp, 2037 __out_opt uint32_t *implementedp, 2038 __out_opt uint32_t *enabledp) 2039 { 2040 efx_mcdi_req_t req; 2041 uint8_t payload[MC_CMD_GET_WORKAROUNDS_OUT_LEN]; 2042 efx_rc_t rc; 2043 2044 (void) memset(payload, 0, sizeof (payload)); 2045 req.emr_cmd = MC_CMD_GET_WORKAROUNDS; 2046 req.emr_in_buf = NULL; 2047 req.emr_in_length = 0; 2048 req.emr_out_buf = payload; 2049 req.emr_out_length = MC_CMD_GET_WORKAROUNDS_OUT_LEN; 2050 2051 efx_mcdi_execute(enp, &req); 2052 2053 if (req.emr_rc != 0) { 2054 rc = req.emr_rc; 2055 goto fail1; 2056 } 2057 2058 if (implementedp != NULL) { 2059 *implementedp = 2060 MCDI_OUT_DWORD(req, GET_WORKAROUNDS_OUT_IMPLEMENTED); 2061 } 2062 2063 if (enabledp != NULL) { 2064 *enabledp = MCDI_OUT_DWORD(req, GET_WORKAROUNDS_OUT_ENABLED); 2065 } 2066 2067 return (0); 2068 2069 fail1: 2070 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2071 2072 return (rc); 2073 } 2074 2075 /* 2076 * Size of media information page in accordance with SFF-8472 and SFF-8436. 2077 * It is used in MCDI interface as well. 2078 */ 2079 #define EFX_PHY_MEDIA_INFO_PAGE_SIZE 0x80 2080 2081 static __checkReturn efx_rc_t 2082 efx_mcdi_get_phy_media_info( 2083 __in efx_nic_t *enp, 2084 __in uint32_t mcdi_page, 2085 __in uint8_t offset, 2086 __in uint8_t len, 2087 __out_bcount(len) uint8_t *data) 2088 { 2089 efx_mcdi_req_t req; 2090 uint8_t payload[MAX(MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN, 2091 MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN( 2092 EFX_PHY_MEDIA_INFO_PAGE_SIZE))]; 2093 efx_rc_t rc; 2094 2095 EFSYS_ASSERT((uint32_t)offset + len <= EFX_PHY_MEDIA_INFO_PAGE_SIZE); 2096 2097 (void) memset(payload, 0, sizeof (payload)); 2098 req.emr_cmd = MC_CMD_GET_PHY_MEDIA_INFO; 2099 req.emr_in_buf = payload; 2100 req.emr_in_length = MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN; 2101 req.emr_out_buf = payload; 2102 req.emr_out_length = 2103 MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(EFX_PHY_MEDIA_INFO_PAGE_SIZE); 2104 2105 MCDI_IN_SET_DWORD(req, GET_PHY_MEDIA_INFO_IN_PAGE, mcdi_page); 2106 2107 efx_mcdi_execute(enp, &req); 2108 2109 if (req.emr_rc != 0) { 2110 rc = req.emr_rc; 2111 goto fail1; 2112 } 2113 2114 if (req.emr_out_length_used != 2115 MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(EFX_PHY_MEDIA_INFO_PAGE_SIZE)) { 2116 rc = EMSGSIZE; 2117 goto fail2; 2118 } 2119 2120 if (MCDI_OUT_DWORD(req, GET_PHY_MEDIA_INFO_OUT_DATALEN) != 2121 EFX_PHY_MEDIA_INFO_PAGE_SIZE) { 2122 rc = EIO; 2123 goto fail3; 2124 } 2125 2126 memcpy(data, 2127 MCDI_OUT2(req, uint8_t, GET_PHY_MEDIA_INFO_OUT_DATA) + offset, 2128 len); 2129 2130 return (0); 2131 2132 fail3: 2133 EFSYS_PROBE(fail3); 2134 fail2: 2135 EFSYS_PROBE(fail2); 2136 fail1: 2137 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2138 2139 return (rc); 2140 } 2141 2142 /* 2143 * 2-wire device address of the base information in accordance with SFF-8472 2144 * Diagnostic Monitoring Interface for Optical Transceivers section 2145 * 4 Memory Organization. 2146 */ 2147 #define EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_BASE 0xA0 2148 2149 /* 2150 * 2-wire device address of the digital diagnostics monitoring interface 2151 * in accordance with SFF-8472 Diagnostic Monitoring Interface for Optical 2152 * Transceivers section 4 Memory Organization. 2153 */ 2154 #define EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_DDM 0xA2 2155 2156 /* 2157 * Hard wired 2-wire device address for QSFP+ in accordance with SFF-8436 2158 * QSFP+ 10 Gbs 4X PLUGGABLE TRANSCEIVER section 7.4 Device Addressing and 2159 * Operation. 2160 */ 2161 #define EFX_PHY_MEDIA_INFO_DEV_ADDR_QSFP 0xA0 2162 2163 __checkReturn efx_rc_t 2164 efx_mcdi_phy_module_get_info( 2165 __in efx_nic_t *enp, 2166 __in uint8_t dev_addr, 2167 __in uint8_t offset, 2168 __in uint8_t len, 2169 __out_bcount(len) uint8_t *data) 2170 { 2171 efx_port_t *epp = &(enp->en_port); 2172 efx_rc_t rc; 2173 uint32_t mcdi_lower_page; 2174 uint32_t mcdi_upper_page; 2175 2176 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 2177 2178 /* 2179 * Map device address to MC_CMD_GET_PHY_MEDIA_INFO pages. 2180 * Offset plus length interface allows to access page 0 only. 2181 * I.e. non-zero upper pages are not accessible. 2182 * See SFF-8472 section 4 Memory Organization and SFF-8436 section 7.6 2183 * QSFP+ Memory Map for details on how information is structured 2184 * and accessible. 2185 */ 2186 switch (epp->ep_fixed_port_type) { 2187 case EFX_PHY_MEDIA_SFP_PLUS: 2188 /* 2189 * In accordance with SFF-8472 Diagnostic Monitoring 2190 * Interface for Optical Transceivers section 4 Memory 2191 * Organization two 2-wire addresses are defined. 2192 */ 2193 switch (dev_addr) { 2194 /* Base information */ 2195 case EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_BASE: 2196 /* 2197 * MCDI page 0 should be used to access lower 2198 * page 0 (0x00 - 0x7f) at the device address 0xA0. 2199 */ 2200 mcdi_lower_page = 0; 2201 /* 2202 * MCDI page 1 should be used to access upper 2203 * page 0 (0x80 - 0xff) at the device address 0xA0. 2204 */ 2205 mcdi_upper_page = 1; 2206 break; 2207 /* Diagnostics */ 2208 case EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_DDM: 2209 /* 2210 * MCDI page 2 should be used to access lower 2211 * page 0 (0x00 - 0x7f) at the device address 0xA2. 2212 */ 2213 mcdi_lower_page = 2; 2214 /* 2215 * MCDI page 3 should be used to access upper 2216 * page 0 (0x80 - 0xff) at the device address 0xA2. 2217 */ 2218 mcdi_upper_page = 3; 2219 break; 2220 default: 2221 rc = ENOTSUP; 2222 goto fail1; 2223 } 2224 break; 2225 case EFX_PHY_MEDIA_QSFP_PLUS: 2226 switch (dev_addr) { 2227 case EFX_PHY_MEDIA_INFO_DEV_ADDR_QSFP: 2228 /* 2229 * MCDI page -1 should be used to access lower page 0 2230 * (0x00 - 0x7f). 2231 */ 2232 mcdi_lower_page = (uint32_t)-1; 2233 /* 2234 * MCDI page 0 should be used to access upper page 0 2235 * (0x80h - 0xff). 2236 */ 2237 mcdi_upper_page = 0; 2238 break; 2239 default: 2240 rc = ENOTSUP; 2241 goto fail1; 2242 } 2243 break; 2244 default: 2245 rc = ENOTSUP; 2246 goto fail1; 2247 } 2248 2249 if (offset < EFX_PHY_MEDIA_INFO_PAGE_SIZE) { 2250 uint8_t read_len = 2251 MIN(len, EFX_PHY_MEDIA_INFO_PAGE_SIZE - offset); 2252 2253 rc = efx_mcdi_get_phy_media_info(enp, 2254 mcdi_lower_page, offset, read_len, data); 2255 if (rc != 0) 2256 goto fail2; 2257 2258 data += read_len; 2259 len -= read_len; 2260 2261 offset = 0; 2262 } else { 2263 offset -= EFX_PHY_MEDIA_INFO_PAGE_SIZE; 2264 } 2265 2266 if (len > 0) { 2267 EFSYS_ASSERT3U(len, <=, EFX_PHY_MEDIA_INFO_PAGE_SIZE); 2268 EFSYS_ASSERT3U(offset, <, EFX_PHY_MEDIA_INFO_PAGE_SIZE); 2269 2270 rc = efx_mcdi_get_phy_media_info(enp, 2271 mcdi_upper_page, offset, len, data); 2272 if (rc != 0) 2273 goto fail3; 2274 } 2275 2276 return (0); 2277 2278 fail3: 2279 EFSYS_PROBE(fail3); 2280 fail2: 2281 EFSYS_PROBE(fail2); 2282 fail1: 2283 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2284 2285 return (rc); 2286 } 2287 2288 #endif /* EFSYS_OPT_MCDI */ 2289