1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright(c) 2019-2020 Xilinx, Inc. 4 * Copyright(c) 2008-2019 Solarflare Communications Inc. 5 */ 6 7 #include "efx.h" 8 #include "efx_impl.h" 9 10 #if EFSYS_OPT_MCDI 11 12 /* 13 * There are three versions of the MCDI interface: 14 * - MCDIv0: Siena BootROM. Transport uses MCDIv1 headers. 15 * - MCDIv1: Siena firmware and Huntington BootROM. 16 * - MCDIv2: EF10 firmware (Huntington/Medford) and Medford BootROM. 17 * Transport uses MCDIv2 headers. 18 * 19 * MCDIv2 Header NOT_EPOCH flag 20 * ---------------------------- 21 * A new epoch begins at initial startup or after an MC reboot, and defines when 22 * the MC should reject stale MCDI requests. 23 * 24 * The first MCDI request sent by the host should contain NOT_EPOCH=0, and all 25 * subsequent requests (until the next MC reboot) should contain NOT_EPOCH=1. 26 * 27 * After rebooting the MC will fail all requests with NOT_EPOCH=1 by writing a 28 * response with ERROR=1 and DATALEN=0 until a request is seen with NOT_EPOCH=0. 29 */ 30 31 32 33 #if EFSYS_OPT_SIENA 34 35 static const efx_mcdi_ops_t __efx_mcdi_siena_ops = { 36 siena_mcdi_init, /* emco_init */ 37 siena_mcdi_send_request, /* emco_send_request */ 38 siena_mcdi_poll_reboot, /* emco_poll_reboot */ 39 siena_mcdi_poll_response, /* emco_poll_response */ 40 siena_mcdi_read_response, /* emco_read_response */ 41 siena_mcdi_fini, /* emco_fini */ 42 siena_mcdi_feature_supported, /* emco_feature_supported */ 43 siena_mcdi_get_timeout, /* emco_get_timeout */ 44 }; 45 46 #endif /* EFSYS_OPT_SIENA */ 47 48 #if EFX_OPTS_EF10() 49 50 static const efx_mcdi_ops_t __efx_mcdi_ef10_ops = { 51 ef10_mcdi_init, /* emco_init */ 52 ef10_mcdi_send_request, /* emco_send_request */ 53 ef10_mcdi_poll_reboot, /* emco_poll_reboot */ 54 ef10_mcdi_poll_response, /* emco_poll_response */ 55 ef10_mcdi_read_response, /* emco_read_response */ 56 ef10_mcdi_fini, /* emco_fini */ 57 ef10_mcdi_feature_supported, /* emco_feature_supported */ 58 ef10_mcdi_get_timeout, /* emco_get_timeout */ 59 }; 60 61 #endif /* EFX_OPTS_EF10() */ 62 63 #if EFSYS_OPT_RIVERHEAD 64 65 static const efx_mcdi_ops_t __efx_mcdi_rhead_ops = { 66 ef10_mcdi_init, /* emco_init */ 67 ef10_mcdi_send_request, /* emco_send_request */ 68 ef10_mcdi_poll_reboot, /* emco_poll_reboot */ 69 ef10_mcdi_poll_response, /* emco_poll_response */ 70 ef10_mcdi_read_response, /* emco_read_response */ 71 ef10_mcdi_fini, /* emco_fini */ 72 ef10_mcdi_feature_supported, /* emco_feature_supported */ 73 ef10_mcdi_get_timeout, /* emco_get_timeout */ 74 }; 75 76 #endif /* EFSYS_OPT_RIVERHEAD */ 77 78 79 80 __checkReturn efx_rc_t 81 efx_mcdi_init( 82 __in efx_nic_t *enp, 83 __in const efx_mcdi_transport_t *emtp) 84 { 85 const efx_mcdi_ops_t *emcop; 86 efx_rc_t rc; 87 88 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 89 EFSYS_ASSERT3U(enp->en_mod_flags, ==, 0); 90 91 switch (enp->en_family) { 92 #if EFSYS_OPT_SIENA 93 case EFX_FAMILY_SIENA: 94 emcop = &__efx_mcdi_siena_ops; 95 break; 96 #endif /* EFSYS_OPT_SIENA */ 97 98 #if EFSYS_OPT_HUNTINGTON 99 case EFX_FAMILY_HUNTINGTON: 100 emcop = &__efx_mcdi_ef10_ops; 101 break; 102 #endif /* EFSYS_OPT_HUNTINGTON */ 103 104 #if EFSYS_OPT_MEDFORD 105 case EFX_FAMILY_MEDFORD: 106 emcop = &__efx_mcdi_ef10_ops; 107 break; 108 #endif /* EFSYS_OPT_MEDFORD */ 109 110 #if EFSYS_OPT_MEDFORD2 111 case EFX_FAMILY_MEDFORD2: 112 emcop = &__efx_mcdi_ef10_ops; 113 break; 114 #endif /* EFSYS_OPT_MEDFORD2 */ 115 116 #if EFSYS_OPT_RIVERHEAD 117 case EFX_FAMILY_RIVERHEAD: 118 emcop = &__efx_mcdi_rhead_ops; 119 break; 120 #endif /* EFSYS_OPT_RIVERHEAD */ 121 122 default: 123 EFSYS_ASSERT(0); 124 rc = ENOTSUP; 125 goto fail1; 126 } 127 128 if (enp->en_features & EFX_FEATURE_MCDI_DMA) { 129 /* MCDI requires a DMA buffer in host memory */ 130 if ((emtp == NULL) || (emtp->emt_dma_mem) == NULL) { 131 rc = EINVAL; 132 goto fail2; 133 } 134 } 135 enp->en_mcdi.em_emtp = emtp; 136 137 if (emcop != NULL && emcop->emco_init != NULL) { 138 if ((rc = emcop->emco_init(enp, emtp)) != 0) 139 goto fail3; 140 } 141 142 enp->en_mcdi.em_emcop = emcop; 143 enp->en_mod_flags |= EFX_MOD_MCDI; 144 145 return (0); 146 147 fail3: 148 EFSYS_PROBE(fail3); 149 fail2: 150 EFSYS_PROBE(fail2); 151 fail1: 152 EFSYS_PROBE1(fail1, efx_rc_t, rc); 153 154 enp->en_mcdi.em_emcop = NULL; 155 enp->en_mcdi.em_emtp = NULL; 156 enp->en_mod_flags &= ~EFX_MOD_MCDI; 157 158 return (rc); 159 } 160 161 void 162 efx_mcdi_fini( 163 __in efx_nic_t *enp) 164 { 165 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 166 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 167 168 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 169 EFSYS_ASSERT3U(enp->en_mod_flags, ==, EFX_MOD_MCDI); 170 171 if (emcop != NULL && emcop->emco_fini != NULL) 172 emcop->emco_fini(enp); 173 174 emip->emi_port = 0; 175 emip->emi_aborted = 0; 176 177 enp->en_mcdi.em_emcop = NULL; 178 enp->en_mod_flags &= ~EFX_MOD_MCDI; 179 } 180 181 void 182 efx_mcdi_new_epoch( 183 __in efx_nic_t *enp) 184 { 185 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 186 efsys_lock_state_t state; 187 188 /* Start a new epoch (allow fresh MCDI requests to succeed) */ 189 EFSYS_LOCK(enp->en_eslp, state); 190 emip->emi_new_epoch = B_TRUE; 191 EFSYS_UNLOCK(enp->en_eslp, state); 192 } 193 194 static void 195 efx_mcdi_send_request( 196 __in efx_nic_t *enp, 197 __in void *hdrp, 198 __in size_t hdr_len, 199 __in void *sdup, 200 __in size_t sdu_len) 201 { 202 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 203 204 emcop->emco_send_request(enp, hdrp, hdr_len, sdup, sdu_len); 205 } 206 207 static efx_rc_t 208 efx_mcdi_poll_reboot( 209 __in efx_nic_t *enp) 210 { 211 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 212 efx_rc_t rc; 213 214 rc = emcop->emco_poll_reboot(enp); 215 return (rc); 216 } 217 218 static boolean_t 219 efx_mcdi_poll_response( 220 __in efx_nic_t *enp) 221 { 222 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 223 boolean_t available; 224 225 available = emcop->emco_poll_response(enp); 226 return (available); 227 } 228 229 static void 230 efx_mcdi_read_response( 231 __in efx_nic_t *enp, 232 __out void *bufferp, 233 __in size_t offset, 234 __in size_t length) 235 { 236 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 237 238 emcop->emco_read_response(enp, bufferp, offset, length); 239 } 240 241 void 242 efx_mcdi_request_start( 243 __in efx_nic_t *enp, 244 __in efx_mcdi_req_t *emrp, 245 __in boolean_t ev_cpl) 246 { 247 #if EFSYS_OPT_MCDI_LOGGING 248 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 249 #endif 250 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 251 efx_dword_t hdr[2]; 252 size_t hdr_len; 253 unsigned int max_version; 254 unsigned int seq; 255 unsigned int xflags; 256 boolean_t new_epoch; 257 efsys_lock_state_t state; 258 259 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 260 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); 261 EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); 262 263 /* 264 * efx_mcdi_request_start() is naturally serialised against both 265 * efx_mcdi_request_poll() and efx_mcdi_ev_cpl()/efx_mcdi_ev_death(), 266 * by virtue of there only being one outstanding MCDI request. 267 * Unfortunately, upper layers may also call efx_mcdi_request_abort() 268 * at any time, to timeout a pending mcdi request, That request may 269 * then subsequently complete, meaning efx_mcdi_ev_cpl() or 270 * efx_mcdi_ev_death() may end up running in parallel with 271 * efx_mcdi_request_start(). This race is handled by ensuring that 272 * %emi_pending_req, %emi_ev_cpl and %emi_seq are protected by the 273 * en_eslp lock. 274 */ 275 EFSYS_LOCK(enp->en_eslp, state); 276 EFSYS_ASSERT(emip->emi_pending_req == NULL); 277 emip->emi_pending_req = emrp; 278 emip->emi_ev_cpl = ev_cpl; 279 emip->emi_poll_cnt = 0; 280 seq = emip->emi_seq++ & EFX_MASK32(MCDI_HEADER_SEQ); 281 new_epoch = emip->emi_new_epoch; 282 max_version = emip->emi_max_version; 283 EFSYS_UNLOCK(enp->en_eslp, state); 284 285 xflags = 0; 286 if (ev_cpl) 287 xflags |= MCDI_HEADER_XFLAGS_EVREQ; 288 289 /* 290 * Huntington firmware supports MCDIv2, but the Huntington BootROM only 291 * supports MCDIv1. Use MCDIv1 headers for MCDIv1 commands where 292 * possible to support this. 293 */ 294 if ((max_version >= 2) && 295 ((emrp->emr_cmd > MC_CMD_CMD_SPACE_ESCAPE_7) || 296 (emrp->emr_in_length > MCDI_CTL_SDU_LEN_MAX_V1) || 297 (emrp->emr_out_length > MCDI_CTL_SDU_LEN_MAX_V1))) { 298 /* Construct MCDI v2 header */ 299 hdr_len = sizeof (hdr); 300 EFX_POPULATE_DWORD_8(hdr[0], 301 MCDI_HEADER_CODE, MC_CMD_V2_EXTN, 302 MCDI_HEADER_RESYNC, 1, 303 MCDI_HEADER_DATALEN, 0, 304 MCDI_HEADER_SEQ, seq, 305 MCDI_HEADER_NOT_EPOCH, new_epoch ? 0 : 1, 306 MCDI_HEADER_ERROR, 0, 307 MCDI_HEADER_RESPONSE, 0, 308 MCDI_HEADER_XFLAGS, xflags); 309 310 EFX_POPULATE_DWORD_2(hdr[1], 311 MC_CMD_V2_EXTN_IN_EXTENDED_CMD, emrp->emr_cmd, 312 MC_CMD_V2_EXTN_IN_ACTUAL_LEN, emrp->emr_in_length); 313 } else { 314 /* Construct MCDI v1 header */ 315 hdr_len = sizeof (hdr[0]); 316 EFX_POPULATE_DWORD_8(hdr[0], 317 MCDI_HEADER_CODE, emrp->emr_cmd, 318 MCDI_HEADER_RESYNC, 1, 319 MCDI_HEADER_DATALEN, emrp->emr_in_length, 320 MCDI_HEADER_SEQ, seq, 321 MCDI_HEADER_NOT_EPOCH, new_epoch ? 0 : 1, 322 MCDI_HEADER_ERROR, 0, 323 MCDI_HEADER_RESPONSE, 0, 324 MCDI_HEADER_XFLAGS, xflags); 325 } 326 327 #if EFSYS_OPT_MCDI_LOGGING 328 if (emtp->emt_logger != NULL) { 329 emtp->emt_logger(emtp->emt_context, EFX_LOG_MCDI_REQUEST, 330 &hdr[0], hdr_len, 331 emrp->emr_in_buf, emrp->emr_in_length); 332 } 333 #endif /* EFSYS_OPT_MCDI_LOGGING */ 334 335 efx_mcdi_send_request(enp, &hdr[0], hdr_len, 336 emrp->emr_in_buf, emrp->emr_in_length); 337 } 338 339 340 static void 341 efx_mcdi_read_response_header( 342 __in efx_nic_t *enp, 343 __inout efx_mcdi_req_t *emrp) 344 { 345 #if EFSYS_OPT_MCDI_LOGGING 346 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 347 #endif /* EFSYS_OPT_MCDI_LOGGING */ 348 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 349 efx_dword_t hdr[2]; 350 unsigned int hdr_len; 351 unsigned int data_len; 352 unsigned int seq; 353 unsigned int cmd; 354 unsigned int error; 355 efx_rc_t rc; 356 357 EFSYS_ASSERT(emrp != NULL); 358 359 efx_mcdi_read_response(enp, &hdr[0], 0, sizeof (hdr[0])); 360 hdr_len = sizeof (hdr[0]); 361 362 cmd = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE); 363 seq = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_SEQ); 364 error = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_ERROR); 365 366 if (cmd != MC_CMD_V2_EXTN) { 367 data_len = EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_DATALEN); 368 } else { 369 efx_mcdi_read_response(enp, &hdr[1], hdr_len, sizeof (hdr[1])); 370 hdr_len += sizeof (hdr[1]); 371 372 cmd = EFX_DWORD_FIELD(hdr[1], MC_CMD_V2_EXTN_IN_EXTENDED_CMD); 373 data_len = 374 EFX_DWORD_FIELD(hdr[1], MC_CMD_V2_EXTN_IN_ACTUAL_LEN); 375 } 376 377 if (error && (data_len == 0)) { 378 /* The MC has rebooted since the request was sent. */ 379 EFSYS_SPIN(EFX_MCDI_STATUS_SLEEP_US); 380 efx_mcdi_poll_reboot(enp); 381 rc = EIO; 382 goto fail1; 383 } 384 #if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER 385 if (((cmd != emrp->emr_cmd) && (emrp->emr_cmd != MC_CMD_PROXY_CMD)) || 386 #else 387 if ((cmd != emrp->emr_cmd) || 388 #endif 389 (seq != ((emip->emi_seq - 1) & EFX_MASK32(MCDI_HEADER_SEQ)))) { 390 /* Response is for a different request */ 391 rc = EIO; 392 goto fail2; 393 } 394 if (error) { 395 efx_dword_t err[2]; 396 unsigned int err_len = MIN(data_len, sizeof (err)); 397 int err_code = MC_CMD_ERR_EPROTO; 398 int err_arg = 0; 399 400 /* Read error code (and arg num for MCDI v2 commands) */ 401 efx_mcdi_read_response(enp, &err, hdr_len, err_len); 402 403 if (err_len >= (MC_CMD_ERR_CODE_OFST + sizeof (efx_dword_t))) 404 err_code = EFX_DWORD_FIELD(err[0], EFX_DWORD_0); 405 #ifdef WITH_MCDI_V2 406 if (err_len >= (MC_CMD_ERR_ARG_OFST + sizeof (efx_dword_t))) 407 err_arg = EFX_DWORD_FIELD(err[1], EFX_DWORD_0); 408 #endif 409 emrp->emr_err_code = err_code; 410 emrp->emr_err_arg = err_arg; 411 412 #if EFSYS_OPT_MCDI_PROXY_AUTH 413 if ((err_code == MC_CMD_ERR_PROXY_PENDING) && 414 (err_len == sizeof (err))) { 415 /* 416 * The MCDI request would normally fail with EPERM, but 417 * firmware has forwarded it to an authorization agent 418 * attached to a privileged PF. 419 * 420 * Save the authorization request handle. The client 421 * must wait for a PROXY_RESPONSE event, or timeout. 422 */ 423 emrp->emr_proxy_handle = err_arg; 424 } 425 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH */ 426 427 #if EFSYS_OPT_MCDI_LOGGING 428 if (emtp->emt_logger != NULL) { 429 emtp->emt_logger(emtp->emt_context, 430 EFX_LOG_MCDI_RESPONSE, 431 &hdr[0], hdr_len, 432 &err[0], err_len); 433 } 434 #endif /* EFSYS_OPT_MCDI_LOGGING */ 435 436 if (!emrp->emr_quiet) { 437 EFSYS_PROBE3(mcdi_err_arg, int, emrp->emr_cmd, 438 int, err_code, int, err_arg); 439 } 440 441 rc = efx_mcdi_request_errcode(err_code); 442 goto fail3; 443 } 444 445 emrp->emr_rc = 0; 446 emrp->emr_out_length_used = data_len; 447 #if EFSYS_OPT_MCDI_PROXY_AUTH 448 emrp->emr_proxy_handle = 0; 449 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH */ 450 return; 451 452 fail3: 453 fail2: 454 fail1: 455 emrp->emr_rc = rc; 456 emrp->emr_out_length_used = 0; 457 } 458 459 static void 460 efx_mcdi_finish_response( 461 __in efx_nic_t *enp, 462 __in efx_mcdi_req_t *emrp) 463 { 464 #if EFSYS_OPT_MCDI_LOGGING 465 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 466 #endif /* EFSYS_OPT_MCDI_LOGGING */ 467 efx_dword_t hdr[2]; 468 unsigned int hdr_len; 469 size_t bytes; 470 unsigned int resp_off; 471 #if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER 472 unsigned int resp_cmd; 473 boolean_t proxied_cmd_resp = B_FALSE; 474 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */ 475 476 if (emrp->emr_out_buf == NULL) 477 return; 478 479 /* Read the command header to detect MCDI response format */ 480 hdr_len = sizeof (hdr[0]); 481 efx_mcdi_read_response(enp, &hdr[0], 0, hdr_len); 482 if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE) == MC_CMD_V2_EXTN) { 483 /* 484 * Read the actual payload length. The length given in the event 485 * is only correct for responses with the V1 format. 486 */ 487 efx_mcdi_read_response(enp, &hdr[1], hdr_len, sizeof (hdr[1])); 488 hdr_len += sizeof (hdr[1]); 489 resp_off = hdr_len; 490 491 emrp->emr_out_length_used = EFX_DWORD_FIELD(hdr[1], 492 MC_CMD_V2_EXTN_IN_ACTUAL_LEN); 493 #if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER 494 /* 495 * A proxy MCDI command is executed by PF on behalf of 496 * one of its VFs. The command to be proxied follows 497 * immediately afterward in the host buffer. 498 * PROXY_CMD inner call complete response should be copied to 499 * output buffer so that it can be returned to the requesting 500 * function in MC_CMD_PROXY_COMPLETE payload. 501 */ 502 resp_cmd = 503 EFX_DWORD_FIELD(hdr[1], MC_CMD_V2_EXTN_IN_EXTENDED_CMD); 504 proxied_cmd_resp = ((emrp->emr_cmd == MC_CMD_PROXY_CMD) && 505 (resp_cmd != MC_CMD_PROXY_CMD)); 506 if (proxied_cmd_resp) { 507 resp_off = 0; 508 emrp->emr_out_length_used += hdr_len; 509 } 510 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */ 511 } else { 512 resp_off = hdr_len; 513 } 514 515 /* Copy payload out into caller supplied buffer */ 516 bytes = MIN(emrp->emr_out_length_used, emrp->emr_out_length); 517 efx_mcdi_read_response(enp, emrp->emr_out_buf, resp_off, bytes); 518 519 #if EFSYS_OPT_MCDI_LOGGING 520 if (emtp->emt_logger != NULL) { 521 emtp->emt_logger(emtp->emt_context, 522 EFX_LOG_MCDI_RESPONSE, 523 &hdr[0], hdr_len, 524 emrp->emr_out_buf, bytes); 525 } 526 #endif /* EFSYS_OPT_MCDI_LOGGING */ 527 } 528 529 530 __checkReturn boolean_t 531 efx_mcdi_request_poll( 532 __in efx_nic_t *enp) 533 { 534 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 535 efx_mcdi_req_t *emrp; 536 efsys_lock_state_t state; 537 efx_rc_t rc; 538 539 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 540 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); 541 EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); 542 543 /* Serialise against post-watchdog efx_mcdi_ev* */ 544 EFSYS_LOCK(enp->en_eslp, state); 545 546 EFSYS_ASSERT(emip->emi_pending_req != NULL); 547 EFSYS_ASSERT(!emip->emi_ev_cpl); 548 emrp = emip->emi_pending_req; 549 550 /* Check if hardware is unavailable */ 551 if (efx_nic_hw_unavailable(enp)) { 552 EFSYS_UNLOCK(enp->en_eslp, state); 553 return (B_FALSE); 554 } 555 556 /* Check for reboot atomically w.r.t efx_mcdi_request_start */ 557 if (emip->emi_poll_cnt++ == 0) { 558 if ((rc = efx_mcdi_poll_reboot(enp)) != 0) { 559 emip->emi_pending_req = NULL; 560 EFSYS_UNLOCK(enp->en_eslp, state); 561 562 /* Reboot/Assertion */ 563 if (rc == EIO || rc == EINTR) 564 efx_mcdi_raise_exception(enp, emrp, rc); 565 566 goto fail1; 567 } 568 } 569 570 /* Check if a response is available */ 571 if (efx_mcdi_poll_response(enp) == B_FALSE) { 572 EFSYS_UNLOCK(enp->en_eslp, state); 573 return (B_FALSE); 574 } 575 576 /* Read the response header */ 577 efx_mcdi_read_response_header(enp, emrp); 578 579 /* Request complete */ 580 emip->emi_pending_req = NULL; 581 582 /* Ensure stale MCDI requests fail after an MC reboot. */ 583 emip->emi_new_epoch = B_FALSE; 584 585 EFSYS_UNLOCK(enp->en_eslp, state); 586 587 if ((rc = emrp->emr_rc) != 0) 588 goto fail2; 589 590 efx_mcdi_finish_response(enp, emrp); 591 return (B_TRUE); 592 593 fail2: 594 if (!emrp->emr_quiet) 595 EFSYS_PROBE(fail2); 596 fail1: 597 if (!emrp->emr_quiet) 598 EFSYS_PROBE1(fail1, efx_rc_t, rc); 599 600 return (B_TRUE); 601 } 602 603 __checkReturn boolean_t 604 efx_mcdi_request_abort( 605 __in efx_nic_t *enp) 606 { 607 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 608 efx_mcdi_req_t *emrp; 609 boolean_t aborted; 610 efsys_lock_state_t state; 611 612 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 613 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); 614 EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); 615 616 /* 617 * efx_mcdi_ev_* may have already completed this event, and be 618 * spinning/blocked on the upper layer lock. So it *is* legitimate 619 * to for emi_pending_req to be NULL. If there is a pending event 620 * completed request, then provide a "credit" to allow 621 * efx_mcdi_ev_cpl() to accept a single spurious completion. 622 */ 623 EFSYS_LOCK(enp->en_eslp, state); 624 emrp = emip->emi_pending_req; 625 aborted = (emrp != NULL); 626 if (aborted) { 627 emip->emi_pending_req = NULL; 628 629 /* Error the request */ 630 emrp->emr_out_length_used = 0; 631 emrp->emr_rc = ETIMEDOUT; 632 633 /* Provide a credit for seqno/emr_pending_req mismatches */ 634 if (emip->emi_ev_cpl) 635 ++emip->emi_aborted; 636 637 /* 638 * The upper layer has called us, so we don't 639 * need to complete the request. 640 */ 641 } 642 EFSYS_UNLOCK(enp->en_eslp, state); 643 644 return (aborted); 645 } 646 647 void 648 efx_mcdi_get_timeout( 649 __in efx_nic_t *enp, 650 __in efx_mcdi_req_t *emrp, 651 __out uint32_t *timeoutp) 652 { 653 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 654 655 emcop->emco_get_timeout(enp, emrp, timeoutp); 656 } 657 658 __checkReturn efx_rc_t 659 efx_mcdi_request_errcode( 660 __in unsigned int err) 661 { 662 663 switch (err) { 664 /* MCDI v1 */ 665 case MC_CMD_ERR_EPERM: 666 return (EACCES); 667 case MC_CMD_ERR_ENOENT: 668 return (ENOENT); 669 case MC_CMD_ERR_EINTR: 670 return (EINTR); 671 case MC_CMD_ERR_EACCES: 672 return (EACCES); 673 case MC_CMD_ERR_EBUSY: 674 return (EBUSY); 675 case MC_CMD_ERR_EINVAL: 676 return (EINVAL); 677 case MC_CMD_ERR_EDEADLK: 678 return (EDEADLK); 679 case MC_CMD_ERR_ENOSYS: 680 return (ENOTSUP); 681 case MC_CMD_ERR_ETIME: 682 return (ETIMEDOUT); 683 case MC_CMD_ERR_ENOTSUP: 684 return (ENOTSUP); 685 case MC_CMD_ERR_EALREADY: 686 return (EALREADY); 687 688 /* MCDI v2 */ 689 case MC_CMD_ERR_EEXIST: 690 return (EEXIST); 691 #ifdef MC_CMD_ERR_EAGAIN 692 case MC_CMD_ERR_EAGAIN: 693 return (EAGAIN); 694 #endif 695 #ifdef MC_CMD_ERR_ENOSPC 696 case MC_CMD_ERR_ENOSPC: 697 return (ENOSPC); 698 #endif 699 case MC_CMD_ERR_ERANGE: 700 return (ERANGE); 701 702 case MC_CMD_ERR_ALLOC_FAIL: 703 return (ENOMEM); 704 case MC_CMD_ERR_NO_VADAPTOR: 705 return (ENOENT); 706 case MC_CMD_ERR_NO_EVB_PORT: 707 return (ENOENT); 708 case MC_CMD_ERR_NO_VSWITCH: 709 return (ENODEV); 710 case MC_CMD_ERR_VLAN_LIMIT: 711 return (EINVAL); 712 case MC_CMD_ERR_BAD_PCI_FUNC: 713 return (ENODEV); 714 case MC_CMD_ERR_BAD_VLAN_MODE: 715 return (EINVAL); 716 case MC_CMD_ERR_BAD_VSWITCH_TYPE: 717 return (EINVAL); 718 case MC_CMD_ERR_BAD_VPORT_TYPE: 719 return (EINVAL); 720 case MC_CMD_ERR_MAC_EXIST: 721 return (EEXIST); 722 723 case MC_CMD_ERR_PROXY_PENDING: 724 return (EAGAIN); 725 726 default: 727 EFSYS_PROBE1(mc_pcol_error, int, err); 728 return (EIO); 729 } 730 } 731 732 void 733 efx_mcdi_raise_exception( 734 __in efx_nic_t *enp, 735 __in_opt efx_mcdi_req_t *emrp, 736 __in int rc) 737 { 738 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 739 efx_mcdi_exception_t exception; 740 741 /* Reboot or Assertion failure only */ 742 EFSYS_ASSERT(rc == EIO || rc == EINTR); 743 744 /* 745 * If MC_CMD_REBOOT causes a reboot (dependent on parameters), 746 * then the EIO is not worthy of an exception. 747 */ 748 if (emrp != NULL && emrp->emr_cmd == MC_CMD_REBOOT && rc == EIO) 749 return; 750 751 exception = (rc == EIO) 752 ? EFX_MCDI_EXCEPTION_MC_REBOOT 753 : EFX_MCDI_EXCEPTION_MC_BADASSERT; 754 755 emtp->emt_exception(emtp->emt_context, exception); 756 } 757 758 void 759 efx_mcdi_execute( 760 __in efx_nic_t *enp, 761 __inout efx_mcdi_req_t *emrp) 762 { 763 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 764 765 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); 766 EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); 767 768 emrp->emr_quiet = B_FALSE; 769 emtp->emt_execute(emtp->emt_context, emrp); 770 } 771 772 void 773 efx_mcdi_execute_quiet( 774 __in efx_nic_t *enp, 775 __inout efx_mcdi_req_t *emrp) 776 { 777 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 778 779 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); 780 EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); 781 782 emrp->emr_quiet = B_TRUE; 783 emtp->emt_execute(emtp->emt_context, emrp); 784 } 785 786 void 787 efx_mcdi_ev_cpl( 788 __in efx_nic_t *enp, 789 __in unsigned int seq, 790 __in unsigned int outlen, 791 __in int errcode) 792 { 793 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 794 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 795 efx_mcdi_req_t *emrp; 796 efsys_lock_state_t state; 797 798 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI); 799 EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); 800 801 /* 802 * Serialise against efx_mcdi_request_poll()/efx_mcdi_request_start() 803 * when we're completing an aborted request. 804 */ 805 EFSYS_LOCK(enp->en_eslp, state); 806 if (emip->emi_pending_req == NULL || !emip->emi_ev_cpl || 807 (seq != ((emip->emi_seq - 1) & EFX_MASK32(MCDI_HEADER_SEQ)))) { 808 EFSYS_ASSERT(emip->emi_aborted > 0); 809 if (emip->emi_aborted > 0) 810 --emip->emi_aborted; 811 EFSYS_UNLOCK(enp->en_eslp, state); 812 return; 813 } 814 815 emrp = emip->emi_pending_req; 816 emip->emi_pending_req = NULL; 817 EFSYS_UNLOCK(enp->en_eslp, state); 818 819 if (emip->emi_max_version >= 2) { 820 /* MCDIv2 response details do not fit into an event. */ 821 efx_mcdi_read_response_header(enp, emrp); 822 } else { 823 if (errcode != 0) { 824 if (!emrp->emr_quiet) { 825 EFSYS_PROBE2(mcdi_err, int, emrp->emr_cmd, 826 int, errcode); 827 } 828 emrp->emr_out_length_used = 0; 829 emrp->emr_rc = efx_mcdi_request_errcode(errcode); 830 } else { 831 emrp->emr_out_length_used = outlen; 832 emrp->emr_rc = 0; 833 } 834 } 835 if (emrp->emr_rc == 0) 836 efx_mcdi_finish_response(enp, emrp); 837 838 emtp->emt_ev_cpl(emtp->emt_context); 839 } 840 841 #if EFSYS_OPT_MCDI_PROXY_AUTH 842 843 __checkReturn efx_rc_t 844 efx_mcdi_get_proxy_handle( 845 __in efx_nic_t *enp, 846 __in efx_mcdi_req_t *emrp, 847 __out uint32_t *handlep) 848 { 849 efx_rc_t rc; 850 851 _NOTE(ARGUNUSED(enp)) 852 853 /* 854 * Return proxy handle from MCDI request that returned with error 855 * MC_MCD_ERR_PROXY_PENDING. This handle is used to wait for a matching 856 * PROXY_RESPONSE event. 857 */ 858 if ((emrp == NULL) || (handlep == NULL)) { 859 rc = EINVAL; 860 goto fail1; 861 } 862 if ((emrp->emr_rc != 0) && 863 (emrp->emr_err_code == MC_CMD_ERR_PROXY_PENDING)) { 864 *handlep = emrp->emr_proxy_handle; 865 rc = 0; 866 } else { 867 *handlep = 0; 868 rc = ENOENT; 869 } 870 return (rc); 871 872 fail1: 873 EFSYS_PROBE1(fail1, efx_rc_t, rc); 874 return (rc); 875 } 876 877 void 878 efx_mcdi_ev_proxy_response( 879 __in efx_nic_t *enp, 880 __in unsigned int handle, 881 __in unsigned int status) 882 { 883 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 884 efx_rc_t rc; 885 886 /* 887 * Handle results of an authorization request for a privileged MCDI 888 * command. If authorization was granted then we must re-issue the 889 * original MCDI request. If authorization failed or timed out, 890 * then the original MCDI request should be completed with the 891 * result code from this event. 892 */ 893 rc = (status == 0) ? 0 : efx_mcdi_request_errcode(status); 894 895 emtp->emt_ev_proxy_response(emtp->emt_context, handle, rc); 896 } 897 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH */ 898 899 #if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER 900 void 901 efx_mcdi_ev_proxy_request( 902 __in efx_nic_t *enp, 903 __in unsigned int index) 904 { 905 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 906 907 if (emtp->emt_ev_proxy_request != NULL) 908 emtp->emt_ev_proxy_request(emtp->emt_context, index); 909 } 910 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */ 911 void 912 efx_mcdi_ev_death( 913 __in efx_nic_t *enp, 914 __in int rc) 915 { 916 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 917 const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp; 918 efx_mcdi_req_t *emrp = NULL; 919 boolean_t ev_cpl; 920 efsys_lock_state_t state; 921 922 /* 923 * The MCDI request (if there is one) has been terminated, either 924 * by a BADASSERT or REBOOT event. 925 * 926 * If there is an outstanding event-completed MCDI operation, then we 927 * will never receive the completion event (because both MCDI 928 * completions and BADASSERT events are sent to the same evq). So 929 * complete this MCDI op. 930 * 931 * This function might run in parallel with efx_mcdi_request_poll() 932 * for poll completed mcdi requests, and also with 933 * efx_mcdi_request_start() for post-watchdog completions. 934 */ 935 EFSYS_LOCK(enp->en_eslp, state); 936 emrp = emip->emi_pending_req; 937 ev_cpl = emip->emi_ev_cpl; 938 if (emrp != NULL && emip->emi_ev_cpl) { 939 emip->emi_pending_req = NULL; 940 941 emrp->emr_out_length_used = 0; 942 emrp->emr_rc = rc; 943 ++emip->emi_aborted; 944 } 945 946 /* 947 * Since we're running in parallel with a request, consume the 948 * status word before dropping the lock. 949 */ 950 if (rc == EIO || rc == EINTR) { 951 EFSYS_SPIN(EFX_MCDI_STATUS_SLEEP_US); 952 (void) efx_mcdi_poll_reboot(enp); 953 emip->emi_new_epoch = B_TRUE; 954 } 955 956 EFSYS_UNLOCK(enp->en_eslp, state); 957 958 efx_mcdi_raise_exception(enp, emrp, rc); 959 960 if (emrp != NULL && ev_cpl) 961 emtp->emt_ev_cpl(emtp->emt_context); 962 } 963 964 __checkReturn efx_rc_t 965 efx_mcdi_get_version( 966 __in efx_nic_t *enp, 967 __in uint32_t flags, 968 __out efx_mcdi_version_t *verp) 969 { 970 efx_nic_board_info_t *board_infop = &verp->emv_board_info; 971 EFX_MCDI_DECLARE_BUF(payload, 972 MC_CMD_GET_VERSION_EXT_IN_LEN, 973 MC_CMD_GET_VERSION_V2_OUT_LEN); 974 efx_word_t *ver_words; 975 uint16_t version[4]; 976 efx_mcdi_req_t req; 977 uint32_t firmware; 978 efx_rc_t rc; 979 980 EFX_STATIC_ASSERT(sizeof (verp->emv_version) == 981 MC_CMD_GET_VERSION_OUT_VERSION_LEN); 982 EFX_STATIC_ASSERT(sizeof (verp->emv_firmware) == 983 MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN); 984 985 EFX_STATIC_ASSERT(EFX_MCDI_VERSION_BOARD_INFO == 986 (1U << MC_CMD_GET_VERSION_V2_OUT_BOARD_EXT_INFO_PRESENT_LBN)); 987 988 EFX_STATIC_ASSERT(sizeof (board_infop->enbi_serial) == 989 MC_CMD_GET_VERSION_V2_OUT_BOARD_SERIAL_LEN); 990 EFX_STATIC_ASSERT(sizeof (board_infop->enbi_name) == 991 MC_CMD_GET_VERSION_V2_OUT_BOARD_NAME_LEN); 992 EFX_STATIC_ASSERT(sizeof (board_infop->enbi_revision) == 993 MC_CMD_GET_VERSION_V2_OUT_BOARD_REVISION_LEN); 994 995 EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); 996 997 req.emr_cmd = MC_CMD_GET_VERSION; 998 req.emr_in_buf = payload; 999 req.emr_out_buf = payload; 1000 1001 if ((flags & EFX_MCDI_VERSION_BOARD_INFO) != 0) { 1002 /* Request basic + extended version information. */ 1003 req.emr_in_length = MC_CMD_GET_VERSION_EXT_IN_LEN; 1004 req.emr_out_length = MC_CMD_GET_VERSION_V2_OUT_LEN; 1005 } else { 1006 /* Request only basic version information. */ 1007 req.emr_in_length = MC_CMD_GET_VERSION_IN_LEN; 1008 req.emr_out_length = MC_CMD_GET_VERSION_OUT_LEN; 1009 } 1010 1011 efx_mcdi_execute(enp, &req); 1012 1013 if (req.emr_rc != 0) { 1014 rc = req.emr_rc; 1015 goto fail1; 1016 } 1017 1018 /* bootrom support */ 1019 if (req.emr_out_length_used == MC_CMD_GET_VERSION_V0_OUT_LEN) { 1020 version[0] = version[1] = version[2] = version[3] = 0; 1021 firmware = MCDI_OUT_DWORD(req, GET_VERSION_OUT_FIRMWARE); 1022 goto out; 1023 } 1024 1025 if (req.emr_out_length_used < req.emr_out_length) { 1026 rc = EMSGSIZE; 1027 goto fail2; 1028 } 1029 1030 ver_words = MCDI_OUT2(req, efx_word_t, GET_VERSION_OUT_VERSION); 1031 version[0] = EFX_WORD_FIELD(ver_words[0], EFX_WORD_0); 1032 version[1] = EFX_WORD_FIELD(ver_words[1], EFX_WORD_0); 1033 version[2] = EFX_WORD_FIELD(ver_words[2], EFX_WORD_0); 1034 version[3] = EFX_WORD_FIELD(ver_words[3], EFX_WORD_0); 1035 firmware = MCDI_OUT_DWORD(req, GET_VERSION_OUT_FIRMWARE); 1036 1037 out: 1038 memset(verp, 0, sizeof (*verp)); 1039 1040 verp->emv_version[0] = version[0]; 1041 verp->emv_version[1] = version[1]; 1042 verp->emv_version[2] = version[2]; 1043 verp->emv_version[3] = version[3]; 1044 verp->emv_firmware = firmware; 1045 1046 verp->emv_flags = MCDI_OUT_DWORD(req, GET_VERSION_V2_OUT_FLAGS); 1047 verp->emv_flags &= flags; 1048 1049 if ((verp->emv_flags & EFX_MCDI_VERSION_BOARD_INFO) != 0) { 1050 memcpy(board_infop->enbi_serial, 1051 MCDI_OUT2(req, char, GET_VERSION_V2_OUT_BOARD_SERIAL), 1052 sizeof (board_infop->enbi_serial)); 1053 memcpy(board_infop->enbi_name, 1054 MCDI_OUT2(req, char, GET_VERSION_V2_OUT_BOARD_NAME), 1055 sizeof (board_infop->enbi_name)); 1056 board_infop->enbi_revision = 1057 MCDI_OUT_DWORD(req, GET_VERSION_V2_OUT_BOARD_REVISION); 1058 } 1059 1060 return (0); 1061 1062 fail2: 1063 EFSYS_PROBE(fail2); 1064 fail1: 1065 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1066 1067 return (rc); 1068 } 1069 1070 static __checkReturn efx_rc_t 1071 efx_mcdi_get_boot_status( 1072 __in efx_nic_t *enp, 1073 __out efx_mcdi_boot_t *statusp) 1074 { 1075 EFX_MCDI_DECLARE_BUF(payload, 1076 MC_CMD_GET_BOOT_STATUS_IN_LEN, 1077 MC_CMD_GET_BOOT_STATUS_OUT_LEN); 1078 efx_mcdi_req_t req; 1079 efx_rc_t rc; 1080 1081 EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI); 1082 1083 req.emr_cmd = MC_CMD_GET_BOOT_STATUS; 1084 req.emr_in_buf = payload; 1085 req.emr_in_length = MC_CMD_GET_BOOT_STATUS_IN_LEN; 1086 req.emr_out_buf = payload; 1087 req.emr_out_length = MC_CMD_GET_BOOT_STATUS_OUT_LEN; 1088 1089 efx_mcdi_execute_quiet(enp, &req); 1090 1091 /* 1092 * NOTE: Unprivileged functions cannot access boot status, 1093 * so the MCDI request will return EACCES. This is 1094 * also checked in efx_mcdi_version. 1095 */ 1096 1097 if (req.emr_rc != 0) { 1098 rc = req.emr_rc; 1099 goto fail1; 1100 } 1101 1102 if (req.emr_out_length_used < MC_CMD_GET_BOOT_STATUS_OUT_LEN) { 1103 rc = EMSGSIZE; 1104 goto fail2; 1105 } 1106 1107 if (MCDI_OUT_DWORD_FIELD(req, GET_BOOT_STATUS_OUT_FLAGS, 1108 GET_BOOT_STATUS_OUT_FLAGS_PRIMARY)) 1109 *statusp = EFX_MCDI_BOOT_PRIMARY; 1110 else 1111 *statusp = EFX_MCDI_BOOT_SECONDARY; 1112 1113 return (0); 1114 1115 fail2: 1116 EFSYS_PROBE(fail2); 1117 fail1: 1118 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1119 1120 return (rc); 1121 } 1122 1123 __checkReturn efx_rc_t 1124 efx_mcdi_version( 1125 __in efx_nic_t *enp, 1126 __out_ecount_opt(4) uint16_t versionp[4], 1127 __out_opt uint32_t *buildp, 1128 __out_opt efx_mcdi_boot_t *statusp) 1129 { 1130 efx_mcdi_version_t ver; 1131 efx_mcdi_boot_t status; 1132 efx_rc_t rc; 1133 1134 rc = efx_mcdi_get_version(enp, 0, &ver); 1135 if (rc != 0) 1136 goto fail1; 1137 1138 /* The bootrom doesn't understand BOOT_STATUS */ 1139 if (MC_FW_VERSION_IS_BOOTLOADER(ver.emv_firmware)) { 1140 status = EFX_MCDI_BOOT_ROM; 1141 goto out; 1142 } 1143 1144 rc = efx_mcdi_get_boot_status(enp, &status); 1145 if (rc == EACCES) { 1146 /* Unprivileged functions cannot access BOOT_STATUS */ 1147 status = EFX_MCDI_BOOT_PRIMARY; 1148 memset(ver.emv_version, 0, sizeof (ver.emv_version)); 1149 ver.emv_firmware = 0; 1150 } else if (rc != 0) { 1151 goto fail2; 1152 } 1153 1154 out: 1155 if (versionp != NULL) 1156 memcpy(versionp, ver.emv_version, sizeof (ver.emv_version)); 1157 if (buildp != NULL) 1158 *buildp = ver.emv_firmware; 1159 if (statusp != NULL) 1160 *statusp = status; 1161 1162 return (0); 1163 1164 fail2: 1165 EFSYS_PROBE(fail2); 1166 fail1: 1167 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1168 1169 return (rc); 1170 } 1171 1172 __checkReturn efx_rc_t 1173 efx_mcdi_get_capabilities( 1174 __in efx_nic_t *enp, 1175 __out_opt uint32_t *flagsp, 1176 __out_opt uint16_t *rx_dpcpu_fw_idp, 1177 __out_opt uint16_t *tx_dpcpu_fw_idp, 1178 __out_opt uint32_t *flags2p, 1179 __out_opt uint32_t *tso2ncp) 1180 { 1181 efx_mcdi_req_t req; 1182 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_CAPABILITIES_IN_LEN, 1183 MC_CMD_GET_CAPABILITIES_V2_OUT_LEN); 1184 boolean_t v2_capable; 1185 efx_rc_t rc; 1186 1187 req.emr_cmd = MC_CMD_GET_CAPABILITIES; 1188 req.emr_in_buf = payload; 1189 req.emr_in_length = MC_CMD_GET_CAPABILITIES_IN_LEN; 1190 req.emr_out_buf = payload; 1191 req.emr_out_length = MC_CMD_GET_CAPABILITIES_V2_OUT_LEN; 1192 1193 efx_mcdi_execute_quiet(enp, &req); 1194 1195 if (req.emr_rc != 0) { 1196 rc = req.emr_rc; 1197 goto fail1; 1198 } 1199 1200 if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_OUT_LEN) { 1201 rc = EMSGSIZE; 1202 goto fail2; 1203 } 1204 1205 if (flagsp != NULL) 1206 *flagsp = MCDI_OUT_DWORD(req, GET_CAPABILITIES_OUT_FLAGS1); 1207 1208 if (rx_dpcpu_fw_idp != NULL) 1209 *rx_dpcpu_fw_idp = MCDI_OUT_WORD(req, 1210 GET_CAPABILITIES_OUT_RX_DPCPU_FW_ID); 1211 1212 if (tx_dpcpu_fw_idp != NULL) 1213 *tx_dpcpu_fw_idp = MCDI_OUT_WORD(req, 1214 GET_CAPABILITIES_OUT_TX_DPCPU_FW_ID); 1215 1216 if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_V2_OUT_LEN) 1217 v2_capable = B_FALSE; 1218 else 1219 v2_capable = B_TRUE; 1220 1221 if (flags2p != NULL) { 1222 *flags2p = (v2_capable) ? 1223 MCDI_OUT_DWORD(req, GET_CAPABILITIES_V2_OUT_FLAGS2) : 1224 0; 1225 } 1226 1227 if (tso2ncp != NULL) { 1228 *tso2ncp = (v2_capable) ? 1229 MCDI_OUT_WORD(req, 1230 GET_CAPABILITIES_V2_OUT_TX_TSO_V2_N_CONTEXTS) : 1231 0; 1232 } 1233 1234 return (0); 1235 1236 fail2: 1237 EFSYS_PROBE(fail2); 1238 fail1: 1239 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1240 1241 return (rc); 1242 } 1243 1244 static __checkReturn efx_rc_t 1245 efx_mcdi_do_reboot( 1246 __in efx_nic_t *enp, 1247 __in boolean_t after_assertion) 1248 { 1249 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_REBOOT_IN_LEN, 1250 MC_CMD_REBOOT_OUT_LEN); 1251 efx_mcdi_req_t req; 1252 efx_rc_t rc; 1253 1254 /* 1255 * We could require the caller to have caused en_mod_flags=0 to 1256 * call this function. This doesn't help the other port though, 1257 * who's about to get the MC ripped out from underneath them. 1258 * Since they have to cope with the subsequent fallout of MCDI 1259 * failures, we should as well. 1260 */ 1261 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1262 1263 req.emr_cmd = MC_CMD_REBOOT; 1264 req.emr_in_buf = payload; 1265 req.emr_in_length = MC_CMD_REBOOT_IN_LEN; 1266 req.emr_out_buf = payload; 1267 req.emr_out_length = MC_CMD_REBOOT_OUT_LEN; 1268 1269 MCDI_IN_SET_DWORD(req, REBOOT_IN_FLAGS, 1270 (after_assertion ? MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION : 0)); 1271 1272 efx_mcdi_execute_quiet(enp, &req); 1273 1274 if (req.emr_rc == EACCES) { 1275 /* Unprivileged functions cannot reboot the MC. */ 1276 goto out; 1277 } 1278 1279 /* A successful reboot request returns EIO. */ 1280 if (req.emr_rc != 0 && req.emr_rc != EIO) { 1281 rc = req.emr_rc; 1282 goto fail1; 1283 } 1284 1285 out: 1286 return (0); 1287 1288 fail1: 1289 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1290 1291 return (rc); 1292 } 1293 1294 __checkReturn efx_rc_t 1295 efx_mcdi_reboot( 1296 __in efx_nic_t *enp) 1297 { 1298 return (efx_mcdi_do_reboot(enp, B_FALSE)); 1299 } 1300 1301 __checkReturn efx_rc_t 1302 efx_mcdi_exit_assertion_handler( 1303 __in efx_nic_t *enp) 1304 { 1305 return (efx_mcdi_do_reboot(enp, B_TRUE)); 1306 } 1307 1308 __checkReturn efx_rc_t 1309 efx_mcdi_read_assertion( 1310 __in efx_nic_t *enp) 1311 { 1312 efx_mcdi_req_t req; 1313 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_ASSERTS_IN_LEN, 1314 MC_CMD_GET_ASSERTS_OUT_LEN); 1315 const char *reason; 1316 unsigned int flags; 1317 unsigned int index; 1318 unsigned int ofst; 1319 int retry; 1320 efx_rc_t rc; 1321 1322 /* 1323 * Before we attempt to chat to the MC, we should verify that the MC 1324 * isn't in it's assertion handler, either due to a previous reboot, 1325 * or because we're reinitializing due to an eec_exception(). 1326 * 1327 * Use GET_ASSERTS to read any assertion state that may be present. 1328 * Retry this command twice. Once because a boot-time assertion failure 1329 * might cause the 1st MCDI request to fail. And once again because 1330 * we might race with efx_mcdi_exit_assertion_handler() running on 1331 * partner port(s) on the same NIC. 1332 */ 1333 retry = 2; 1334 do { 1335 (void) memset(payload, 0, sizeof (payload)); 1336 req.emr_cmd = MC_CMD_GET_ASSERTS; 1337 req.emr_in_buf = payload; 1338 req.emr_in_length = MC_CMD_GET_ASSERTS_IN_LEN; 1339 req.emr_out_buf = payload; 1340 req.emr_out_length = MC_CMD_GET_ASSERTS_OUT_LEN; 1341 1342 MCDI_IN_SET_DWORD(req, GET_ASSERTS_IN_CLEAR, 1); 1343 efx_mcdi_execute_quiet(enp, &req); 1344 1345 } while ((req.emr_rc == EINTR || req.emr_rc == EIO) && retry-- > 0); 1346 1347 if (req.emr_rc != 0) { 1348 if (req.emr_rc == EACCES) { 1349 /* Unprivileged functions cannot clear assertions. */ 1350 goto out; 1351 } 1352 rc = req.emr_rc; 1353 goto fail1; 1354 } 1355 1356 if (req.emr_out_length_used < MC_CMD_GET_ASSERTS_OUT_LEN) { 1357 rc = EMSGSIZE; 1358 goto fail2; 1359 } 1360 1361 /* Print out any assertion state recorded */ 1362 flags = MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_GLOBAL_FLAGS); 1363 if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS) 1364 return (0); 1365 1366 reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL) 1367 ? "system-level assertion" 1368 : (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL) 1369 ? "thread-level assertion" 1370 : (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED) 1371 ? "watchdog reset" 1372 : (flags == MC_CMD_GET_ASSERTS_FLAGS_ADDR_TRAP) 1373 ? "illegal address trap" 1374 : "unknown assertion"; 1375 EFSYS_PROBE3(mcpu_assertion, 1376 const char *, reason, unsigned int, 1377 MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_SAVED_PC_OFFS), 1378 unsigned int, 1379 MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_THREAD_OFFS)); 1380 1381 /* Print out the registers (r1 ... r31) */ 1382 ofst = MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST; 1383 for (index = 1; 1384 index < 1 + MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_NUM; 1385 index++) { 1386 EFSYS_PROBE2(mcpu_register, unsigned int, index, unsigned int, 1387 EFX_DWORD_FIELD(*MCDI_OUT(req, efx_dword_t, ofst), 1388 EFX_DWORD_0)); 1389 ofst += sizeof (efx_dword_t); 1390 } 1391 EFSYS_ASSERT(ofst <= MC_CMD_GET_ASSERTS_OUT_LEN); 1392 1393 out: 1394 return (0); 1395 1396 fail2: 1397 EFSYS_PROBE(fail2); 1398 fail1: 1399 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1400 1401 return (rc); 1402 } 1403 1404 1405 /* 1406 * Internal routines for for specific MCDI requests. 1407 */ 1408 1409 __checkReturn efx_rc_t 1410 efx_mcdi_drv_attach( 1411 __in efx_nic_t *enp, 1412 __in boolean_t attach) 1413 { 1414 efx_mcdi_req_t req; 1415 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_DRV_ATTACH_IN_V2_LEN, 1416 MC_CMD_DRV_ATTACH_EXT_OUT_LEN); 1417 efx_rc_t rc; 1418 1419 req.emr_cmd = MC_CMD_DRV_ATTACH; 1420 req.emr_in_buf = payload; 1421 if (enp->en_drv_version[0] == '\0') { 1422 req.emr_in_length = MC_CMD_DRV_ATTACH_IN_LEN; 1423 } else { 1424 req.emr_in_length = MC_CMD_DRV_ATTACH_IN_V2_LEN; 1425 } 1426 req.emr_out_buf = payload; 1427 req.emr_out_length = MC_CMD_DRV_ATTACH_EXT_OUT_LEN; 1428 1429 /* 1430 * Typically, client drivers use DONT_CARE for the datapath firmware 1431 * type to ensure that the driver can attach to an unprivileged 1432 * function. The datapath firmware type to use is controlled by the 1433 * 'sfboot' utility. 1434 * If a client driver wishes to attach with a specific datapath firmware 1435 * type, that can be passed in second argument of efx_nic_probe API. One 1436 * such example is the ESXi native driver that attempts attaching with 1437 * FULL_FEATURED datapath firmware type first and fall backs to 1438 * DONT_CARE datapath firmware type if MC_CMD_DRV_ATTACH fails. 1439 */ 1440 MCDI_IN_POPULATE_DWORD_2(req, DRV_ATTACH_IN_NEW_STATE, 1441 DRV_ATTACH_IN_ATTACH, attach ? 1 : 0, 1442 DRV_ATTACH_IN_SUBVARIANT_AWARE, EFSYS_OPT_FW_SUBVARIANT_AWARE); 1443 MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_UPDATE, 1); 1444 MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_FIRMWARE_ID, enp->efv); 1445 1446 if (req.emr_in_length >= MC_CMD_DRV_ATTACH_IN_V2_LEN) { 1447 EFX_STATIC_ASSERT(sizeof (enp->en_drv_version) == 1448 MC_CMD_DRV_ATTACH_IN_V2_DRIVER_VERSION_LEN); 1449 memcpy(MCDI_IN2(req, char, DRV_ATTACH_IN_V2_DRIVER_VERSION), 1450 enp->en_drv_version, 1451 MC_CMD_DRV_ATTACH_IN_V2_DRIVER_VERSION_LEN); 1452 } 1453 1454 efx_mcdi_execute(enp, &req); 1455 1456 if (req.emr_rc != 0) { 1457 rc = req.emr_rc; 1458 goto fail1; 1459 } 1460 1461 if (req.emr_out_length_used < MC_CMD_DRV_ATTACH_OUT_LEN) { 1462 rc = EMSGSIZE; 1463 goto fail2; 1464 } 1465 1466 return (0); 1467 1468 fail2: 1469 EFSYS_PROBE(fail2); 1470 fail1: 1471 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1472 1473 return (rc); 1474 } 1475 1476 __checkReturn efx_rc_t 1477 efx_mcdi_get_board_cfg( 1478 __in efx_nic_t *enp, 1479 __out_opt uint32_t *board_typep, 1480 __out_opt efx_dword_t *capabilitiesp, 1481 __out_ecount_opt(6) uint8_t mac_addrp[6]) 1482 { 1483 efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); 1484 efx_mcdi_req_t req; 1485 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_BOARD_CFG_IN_LEN, 1486 MC_CMD_GET_BOARD_CFG_OUT_LENMIN); 1487 efx_rc_t rc; 1488 1489 req.emr_cmd = MC_CMD_GET_BOARD_CFG; 1490 req.emr_in_buf = payload; 1491 req.emr_in_length = MC_CMD_GET_BOARD_CFG_IN_LEN; 1492 req.emr_out_buf = payload; 1493 req.emr_out_length = MC_CMD_GET_BOARD_CFG_OUT_LENMIN; 1494 1495 efx_mcdi_execute(enp, &req); 1496 1497 if (req.emr_rc != 0) { 1498 rc = req.emr_rc; 1499 goto fail1; 1500 } 1501 1502 if (req.emr_out_length_used < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) { 1503 rc = EMSGSIZE; 1504 goto fail2; 1505 } 1506 1507 if (mac_addrp != NULL) { 1508 uint8_t *addrp; 1509 1510 if (emip->emi_port == 1) { 1511 addrp = MCDI_OUT2(req, uint8_t, 1512 GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0); 1513 } else if (emip->emi_port == 2) { 1514 addrp = MCDI_OUT2(req, uint8_t, 1515 GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1); 1516 } else { 1517 rc = EINVAL; 1518 goto fail3; 1519 } 1520 1521 EFX_MAC_ADDR_COPY(mac_addrp, addrp); 1522 } 1523 1524 if (capabilitiesp != NULL) { 1525 if (emip->emi_port == 1) { 1526 *capabilitiesp = *MCDI_OUT2(req, efx_dword_t, 1527 GET_BOARD_CFG_OUT_CAPABILITIES_PORT0); 1528 } else if (emip->emi_port == 2) { 1529 *capabilitiesp = *MCDI_OUT2(req, efx_dword_t, 1530 GET_BOARD_CFG_OUT_CAPABILITIES_PORT1); 1531 } else { 1532 rc = EINVAL; 1533 goto fail4; 1534 } 1535 } 1536 1537 if (board_typep != NULL) { 1538 *board_typep = MCDI_OUT_DWORD(req, 1539 GET_BOARD_CFG_OUT_BOARD_TYPE); 1540 } 1541 1542 return (0); 1543 1544 fail4: 1545 EFSYS_PROBE(fail4); 1546 fail3: 1547 EFSYS_PROBE(fail3); 1548 fail2: 1549 EFSYS_PROBE(fail2); 1550 fail1: 1551 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1552 1553 return (rc); 1554 } 1555 1556 __checkReturn efx_rc_t 1557 efx_mcdi_get_resource_limits( 1558 __in efx_nic_t *enp, 1559 __out_opt uint32_t *nevqp, 1560 __out_opt uint32_t *nrxqp, 1561 __out_opt uint32_t *ntxqp) 1562 { 1563 efx_mcdi_req_t req; 1564 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_RESOURCE_LIMITS_IN_LEN, 1565 MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN); 1566 efx_rc_t rc; 1567 1568 req.emr_cmd = MC_CMD_GET_RESOURCE_LIMITS; 1569 req.emr_in_buf = payload; 1570 req.emr_in_length = MC_CMD_GET_RESOURCE_LIMITS_IN_LEN; 1571 req.emr_out_buf = payload; 1572 req.emr_out_length = MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN; 1573 1574 efx_mcdi_execute(enp, &req); 1575 1576 if (req.emr_rc != 0) { 1577 rc = req.emr_rc; 1578 goto fail1; 1579 } 1580 1581 if (req.emr_out_length_used < MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN) { 1582 rc = EMSGSIZE; 1583 goto fail2; 1584 } 1585 1586 if (nevqp != NULL) 1587 *nevqp = MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_EVQ); 1588 if (nrxqp != NULL) 1589 *nrxqp = MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_RXQ); 1590 if (ntxqp != NULL) 1591 *ntxqp = MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_TXQ); 1592 1593 return (0); 1594 1595 fail2: 1596 EFSYS_PROBE(fail2); 1597 fail1: 1598 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1599 1600 return (rc); 1601 } 1602 1603 __checkReturn efx_rc_t 1604 efx_mcdi_get_phy_cfg( 1605 __in efx_nic_t *enp) 1606 { 1607 efx_port_t *epp = &(enp->en_port); 1608 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1609 efx_mcdi_req_t req; 1610 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PHY_CFG_IN_LEN, 1611 MC_CMD_GET_PHY_CFG_OUT_LEN); 1612 #if EFSYS_OPT_NAMES 1613 const char *namep; 1614 size_t namelen; 1615 #endif 1616 uint32_t phy_media_type; 1617 efx_rc_t rc; 1618 1619 req.emr_cmd = MC_CMD_GET_PHY_CFG; 1620 req.emr_in_buf = payload; 1621 req.emr_in_length = MC_CMD_GET_PHY_CFG_IN_LEN; 1622 req.emr_out_buf = payload; 1623 req.emr_out_length = MC_CMD_GET_PHY_CFG_OUT_LEN; 1624 1625 efx_mcdi_execute(enp, &req); 1626 1627 if (req.emr_rc != 0) { 1628 rc = req.emr_rc; 1629 goto fail1; 1630 } 1631 1632 if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN) { 1633 rc = EMSGSIZE; 1634 goto fail2; 1635 } 1636 1637 encp->enc_phy_type = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_TYPE); 1638 #if EFSYS_OPT_NAMES 1639 namep = MCDI_OUT2(req, char, GET_PHY_CFG_OUT_NAME); 1640 namelen = MIN(sizeof (encp->enc_phy_name) - 1, 1641 strnlen(namep, MC_CMD_GET_PHY_CFG_OUT_NAME_LEN)); 1642 (void) memset(encp->enc_phy_name, 0, 1643 sizeof (encp->enc_phy_name)); 1644 memcpy(encp->enc_phy_name, namep, namelen); 1645 #endif /* EFSYS_OPT_NAMES */ 1646 (void) memset(encp->enc_phy_revision, 0, 1647 sizeof (encp->enc_phy_revision)); 1648 memcpy(encp->enc_phy_revision, 1649 MCDI_OUT2(req, char, GET_PHY_CFG_OUT_REVISION), 1650 MIN(sizeof (encp->enc_phy_revision) - 1, 1651 MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN)); 1652 #if EFSYS_OPT_PHY_LED_CONTROL 1653 encp->enc_led_mask = ((1 << EFX_PHY_LED_DEFAULT) | 1654 (1 << EFX_PHY_LED_OFF) | 1655 (1 << EFX_PHY_LED_ON)); 1656 #endif /* EFSYS_OPT_PHY_LED_CONTROL */ 1657 1658 /* Get the media type of the fixed port, if recognised. */ 1659 EFX_STATIC_ASSERT(MC_CMD_MEDIA_XAUI == EFX_PHY_MEDIA_XAUI); 1660 EFX_STATIC_ASSERT(MC_CMD_MEDIA_CX4 == EFX_PHY_MEDIA_CX4); 1661 EFX_STATIC_ASSERT(MC_CMD_MEDIA_KX4 == EFX_PHY_MEDIA_KX4); 1662 EFX_STATIC_ASSERT(MC_CMD_MEDIA_XFP == EFX_PHY_MEDIA_XFP); 1663 EFX_STATIC_ASSERT(MC_CMD_MEDIA_SFP_PLUS == EFX_PHY_MEDIA_SFP_PLUS); 1664 EFX_STATIC_ASSERT(MC_CMD_MEDIA_BASE_T == EFX_PHY_MEDIA_BASE_T); 1665 EFX_STATIC_ASSERT(MC_CMD_MEDIA_QSFP_PLUS == EFX_PHY_MEDIA_QSFP_PLUS); 1666 phy_media_type = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_MEDIA_TYPE); 1667 epp->ep_fixed_port_type = (efx_phy_media_type_t)phy_media_type; 1668 if (epp->ep_fixed_port_type >= EFX_PHY_MEDIA_NTYPES) 1669 epp->ep_fixed_port_type = EFX_PHY_MEDIA_INVALID; 1670 1671 epp->ep_phy_cap_mask = 1672 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_SUPPORTED_CAP); 1673 #if EFSYS_OPT_PHY_FLAGS 1674 encp->enc_phy_flags_mask = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_FLAGS); 1675 #endif /* EFSYS_OPT_PHY_FLAGS */ 1676 1677 encp->enc_port = (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_PRT); 1678 1679 /* Populate internal state */ 1680 encp->enc_mcdi_mdio_channel = 1681 (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_CHANNEL); 1682 1683 #if EFSYS_OPT_PHY_STATS 1684 encp->enc_mcdi_phy_stat_mask = 1685 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_STATS_MASK); 1686 #endif /* EFSYS_OPT_PHY_STATS */ 1687 1688 #if EFSYS_OPT_BIST 1689 encp->enc_bist_mask = 0; 1690 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 1691 GET_PHY_CFG_OUT_BIST_CABLE_SHORT)) 1692 encp->enc_bist_mask |= (1 << EFX_BIST_TYPE_PHY_CABLE_SHORT); 1693 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 1694 GET_PHY_CFG_OUT_BIST_CABLE_LONG)) 1695 encp->enc_bist_mask |= (1 << EFX_BIST_TYPE_PHY_CABLE_LONG); 1696 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 1697 GET_PHY_CFG_OUT_BIST)) 1698 encp->enc_bist_mask |= (1 << EFX_BIST_TYPE_PHY_NORMAL); 1699 #endif /* EFSYS_OPT_BIST */ 1700 1701 return (0); 1702 1703 fail2: 1704 EFSYS_PROBE(fail2); 1705 fail1: 1706 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1707 1708 return (rc); 1709 } 1710 1711 __checkReturn efx_rc_t 1712 efx_mcdi_firmware_update_supported( 1713 __in efx_nic_t *enp, 1714 __out boolean_t *supportedp) 1715 { 1716 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 1717 efx_rc_t rc; 1718 1719 if (emcop != NULL) { 1720 if ((rc = emcop->emco_feature_supported(enp, 1721 EFX_MCDI_FEATURE_FW_UPDATE, supportedp)) != 0) 1722 goto fail1; 1723 } else { 1724 /* Earlier devices always supported updates */ 1725 *supportedp = B_TRUE; 1726 } 1727 1728 return (0); 1729 1730 fail1: 1731 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1732 1733 return (rc); 1734 } 1735 1736 __checkReturn efx_rc_t 1737 efx_mcdi_macaddr_change_supported( 1738 __in efx_nic_t *enp, 1739 __out boolean_t *supportedp) 1740 { 1741 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 1742 efx_rc_t rc; 1743 1744 if (emcop != NULL) { 1745 if ((rc = emcop->emco_feature_supported(enp, 1746 EFX_MCDI_FEATURE_MACADDR_CHANGE, supportedp)) != 0) 1747 goto fail1; 1748 } else { 1749 /* Earlier devices always supported MAC changes */ 1750 *supportedp = B_TRUE; 1751 } 1752 1753 return (0); 1754 1755 fail1: 1756 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1757 1758 return (rc); 1759 } 1760 1761 __checkReturn efx_rc_t 1762 efx_mcdi_link_control_supported( 1763 __in efx_nic_t *enp, 1764 __out boolean_t *supportedp) 1765 { 1766 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 1767 efx_rc_t rc; 1768 1769 if (emcop != NULL) { 1770 if ((rc = emcop->emco_feature_supported(enp, 1771 EFX_MCDI_FEATURE_LINK_CONTROL, supportedp)) != 0) 1772 goto fail1; 1773 } else { 1774 /* Earlier devices always supported link control */ 1775 *supportedp = B_TRUE; 1776 } 1777 1778 return (0); 1779 1780 fail1: 1781 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1782 1783 return (rc); 1784 } 1785 1786 __checkReturn efx_rc_t 1787 efx_mcdi_mac_spoofing_supported( 1788 __in efx_nic_t *enp, 1789 __out boolean_t *supportedp) 1790 { 1791 const efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop; 1792 efx_rc_t rc; 1793 1794 if (emcop != NULL) { 1795 if ((rc = emcop->emco_feature_supported(enp, 1796 EFX_MCDI_FEATURE_MAC_SPOOFING, supportedp)) != 0) 1797 goto fail1; 1798 } else { 1799 /* Earlier devices always supported MAC spoofing */ 1800 *supportedp = B_TRUE; 1801 } 1802 1803 return (0); 1804 1805 fail1: 1806 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1807 1808 return (rc); 1809 } 1810 1811 #if EFSYS_OPT_BIST 1812 1813 #if EFX_OPTS_EF10() 1814 /* 1815 * Enter bist offline mode. This is a fw mode which puts the NIC into a state 1816 * where memory BIST tests can be run and not much else can interfere or happen. 1817 * A reboot is required to exit this mode. 1818 */ 1819 __checkReturn efx_rc_t 1820 efx_mcdi_bist_enable_offline( 1821 __in efx_nic_t *enp) 1822 { 1823 efx_mcdi_req_t req; 1824 efx_rc_t rc; 1825 1826 EFX_STATIC_ASSERT(MC_CMD_ENABLE_OFFLINE_BIST_IN_LEN == 0); 1827 EFX_STATIC_ASSERT(MC_CMD_ENABLE_OFFLINE_BIST_OUT_LEN == 0); 1828 1829 req.emr_cmd = MC_CMD_ENABLE_OFFLINE_BIST; 1830 req.emr_in_buf = NULL; 1831 req.emr_in_length = 0; 1832 req.emr_out_buf = NULL; 1833 req.emr_out_length = 0; 1834 1835 efx_mcdi_execute(enp, &req); 1836 1837 if (req.emr_rc != 0) { 1838 rc = req.emr_rc; 1839 goto fail1; 1840 } 1841 1842 return (0); 1843 1844 fail1: 1845 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1846 1847 return (rc); 1848 } 1849 #endif /* EFX_OPTS_EF10() */ 1850 1851 __checkReturn efx_rc_t 1852 efx_mcdi_bist_start( 1853 __in efx_nic_t *enp, 1854 __in efx_bist_type_t type) 1855 { 1856 efx_mcdi_req_t req; 1857 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_START_BIST_IN_LEN, 1858 MC_CMD_START_BIST_OUT_LEN); 1859 efx_rc_t rc; 1860 1861 req.emr_cmd = MC_CMD_START_BIST; 1862 req.emr_in_buf = payload; 1863 req.emr_in_length = MC_CMD_START_BIST_IN_LEN; 1864 req.emr_out_buf = payload; 1865 req.emr_out_length = MC_CMD_START_BIST_OUT_LEN; 1866 1867 switch (type) { 1868 case EFX_BIST_TYPE_PHY_NORMAL: 1869 MCDI_IN_SET_DWORD(req, START_BIST_IN_TYPE, MC_CMD_PHY_BIST); 1870 break; 1871 case EFX_BIST_TYPE_PHY_CABLE_SHORT: 1872 MCDI_IN_SET_DWORD(req, START_BIST_IN_TYPE, 1873 MC_CMD_PHY_BIST_CABLE_SHORT); 1874 break; 1875 case EFX_BIST_TYPE_PHY_CABLE_LONG: 1876 MCDI_IN_SET_DWORD(req, START_BIST_IN_TYPE, 1877 MC_CMD_PHY_BIST_CABLE_LONG); 1878 break; 1879 case EFX_BIST_TYPE_MC_MEM: 1880 MCDI_IN_SET_DWORD(req, START_BIST_IN_TYPE, 1881 MC_CMD_MC_MEM_BIST); 1882 break; 1883 case EFX_BIST_TYPE_SAT_MEM: 1884 MCDI_IN_SET_DWORD(req, START_BIST_IN_TYPE, 1885 MC_CMD_PORT_MEM_BIST); 1886 break; 1887 case EFX_BIST_TYPE_REG: 1888 MCDI_IN_SET_DWORD(req, START_BIST_IN_TYPE, 1889 MC_CMD_REG_BIST); 1890 break; 1891 default: 1892 EFSYS_ASSERT(0); 1893 } 1894 1895 efx_mcdi_execute(enp, &req); 1896 1897 if (req.emr_rc != 0) { 1898 rc = req.emr_rc; 1899 goto fail1; 1900 } 1901 1902 return (0); 1903 1904 fail1: 1905 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1906 1907 return (rc); 1908 } 1909 1910 #endif /* EFSYS_OPT_BIST */ 1911 1912 1913 /* Enable logging of some events (e.g. link state changes) */ 1914 __checkReturn efx_rc_t 1915 efx_mcdi_log_ctrl( 1916 __in efx_nic_t *enp) 1917 { 1918 efx_mcdi_req_t req; 1919 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_LOG_CTRL_IN_LEN, 1920 MC_CMD_LOG_CTRL_OUT_LEN); 1921 efx_rc_t rc; 1922 1923 req.emr_cmd = MC_CMD_LOG_CTRL; 1924 req.emr_in_buf = payload; 1925 req.emr_in_length = MC_CMD_LOG_CTRL_IN_LEN; 1926 req.emr_out_buf = payload; 1927 req.emr_out_length = MC_CMD_LOG_CTRL_OUT_LEN; 1928 1929 MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST, 1930 MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ); 1931 MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST_EVQ, 0); 1932 1933 efx_mcdi_execute(enp, &req); 1934 1935 if (req.emr_rc != 0) { 1936 rc = req.emr_rc; 1937 goto fail1; 1938 } 1939 1940 return (0); 1941 1942 fail1: 1943 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1944 1945 return (rc); 1946 } 1947 1948 1949 #if EFSYS_OPT_MAC_STATS 1950 1951 __checkReturn efx_rc_t 1952 efx_mcdi_mac_stats( 1953 __in efx_nic_t *enp, 1954 __in uint32_t vport_id, 1955 __in_opt efsys_mem_t *esmp, 1956 __in efx_stats_action_t action, 1957 __in uint16_t period_ms) 1958 { 1959 efx_mcdi_req_t req; 1960 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_MAC_STATS_IN_LEN, 1961 MC_CMD_MAC_STATS_V2_OUT_DMA_LEN); 1962 int clear = (action == EFX_STATS_CLEAR); 1963 int upload = (action == EFX_STATS_UPLOAD); 1964 int enable = (action == EFX_STATS_ENABLE_NOEVENTS); 1965 int events = (action == EFX_STATS_ENABLE_EVENTS); 1966 int disable = (action == EFX_STATS_DISABLE); 1967 efx_rc_t rc; 1968 1969 req.emr_cmd = MC_CMD_MAC_STATS; 1970 req.emr_in_buf = payload; 1971 req.emr_in_length = MC_CMD_MAC_STATS_IN_LEN; 1972 req.emr_out_buf = payload; 1973 req.emr_out_length = MC_CMD_MAC_STATS_V2_OUT_DMA_LEN; 1974 1975 MCDI_IN_POPULATE_DWORD_6(req, MAC_STATS_IN_CMD, 1976 MAC_STATS_IN_DMA, upload, 1977 MAC_STATS_IN_CLEAR, clear, 1978 MAC_STATS_IN_PERIODIC_CHANGE, enable | events | disable, 1979 MAC_STATS_IN_PERIODIC_ENABLE, enable | events, 1980 MAC_STATS_IN_PERIODIC_NOEVENT, !events, 1981 MAC_STATS_IN_PERIOD_MS, (enable | events) ? period_ms : 0); 1982 1983 if (enable || events || upload) { 1984 const efx_nic_cfg_t *encp = &enp->en_nic_cfg; 1985 uint32_t bytes; 1986 1987 /* Periodic stats or stats upload require a DMA buffer */ 1988 if (esmp == NULL) { 1989 rc = EINVAL; 1990 goto fail1; 1991 } 1992 1993 if (encp->enc_mac_stats_nstats < MC_CMD_MAC_NSTATS) { 1994 /* MAC stats count too small for legacy MAC stats */ 1995 rc = ENOSPC; 1996 goto fail2; 1997 } 1998 1999 bytes = encp->enc_mac_stats_nstats * sizeof (efx_qword_t); 2000 2001 if (EFSYS_MEM_SIZE(esmp) < bytes) { 2002 /* DMA buffer too small */ 2003 rc = ENOSPC; 2004 goto fail3; 2005 } 2006 2007 MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_ADDR_LO, 2008 EFSYS_MEM_ADDR(esmp) & 0xffffffff); 2009 MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_ADDR_HI, 2010 EFSYS_MEM_ADDR(esmp) >> 32); 2011 MCDI_IN_SET_DWORD(req, MAC_STATS_IN_DMA_LEN, bytes); 2012 } 2013 2014 /* 2015 * NOTE: Do not use EVB_PORT_ID_ASSIGNED when disabling periodic stats, 2016 * as this may fail (and leave periodic DMA enabled) if the 2017 * vadapter has already been deleted. 2018 */ 2019 MCDI_IN_SET_DWORD(req, MAC_STATS_IN_PORT_ID, 2020 (disable ? EVB_PORT_ID_NULL : vport_id)); 2021 2022 efx_mcdi_execute(enp, &req); 2023 2024 if (req.emr_rc != 0) { 2025 /* EF10: Expect ENOENT if no DMA queues are initialised */ 2026 if ((req.emr_rc != ENOENT) || 2027 (enp->en_rx_qcount + enp->en_tx_qcount != 0)) { 2028 rc = req.emr_rc; 2029 goto fail4; 2030 } 2031 } 2032 2033 return (0); 2034 2035 fail4: 2036 EFSYS_PROBE(fail4); 2037 fail3: 2038 EFSYS_PROBE(fail3); 2039 fail2: 2040 EFSYS_PROBE(fail2); 2041 fail1: 2042 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2043 2044 return (rc); 2045 } 2046 2047 __checkReturn efx_rc_t 2048 efx_mcdi_mac_stats_clear( 2049 __in efx_nic_t *enp) 2050 { 2051 efx_rc_t rc; 2052 2053 if ((rc = efx_mcdi_mac_stats(enp, enp->en_vport_id, NULL, 2054 EFX_STATS_CLEAR, 0)) != 0) 2055 goto fail1; 2056 2057 return (0); 2058 2059 fail1: 2060 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2061 2062 return (rc); 2063 } 2064 2065 __checkReturn efx_rc_t 2066 efx_mcdi_mac_stats_upload( 2067 __in efx_nic_t *enp, 2068 __in efsys_mem_t *esmp) 2069 { 2070 efx_rc_t rc; 2071 2072 /* 2073 * The MC DMAs aggregate statistics for our convenience, so we can 2074 * avoid having to pull the statistics buffer into the cache to 2075 * maintain cumulative statistics. 2076 */ 2077 if ((rc = efx_mcdi_mac_stats(enp, enp->en_vport_id, esmp, 2078 EFX_STATS_UPLOAD, 0)) != 0) 2079 goto fail1; 2080 2081 return (0); 2082 2083 fail1: 2084 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2085 2086 return (rc); 2087 } 2088 2089 __checkReturn efx_rc_t 2090 efx_mcdi_mac_stats_periodic( 2091 __in efx_nic_t *enp, 2092 __in efsys_mem_t *esmp, 2093 __in uint16_t period_ms, 2094 __in boolean_t events) 2095 { 2096 efx_rc_t rc; 2097 2098 /* 2099 * The MC DMAs aggregate statistics for our convenience, so we can 2100 * avoid having to pull the statistics buffer into the cache to 2101 * maintain cumulative statistics. 2102 * Huntington uses a fixed 1sec period. 2103 * Medford uses a fixed 1sec period before v6.2.1.1033 firmware. 2104 */ 2105 if (period_ms == 0) 2106 rc = efx_mcdi_mac_stats(enp, enp->en_vport_id, NULL, 2107 EFX_STATS_DISABLE, 0); 2108 else if (events) 2109 rc = efx_mcdi_mac_stats(enp, enp->en_vport_id, esmp, 2110 EFX_STATS_ENABLE_EVENTS, period_ms); 2111 else 2112 rc = efx_mcdi_mac_stats(enp, enp->en_vport_id, esmp, 2113 EFX_STATS_ENABLE_NOEVENTS, period_ms); 2114 2115 if (rc != 0) 2116 goto fail1; 2117 2118 return (0); 2119 2120 fail1: 2121 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2122 2123 return (rc); 2124 } 2125 2126 #endif /* EFSYS_OPT_MAC_STATS */ 2127 2128 #if EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() 2129 2130 /* 2131 * This function returns the pf and vf number of a function. If it is a pf the 2132 * vf number is 0xffff. The vf number is the index of the vf on that 2133 * function. So if you have 3 vfs on pf 0 the 3 vfs will return (pf=0,vf=0), 2134 * (pf=0,vf=1), (pf=0,vf=2) aand the pf will return (pf=0, vf=0xffff). 2135 */ 2136 __checkReturn efx_rc_t 2137 efx_mcdi_get_function_info( 2138 __in efx_nic_t *enp, 2139 __out uint32_t *pfp, 2140 __out_opt uint32_t *vfp) 2141 { 2142 efx_mcdi_req_t req; 2143 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_FUNCTION_INFO_IN_LEN, 2144 MC_CMD_GET_FUNCTION_INFO_OUT_LEN); 2145 efx_rc_t rc; 2146 2147 req.emr_cmd = MC_CMD_GET_FUNCTION_INFO; 2148 req.emr_in_buf = payload; 2149 req.emr_in_length = MC_CMD_GET_FUNCTION_INFO_IN_LEN; 2150 req.emr_out_buf = payload; 2151 req.emr_out_length = MC_CMD_GET_FUNCTION_INFO_OUT_LEN; 2152 2153 efx_mcdi_execute(enp, &req); 2154 2155 if (req.emr_rc != 0) { 2156 rc = req.emr_rc; 2157 goto fail1; 2158 } 2159 2160 if (req.emr_out_length_used < MC_CMD_GET_FUNCTION_INFO_OUT_LEN) { 2161 rc = EMSGSIZE; 2162 goto fail2; 2163 } 2164 2165 *pfp = MCDI_OUT_DWORD(req, GET_FUNCTION_INFO_OUT_PF); 2166 if (vfp != NULL) 2167 *vfp = MCDI_OUT_DWORD(req, GET_FUNCTION_INFO_OUT_VF); 2168 2169 return (0); 2170 2171 fail2: 2172 EFSYS_PROBE(fail2); 2173 fail1: 2174 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2175 2176 return (rc); 2177 } 2178 2179 __checkReturn efx_rc_t 2180 efx_mcdi_privilege_mask( 2181 __in efx_nic_t *enp, 2182 __in uint32_t pf, 2183 __in uint32_t vf, 2184 __out uint32_t *maskp) 2185 { 2186 efx_mcdi_req_t req; 2187 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PRIVILEGE_MASK_IN_LEN, 2188 MC_CMD_PRIVILEGE_MASK_OUT_LEN); 2189 efx_rc_t rc; 2190 2191 req.emr_cmd = MC_CMD_PRIVILEGE_MASK; 2192 req.emr_in_buf = payload; 2193 req.emr_in_length = MC_CMD_PRIVILEGE_MASK_IN_LEN; 2194 req.emr_out_buf = payload; 2195 req.emr_out_length = MC_CMD_PRIVILEGE_MASK_OUT_LEN; 2196 2197 MCDI_IN_POPULATE_DWORD_2(req, PRIVILEGE_MASK_IN_FUNCTION, 2198 PRIVILEGE_MASK_IN_FUNCTION_PF, pf, 2199 PRIVILEGE_MASK_IN_FUNCTION_VF, vf); 2200 2201 efx_mcdi_execute(enp, &req); 2202 2203 if (req.emr_rc != 0) { 2204 rc = req.emr_rc; 2205 goto fail1; 2206 } 2207 2208 if (req.emr_out_length_used < MC_CMD_PRIVILEGE_MASK_OUT_LEN) { 2209 rc = EMSGSIZE; 2210 goto fail2; 2211 } 2212 2213 *maskp = MCDI_OUT_DWORD(req, PRIVILEGE_MASK_OUT_OLD_MASK); 2214 2215 return (0); 2216 2217 fail2: 2218 EFSYS_PROBE(fail2); 2219 fail1: 2220 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2221 2222 return (rc); 2223 } 2224 2225 #endif /* EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() */ 2226 2227 __checkReturn efx_rc_t 2228 efx_mcdi_set_workaround( 2229 __in efx_nic_t *enp, 2230 __in uint32_t type, 2231 __in boolean_t enabled, 2232 __out_opt uint32_t *flagsp) 2233 { 2234 efx_mcdi_req_t req; 2235 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_WORKAROUND_IN_LEN, 2236 MC_CMD_WORKAROUND_EXT_OUT_LEN); 2237 efx_rc_t rc; 2238 2239 req.emr_cmd = MC_CMD_WORKAROUND; 2240 req.emr_in_buf = payload; 2241 req.emr_in_length = MC_CMD_WORKAROUND_IN_LEN; 2242 req.emr_out_buf = payload; 2243 req.emr_out_length = MC_CMD_WORKAROUND_OUT_LEN; 2244 2245 MCDI_IN_SET_DWORD(req, WORKAROUND_IN_TYPE, type); 2246 MCDI_IN_SET_DWORD(req, WORKAROUND_IN_ENABLED, enabled ? 1 : 0); 2247 2248 efx_mcdi_execute_quiet(enp, &req); 2249 2250 if (req.emr_rc != 0) { 2251 rc = req.emr_rc; 2252 goto fail1; 2253 } 2254 2255 if (flagsp != NULL) { 2256 if (req.emr_out_length_used >= MC_CMD_WORKAROUND_EXT_OUT_LEN) 2257 *flagsp = MCDI_OUT_DWORD(req, WORKAROUND_EXT_OUT_FLAGS); 2258 else 2259 *flagsp = 0; 2260 } 2261 2262 return (0); 2263 2264 fail1: 2265 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2266 2267 return (rc); 2268 } 2269 2270 2271 __checkReturn efx_rc_t 2272 efx_mcdi_get_workarounds( 2273 __in efx_nic_t *enp, 2274 __out_opt uint32_t *implementedp, 2275 __out_opt uint32_t *enabledp) 2276 { 2277 efx_mcdi_req_t req; 2278 EFX_MCDI_DECLARE_BUF(payload, 0, MC_CMD_GET_WORKAROUNDS_OUT_LEN); 2279 efx_rc_t rc; 2280 2281 req.emr_cmd = MC_CMD_GET_WORKAROUNDS; 2282 req.emr_in_buf = NULL; 2283 req.emr_in_length = 0; 2284 req.emr_out_buf = payload; 2285 req.emr_out_length = MC_CMD_GET_WORKAROUNDS_OUT_LEN; 2286 2287 efx_mcdi_execute(enp, &req); 2288 2289 if (req.emr_rc != 0) { 2290 rc = req.emr_rc; 2291 goto fail1; 2292 } 2293 2294 if (implementedp != NULL) { 2295 *implementedp = 2296 MCDI_OUT_DWORD(req, GET_WORKAROUNDS_OUT_IMPLEMENTED); 2297 } 2298 2299 if (enabledp != NULL) { 2300 *enabledp = MCDI_OUT_DWORD(req, GET_WORKAROUNDS_OUT_ENABLED); 2301 } 2302 2303 return (0); 2304 2305 fail1: 2306 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2307 2308 return (rc); 2309 } 2310 2311 /* 2312 * Size of media information page in accordance with SFF-8472 and SFF-8436. 2313 * It is used in MCDI interface as well. 2314 */ 2315 #define EFX_PHY_MEDIA_INFO_PAGE_SIZE 0x80 2316 2317 /* 2318 * Transceiver identifiers from SFF-8024 Table 4-1. 2319 */ 2320 #define EFX_SFF_TRANSCEIVER_ID_SFP 0x03 /* SFP/SFP+/SFP28 */ 2321 #define EFX_SFF_TRANSCEIVER_ID_QSFP 0x0c /* QSFP */ 2322 #define EFX_SFF_TRANSCEIVER_ID_QSFP_PLUS 0x0d /* QSFP+ or later */ 2323 #define EFX_SFF_TRANSCEIVER_ID_QSFP28 0x11 /* QSFP28 or later */ 2324 2325 static __checkReturn efx_rc_t 2326 efx_mcdi_get_phy_media_info( 2327 __in efx_nic_t *enp, 2328 __in uint32_t mcdi_page, 2329 __in uint8_t offset, 2330 __in uint8_t len, 2331 __out_bcount(len) uint8_t *data) 2332 { 2333 efx_mcdi_req_t req; 2334 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN, 2335 MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN( 2336 EFX_PHY_MEDIA_INFO_PAGE_SIZE)); 2337 efx_rc_t rc; 2338 2339 EFSYS_ASSERT((uint32_t)offset + len <= EFX_PHY_MEDIA_INFO_PAGE_SIZE); 2340 2341 req.emr_cmd = MC_CMD_GET_PHY_MEDIA_INFO; 2342 req.emr_in_buf = payload; 2343 req.emr_in_length = MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN; 2344 req.emr_out_buf = payload; 2345 req.emr_out_length = 2346 MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(EFX_PHY_MEDIA_INFO_PAGE_SIZE); 2347 2348 MCDI_IN_SET_DWORD(req, GET_PHY_MEDIA_INFO_IN_PAGE, mcdi_page); 2349 2350 efx_mcdi_execute(enp, &req); 2351 2352 if (req.emr_rc != 0) { 2353 rc = req.emr_rc; 2354 goto fail1; 2355 } 2356 2357 if (req.emr_out_length_used != 2358 MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(EFX_PHY_MEDIA_INFO_PAGE_SIZE)) { 2359 rc = EMSGSIZE; 2360 goto fail2; 2361 } 2362 2363 if (MCDI_OUT_DWORD(req, GET_PHY_MEDIA_INFO_OUT_DATALEN) != 2364 EFX_PHY_MEDIA_INFO_PAGE_SIZE) { 2365 rc = EIO; 2366 goto fail3; 2367 } 2368 2369 memcpy(data, 2370 MCDI_OUT2(req, uint8_t, GET_PHY_MEDIA_INFO_OUT_DATA) + offset, 2371 len); 2372 2373 return (0); 2374 2375 fail3: 2376 EFSYS_PROBE(fail3); 2377 fail2: 2378 EFSYS_PROBE(fail2); 2379 fail1: 2380 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2381 2382 return (rc); 2383 } 2384 2385 __checkReturn efx_rc_t 2386 efx_mcdi_phy_module_get_info( 2387 __in efx_nic_t *enp, 2388 __in uint8_t dev_addr, 2389 __in size_t offset, 2390 __in size_t len, 2391 __out_bcount(len) uint8_t *data) 2392 { 2393 efx_port_t *epp = &(enp->en_port); 2394 efx_rc_t rc; 2395 uint32_t mcdi_lower_page; 2396 uint32_t mcdi_upper_page; 2397 uint8_t id; 2398 2399 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 2400 2401 /* 2402 * Map device address to MC_CMD_GET_PHY_MEDIA_INFO pages. 2403 * Offset plus length interface allows to access page 0 only. 2404 * I.e. non-zero upper pages are not accessible. 2405 * See SFF-8472 section 4 Memory Organization and SFF-8436 section 7.6 2406 * QSFP+ Memory Map for details on how information is structured 2407 * and accessible. 2408 */ 2409 switch (epp->ep_fixed_port_type) { 2410 case EFX_PHY_MEDIA_SFP_PLUS: 2411 case EFX_PHY_MEDIA_QSFP_PLUS: 2412 /* Port type supports modules */ 2413 break; 2414 default: 2415 rc = ENOTSUP; 2416 goto fail1; 2417 } 2418 2419 /* 2420 * For all supported port types, MCDI page 0 offset 0 holds the 2421 * transceiver identifier. Probe to determine the data layout. 2422 * Definitions from SFF-8024 Table 4-1. 2423 */ 2424 rc = efx_mcdi_get_phy_media_info(enp, 2425 0, 0, sizeof(id), &id); 2426 if (rc != 0) 2427 goto fail2; 2428 2429 switch (id) { 2430 case EFX_SFF_TRANSCEIVER_ID_SFP: 2431 /* 2432 * In accordance with SFF-8472 Diagnostic Monitoring 2433 * Interface for Optical Transceivers section 4 Memory 2434 * Organization two 2-wire addresses are defined. 2435 */ 2436 switch (dev_addr) { 2437 /* Base information */ 2438 case EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_BASE: 2439 /* 2440 * MCDI page 0 should be used to access lower 2441 * page 0 (0x00 - 0x7f) at the device address 0xA0. 2442 */ 2443 mcdi_lower_page = 0; 2444 /* 2445 * MCDI page 1 should be used to access upper 2446 * page 0 (0x80 - 0xff) at the device address 0xA0. 2447 */ 2448 mcdi_upper_page = 1; 2449 break; 2450 /* Diagnostics */ 2451 case EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_DDM: 2452 /* 2453 * MCDI page 2 should be used to access lower 2454 * page 0 (0x00 - 0x7f) at the device address 0xA2. 2455 */ 2456 mcdi_lower_page = 2; 2457 /* 2458 * MCDI page 3 should be used to access upper 2459 * page 0 (0x80 - 0xff) at the device address 0xA2. 2460 */ 2461 mcdi_upper_page = 3; 2462 break; 2463 default: 2464 rc = ENOTSUP; 2465 goto fail3; 2466 } 2467 break; 2468 case EFX_SFF_TRANSCEIVER_ID_QSFP: 2469 case EFX_SFF_TRANSCEIVER_ID_QSFP_PLUS: 2470 case EFX_SFF_TRANSCEIVER_ID_QSFP28: 2471 switch (dev_addr) { 2472 case EFX_PHY_MEDIA_INFO_DEV_ADDR_QSFP: 2473 /* 2474 * MCDI page -1 should be used to access lower page 0 2475 * (0x00 - 0x7f). 2476 */ 2477 mcdi_lower_page = (uint32_t)-1; 2478 /* 2479 * MCDI page 0 should be used to access upper page 0 2480 * (0x80h - 0xff). 2481 */ 2482 mcdi_upper_page = 0; 2483 break; 2484 default: 2485 rc = ENOTSUP; 2486 goto fail3; 2487 } 2488 break; 2489 default: 2490 rc = ENOTSUP; 2491 goto fail3; 2492 } 2493 2494 EFX_STATIC_ASSERT(EFX_PHY_MEDIA_INFO_PAGE_SIZE <= 0xFF); 2495 2496 if (offset < EFX_PHY_MEDIA_INFO_PAGE_SIZE) { 2497 size_t read_len = 2498 MIN(len, EFX_PHY_MEDIA_INFO_PAGE_SIZE - offset); 2499 2500 rc = efx_mcdi_get_phy_media_info(enp, 2501 mcdi_lower_page, (uint8_t)offset, (uint8_t)read_len, data); 2502 if (rc != 0) 2503 goto fail4; 2504 2505 data += read_len; 2506 len -= read_len; 2507 2508 offset = 0; 2509 } else { 2510 offset -= EFX_PHY_MEDIA_INFO_PAGE_SIZE; 2511 } 2512 2513 if (len > 0) { 2514 EFSYS_ASSERT3U(len, <=, EFX_PHY_MEDIA_INFO_PAGE_SIZE); 2515 EFSYS_ASSERT3U(offset, <, EFX_PHY_MEDIA_INFO_PAGE_SIZE); 2516 2517 rc = efx_mcdi_get_phy_media_info(enp, 2518 mcdi_upper_page, (uint8_t)offset, (uint8_t)len, data); 2519 if (rc != 0) 2520 goto fail5; 2521 } 2522 2523 return (0); 2524 2525 fail5: 2526 EFSYS_PROBE(fail5); 2527 fail4: 2528 EFSYS_PROBE(fail4); 2529 fail3: 2530 EFSYS_PROBE(fail3); 2531 fail2: 2532 EFSYS_PROBE(fail2); 2533 fail1: 2534 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2535 2536 return (rc); 2537 } 2538 2539 #if EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() 2540 2541 #define INIT_EVQ_MAXNBUFS MC_CMD_INIT_EVQ_V2_IN_DMA_ADDR_MAXNUM 2542 2543 #if EFX_OPTS_EF10() 2544 # if (INIT_EVQ_MAXNBUFS < EF10_EVQ_MAXNBUFS) 2545 # error "INIT_EVQ_MAXNBUFS too small" 2546 # endif 2547 #endif /* EFX_OPTS_EF10 */ 2548 #if EFSYS_OPT_RIVERHEAD 2549 # if (INIT_EVQ_MAXNBUFS < RHEAD_EVQ_MAXNBUFS) 2550 # error "INIT_EVQ_MAXNBUFS too small" 2551 # endif 2552 #endif /* EFSYS_OPT_RIVERHEAD */ 2553 2554 __checkReturn efx_rc_t 2555 efx_mcdi_init_evq( 2556 __in efx_nic_t *enp, 2557 __in unsigned int instance, 2558 __in efsys_mem_t *esmp, 2559 __in size_t nevs, 2560 __in uint32_t irq, 2561 __in uint32_t us, 2562 __in uint32_t flags, 2563 __in boolean_t low_latency) 2564 { 2565 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 2566 efx_mcdi_req_t req; 2567 EFX_MCDI_DECLARE_BUF(payload, 2568 MC_CMD_INIT_EVQ_V2_IN_LEN(INIT_EVQ_MAXNBUFS), 2569 MC_CMD_INIT_EVQ_V2_OUT_LEN); 2570 boolean_t interrupting; 2571 int ev_extended_width; 2572 int ev_cut_through; 2573 int ev_merge; 2574 unsigned int evq_type; 2575 efx_qword_t *dma_addr; 2576 uint64_t addr; 2577 int npages; 2578 int i; 2579 efx_rc_t rc; 2580 2581 npages = efx_evq_nbufs(enp, nevs, flags); 2582 if (npages > INIT_EVQ_MAXNBUFS) { 2583 rc = EINVAL; 2584 goto fail1; 2585 } 2586 2587 req.emr_cmd = MC_CMD_INIT_EVQ; 2588 req.emr_in_buf = payload; 2589 req.emr_in_length = MC_CMD_INIT_EVQ_V2_IN_LEN(npages); 2590 req.emr_out_buf = payload; 2591 req.emr_out_length = MC_CMD_INIT_EVQ_V2_OUT_LEN; 2592 2593 MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_SIZE, nevs); 2594 MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_INSTANCE, instance); 2595 MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_IRQ_NUM, irq); 2596 2597 interrupting = ((flags & EFX_EVQ_FLAGS_NOTIFY_MASK) == 2598 EFX_EVQ_FLAGS_NOTIFY_INTERRUPT); 2599 2600 if (encp->enc_init_evq_v2_supported) { 2601 /* 2602 * On Medford the low latency license is required to enable RX 2603 * and event cut through and to disable RX batching. If event 2604 * queue type in flags is auto, we let the firmware decide the 2605 * settings to use. If the adapter has a low latency license, 2606 * it will choose the best settings for low latency, otherwise 2607 * it will choose the best settings for throughput. 2608 */ 2609 switch (flags & EFX_EVQ_FLAGS_TYPE_MASK) { 2610 case EFX_EVQ_FLAGS_TYPE_AUTO: 2611 evq_type = MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_AUTO; 2612 break; 2613 case EFX_EVQ_FLAGS_TYPE_THROUGHPUT: 2614 evq_type = MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_THROUGHPUT; 2615 break; 2616 case EFX_EVQ_FLAGS_TYPE_LOW_LATENCY: 2617 evq_type = MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_LOW_LATENCY; 2618 break; 2619 default: 2620 rc = EINVAL; 2621 goto fail2; 2622 } 2623 /* EvQ type controls merging, no manual settings */ 2624 ev_merge = 0; 2625 ev_cut_through = 0; 2626 } else { 2627 /* EvQ types other than manual are not supported */ 2628 evq_type = MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_MANUAL; 2629 /* 2630 * On Huntington RX and TX event batching can only be requested 2631 * together (even if the datapath firmware doesn't actually 2632 * support RX batching). If event cut through is enabled no RX 2633 * batching will occur. 2634 * 2635 * So always enable RX and TX event batching, and enable event 2636 * cut through if we want low latency operation. 2637 */ 2638 ev_merge = 1; 2639 switch (flags & EFX_EVQ_FLAGS_TYPE_MASK) { 2640 case EFX_EVQ_FLAGS_TYPE_AUTO: 2641 ev_cut_through = low_latency ? 1 : 0; 2642 break; 2643 case EFX_EVQ_FLAGS_TYPE_THROUGHPUT: 2644 ev_cut_through = 0; 2645 break; 2646 case EFX_EVQ_FLAGS_TYPE_LOW_LATENCY: 2647 ev_cut_through = 1; 2648 break; 2649 default: 2650 rc = EINVAL; 2651 goto fail2; 2652 } 2653 } 2654 2655 /* 2656 * On EF100, extended width event queues have a different event 2657 * descriptor layout and are used to support descriptor proxy queues. 2658 */ 2659 ev_extended_width = 0; 2660 #if EFSYS_OPT_EV_EXTENDED_WIDTH 2661 if (encp->enc_init_evq_extended_width_supported) { 2662 if (flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) 2663 ev_extended_width = 1; 2664 } 2665 #endif 2666 2667 MCDI_IN_POPULATE_DWORD_8(req, INIT_EVQ_V2_IN_FLAGS, 2668 INIT_EVQ_V2_IN_FLAG_INTERRUPTING, interrupting, 2669 INIT_EVQ_V2_IN_FLAG_RPTR_DOS, 0, 2670 INIT_EVQ_V2_IN_FLAG_INT_ARMD, 0, 2671 INIT_EVQ_V2_IN_FLAG_CUT_THRU, ev_cut_through, 2672 INIT_EVQ_V2_IN_FLAG_RX_MERGE, ev_merge, 2673 INIT_EVQ_V2_IN_FLAG_TX_MERGE, ev_merge, 2674 INIT_EVQ_V2_IN_FLAG_TYPE, evq_type, 2675 INIT_EVQ_V2_IN_FLAG_EXT_WIDTH, ev_extended_width); 2676 2677 /* If the value is zero then disable the timer */ 2678 if (us == 0) { 2679 MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_MODE, 2680 MC_CMD_INIT_EVQ_V2_IN_TMR_MODE_DIS); 2681 MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_LOAD, 0); 2682 MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_RELOAD, 0); 2683 } else { 2684 unsigned int ticks; 2685 2686 if ((rc = efx_ev_usecs_to_ticks(enp, us, &ticks)) != 0) 2687 goto fail3; 2688 2689 MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_MODE, 2690 MC_CMD_INIT_EVQ_V2_IN_TMR_INT_HLDOFF); 2691 MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_LOAD, ticks); 2692 MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_RELOAD, ticks); 2693 } 2694 2695 MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_COUNT_MODE, 2696 MC_CMD_INIT_EVQ_V2_IN_COUNT_MODE_DIS); 2697 MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_COUNT_THRSHLD, 0); 2698 2699 dma_addr = MCDI_IN2(req, efx_qword_t, INIT_EVQ_V2_IN_DMA_ADDR); 2700 addr = EFSYS_MEM_ADDR(esmp); 2701 2702 for (i = 0; i < npages; i++) { 2703 EFX_POPULATE_QWORD_2(*dma_addr, 2704 EFX_DWORD_1, (uint32_t)(addr >> 32), 2705 EFX_DWORD_0, (uint32_t)(addr & 0xffffffff)); 2706 2707 dma_addr++; 2708 addr += EFX_BUF_SIZE; 2709 } 2710 2711 efx_mcdi_execute(enp, &req); 2712 2713 if (req.emr_rc != 0) { 2714 rc = req.emr_rc; 2715 goto fail4; 2716 } 2717 2718 if (encp->enc_init_evq_v2_supported) { 2719 if (req.emr_out_length_used < MC_CMD_INIT_EVQ_V2_OUT_LEN) { 2720 rc = EMSGSIZE; 2721 goto fail5; 2722 } 2723 EFSYS_PROBE1(mcdi_evq_flags, uint32_t, 2724 MCDI_OUT_DWORD(req, INIT_EVQ_V2_OUT_FLAGS)); 2725 } else { 2726 if (req.emr_out_length_used < MC_CMD_INIT_EVQ_OUT_LEN) { 2727 rc = EMSGSIZE; 2728 goto fail6; 2729 } 2730 } 2731 2732 /* NOTE: ignore the returned IRQ param as firmware does not set it. */ 2733 2734 return (0); 2735 2736 fail6: 2737 EFSYS_PROBE(fail6); 2738 fail5: 2739 EFSYS_PROBE(fail5); 2740 fail4: 2741 EFSYS_PROBE(fail4); 2742 fail3: 2743 EFSYS_PROBE(fail3); 2744 fail2: 2745 EFSYS_PROBE(fail2); 2746 fail1: 2747 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2748 2749 return (rc); 2750 } 2751 2752 __checkReturn efx_rc_t 2753 efx_mcdi_fini_evq( 2754 __in efx_nic_t *enp, 2755 __in uint32_t instance) 2756 { 2757 efx_mcdi_req_t req; 2758 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FINI_EVQ_IN_LEN, 2759 MC_CMD_FINI_EVQ_OUT_LEN); 2760 efx_rc_t rc; 2761 2762 req.emr_cmd = MC_CMD_FINI_EVQ; 2763 req.emr_in_buf = payload; 2764 req.emr_in_length = MC_CMD_FINI_EVQ_IN_LEN; 2765 req.emr_out_buf = payload; 2766 req.emr_out_length = MC_CMD_FINI_EVQ_OUT_LEN; 2767 2768 MCDI_IN_SET_DWORD(req, FINI_EVQ_IN_INSTANCE, instance); 2769 2770 efx_mcdi_execute_quiet(enp, &req); 2771 2772 if (req.emr_rc != 0) { 2773 rc = req.emr_rc; 2774 goto fail1; 2775 } 2776 2777 return (0); 2778 2779 fail1: 2780 /* 2781 * EALREADY is not an error, but indicates that the MC has rebooted and 2782 * that the EVQ has already been destroyed. 2783 */ 2784 if (rc != EALREADY) 2785 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2786 2787 return (rc); 2788 } 2789 2790 __checkReturn efx_rc_t 2791 efx_mcdi_init_rxq( 2792 __in efx_nic_t *enp, 2793 __in uint32_t ndescs, 2794 __in efx_evq_t *eep, 2795 __in uint32_t label, 2796 __in uint32_t instance, 2797 __in efsys_mem_t *esmp, 2798 __in const efx_mcdi_init_rxq_params_t *params) 2799 { 2800 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 2801 efx_mcdi_req_t req; 2802 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_INIT_RXQ_V5_IN_LEN, 2803 MC_CMD_INIT_RXQ_V5_OUT_LEN); 2804 int npages = efx_rxq_nbufs(enp, ndescs); 2805 int i; 2806 efx_qword_t *dma_addr; 2807 uint64_t addr; 2808 efx_rc_t rc; 2809 uint32_t dma_mode; 2810 boolean_t want_outer_classes; 2811 boolean_t no_cont_ev; 2812 2813 EFSYS_ASSERT3U(ndescs, <=, encp->enc_rxq_max_ndescs); 2814 2815 if ((esmp == NULL) || 2816 (EFSYS_MEM_SIZE(esmp) < efx_rxq_size(enp, ndescs))) { 2817 rc = EINVAL; 2818 goto fail1; 2819 } 2820 2821 no_cont_ev = (eep->ee_flags & EFX_EVQ_FLAGS_NO_CONT_EV); 2822 if ((no_cont_ev == B_TRUE) && (params->disable_scatter == B_FALSE)) { 2823 /* TODO: Support scatter in NO_CONT_EV mode */ 2824 rc = EINVAL; 2825 goto fail2; 2826 } 2827 2828 if (params->ps_buf_size > 0) 2829 dma_mode = MC_CMD_INIT_RXQ_EXT_IN_PACKED_STREAM; 2830 else if (params->es_bufs_per_desc > 0) 2831 dma_mode = MC_CMD_INIT_RXQ_V3_IN_EQUAL_STRIDE_SUPER_BUFFER; 2832 else 2833 dma_mode = MC_CMD_INIT_RXQ_EXT_IN_SINGLE_PACKET; 2834 2835 if (encp->enc_tunnel_encapsulations_supported != 0 && 2836 !params->want_inner_classes) { 2837 /* 2838 * WANT_OUTER_CLASSES can only be specified on hardware which 2839 * supports tunnel encapsulation offloads, even though it is 2840 * effectively the behaviour the hardware gives. 2841 * 2842 * Also, on hardware which does support such offloads, older 2843 * firmware rejects the flag if the offloads are not supported 2844 * by the current firmware variant, which means this may fail if 2845 * the capabilities are not updated when the firmware variant 2846 * changes. This is not an issue on newer firmware, as it was 2847 * changed in bug 69842 (v6.4.2.1007) to permit this flag to be 2848 * specified on all firmware variants. 2849 */ 2850 want_outer_classes = B_TRUE; 2851 } else { 2852 want_outer_classes = B_FALSE; 2853 } 2854 2855 req.emr_cmd = MC_CMD_INIT_RXQ; 2856 req.emr_in_buf = payload; 2857 req.emr_in_length = MC_CMD_INIT_RXQ_V5_IN_LEN; 2858 req.emr_out_buf = payload; 2859 req.emr_out_length = MC_CMD_INIT_RXQ_V5_OUT_LEN; 2860 2861 MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_SIZE, ndescs); 2862 MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_TARGET_EVQ, eep->ee_index); 2863 MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_LABEL, label); 2864 MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_INSTANCE, instance); 2865 MCDI_IN_POPULATE_DWORD_10(req, INIT_RXQ_EXT_IN_FLAGS, 2866 INIT_RXQ_EXT_IN_FLAG_BUFF_MODE, 0, 2867 INIT_RXQ_EXT_IN_FLAG_HDR_SPLIT, 0, 2868 INIT_RXQ_EXT_IN_FLAG_TIMESTAMP, 0, 2869 INIT_RXQ_EXT_IN_CRC_MODE, 0, 2870 INIT_RXQ_EXT_IN_FLAG_PREFIX, 1, 2871 INIT_RXQ_EXT_IN_FLAG_DISABLE_SCATTER, params->disable_scatter, 2872 INIT_RXQ_EXT_IN_DMA_MODE, 2873 dma_mode, 2874 INIT_RXQ_EXT_IN_PACKED_STREAM_BUFF_SIZE, params->ps_buf_size, 2875 INIT_RXQ_EXT_IN_FLAG_WANT_OUTER_CLASSES, want_outer_classes, 2876 INIT_RXQ_EXT_IN_FLAG_NO_CONT_EV, no_cont_ev); 2877 MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_OWNER_ID, 0); 2878 MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_PORT_ID, enp->en_vport_id); 2879 2880 if (params->es_bufs_per_desc > 0) { 2881 MCDI_IN_SET_DWORD(req, 2882 INIT_RXQ_V3_IN_ES_PACKET_BUFFERS_PER_BUCKET, 2883 params->es_bufs_per_desc); 2884 MCDI_IN_SET_DWORD(req, 2885 INIT_RXQ_V3_IN_ES_MAX_DMA_LEN, params->es_max_dma_len); 2886 MCDI_IN_SET_DWORD(req, 2887 INIT_RXQ_V3_IN_ES_PACKET_STRIDE, params->es_buf_stride); 2888 MCDI_IN_SET_DWORD(req, 2889 INIT_RXQ_V3_IN_ES_HEAD_OF_LINE_BLOCK_TIMEOUT, 2890 params->hol_block_timeout); 2891 } 2892 2893 if (encp->enc_init_rxq_with_buffer_size) 2894 MCDI_IN_SET_DWORD(req, INIT_RXQ_V4_IN_BUFFER_SIZE_BYTES, 2895 params->buf_size); 2896 2897 MCDI_IN_SET_DWORD(req, INIT_RXQ_V5_IN_RX_PREFIX_ID, params->prefix_id); 2898 2899 dma_addr = MCDI_IN2(req, efx_qword_t, INIT_RXQ_IN_DMA_ADDR); 2900 addr = EFSYS_MEM_ADDR(esmp); 2901 2902 for (i = 0; i < npages; i++) { 2903 EFX_POPULATE_QWORD_2(*dma_addr, 2904 EFX_DWORD_1, (uint32_t)(addr >> 32), 2905 EFX_DWORD_0, (uint32_t)(addr & 0xffffffff)); 2906 2907 dma_addr++; 2908 addr += EFX_BUF_SIZE; 2909 } 2910 2911 efx_mcdi_execute(enp, &req); 2912 2913 if (req.emr_rc != 0) { 2914 rc = req.emr_rc; 2915 goto fail3; 2916 } 2917 2918 return (0); 2919 2920 fail3: 2921 EFSYS_PROBE(fail3); 2922 fail2: 2923 EFSYS_PROBE(fail2); 2924 fail1: 2925 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2926 2927 return (rc); 2928 } 2929 2930 __checkReturn efx_rc_t 2931 efx_mcdi_fini_rxq( 2932 __in efx_nic_t *enp, 2933 __in uint32_t instance) 2934 { 2935 efx_mcdi_req_t req; 2936 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FINI_RXQ_IN_LEN, 2937 MC_CMD_FINI_RXQ_OUT_LEN); 2938 efx_rc_t rc; 2939 2940 req.emr_cmd = MC_CMD_FINI_RXQ; 2941 req.emr_in_buf = payload; 2942 req.emr_in_length = MC_CMD_FINI_RXQ_IN_LEN; 2943 req.emr_out_buf = payload; 2944 req.emr_out_length = MC_CMD_FINI_RXQ_OUT_LEN; 2945 2946 MCDI_IN_SET_DWORD(req, FINI_RXQ_IN_INSTANCE, instance); 2947 2948 efx_mcdi_execute_quiet(enp, &req); 2949 2950 if (req.emr_rc != 0) { 2951 rc = req.emr_rc; 2952 goto fail1; 2953 } 2954 2955 return (0); 2956 2957 fail1: 2958 /* 2959 * EALREADY is not an error, but indicates that the MC has rebooted and 2960 * that the RXQ has already been destroyed. 2961 */ 2962 if (rc != EALREADY) 2963 EFSYS_PROBE1(fail1, efx_rc_t, rc); 2964 2965 return (rc); 2966 } 2967 2968 __checkReturn efx_rc_t 2969 efx_mcdi_init_txq( 2970 __in efx_nic_t *enp, 2971 __in uint32_t ndescs, 2972 __in uint32_t target_evq, 2973 __in uint32_t label, 2974 __in uint32_t instance, 2975 __in uint16_t flags, 2976 __in efsys_mem_t *esmp) 2977 { 2978 efx_mcdi_req_t req; 2979 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_INIT_TXQ_EXT_IN_LEN, 2980 MC_CMD_INIT_TXQ_OUT_LEN); 2981 efx_qword_t *dma_addr; 2982 uint64_t addr; 2983 int npages; 2984 int i; 2985 efx_rc_t rc; 2986 2987 EFSYS_ASSERT(MC_CMD_INIT_TXQ_EXT_IN_DMA_ADDR_MAXNUM >= 2988 efx_txq_nbufs(enp, enp->en_nic_cfg.enc_txq_max_ndescs)); 2989 2990 if ((esmp == NULL) || 2991 (EFSYS_MEM_SIZE(esmp) < efx_txq_size(enp, ndescs))) { 2992 rc = EINVAL; 2993 goto fail1; 2994 } 2995 2996 npages = efx_txq_nbufs(enp, ndescs); 2997 if (MC_CMD_INIT_TXQ_IN_LEN(npages) > sizeof (payload)) { 2998 rc = EINVAL; 2999 goto fail2; 3000 } 3001 3002 req.emr_cmd = MC_CMD_INIT_TXQ; 3003 req.emr_in_buf = payload; 3004 req.emr_in_length = MC_CMD_INIT_TXQ_IN_LEN(npages); 3005 req.emr_out_buf = payload; 3006 req.emr_out_length = MC_CMD_INIT_TXQ_OUT_LEN; 3007 3008 MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_SIZE, ndescs); 3009 MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_TARGET_EVQ, target_evq); 3010 MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_LABEL, label); 3011 MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_INSTANCE, instance); 3012 3013 MCDI_IN_POPULATE_DWORD_9(req, INIT_TXQ_IN_FLAGS, 3014 INIT_TXQ_IN_FLAG_BUFF_MODE, 0, 3015 INIT_TXQ_IN_FLAG_IP_CSUM_DIS, 3016 (flags & EFX_TXQ_CKSUM_IPV4) ? 0 : 1, 3017 INIT_TXQ_IN_FLAG_TCP_CSUM_DIS, 3018 (flags & EFX_TXQ_CKSUM_TCPUDP) ? 0 : 1, 3019 INIT_TXQ_EXT_IN_FLAG_INNER_IP_CSUM_EN, 3020 (flags & EFX_TXQ_CKSUM_INNER_IPV4) ? 1 : 0, 3021 INIT_TXQ_EXT_IN_FLAG_INNER_TCP_CSUM_EN, 3022 (flags & EFX_TXQ_CKSUM_INNER_TCPUDP) ? 1 : 0, 3023 INIT_TXQ_EXT_IN_FLAG_TSOV2_EN, (flags & EFX_TXQ_FATSOV2) ? 1 : 0, 3024 INIT_TXQ_IN_FLAG_TCP_UDP_ONLY, 0, 3025 INIT_TXQ_IN_CRC_MODE, 0, 3026 INIT_TXQ_IN_FLAG_TIMESTAMP, 0); 3027 3028 MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_OWNER_ID, 0); 3029 MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_PORT_ID, enp->en_vport_id); 3030 3031 dma_addr = MCDI_IN2(req, efx_qword_t, INIT_TXQ_IN_DMA_ADDR); 3032 addr = EFSYS_MEM_ADDR(esmp); 3033 3034 for (i = 0; i < npages; i++) { 3035 EFX_POPULATE_QWORD_2(*dma_addr, 3036 EFX_DWORD_1, (uint32_t)(addr >> 32), 3037 EFX_DWORD_0, (uint32_t)(addr & 0xffffffff)); 3038 3039 dma_addr++; 3040 addr += EFX_BUF_SIZE; 3041 } 3042 3043 efx_mcdi_execute(enp, &req); 3044 3045 if (req.emr_rc != 0) { 3046 rc = req.emr_rc; 3047 goto fail3; 3048 } 3049 3050 return (0); 3051 3052 fail3: 3053 EFSYS_PROBE(fail3); 3054 fail2: 3055 EFSYS_PROBE(fail2); 3056 fail1: 3057 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3058 3059 return (rc); 3060 } 3061 3062 __checkReturn efx_rc_t 3063 efx_mcdi_fini_txq( 3064 __in efx_nic_t *enp, 3065 __in uint32_t instance) 3066 { 3067 efx_mcdi_req_t req; 3068 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FINI_TXQ_IN_LEN, 3069 MC_CMD_FINI_TXQ_OUT_LEN); 3070 efx_rc_t rc; 3071 3072 req.emr_cmd = MC_CMD_FINI_TXQ; 3073 req.emr_in_buf = payload; 3074 req.emr_in_length = MC_CMD_FINI_TXQ_IN_LEN; 3075 req.emr_out_buf = payload; 3076 req.emr_out_length = MC_CMD_FINI_TXQ_OUT_LEN; 3077 3078 MCDI_IN_SET_DWORD(req, FINI_TXQ_IN_INSTANCE, instance); 3079 3080 efx_mcdi_execute_quiet(enp, &req); 3081 3082 if (req.emr_rc != 0) { 3083 rc = req.emr_rc; 3084 goto fail1; 3085 } 3086 3087 return (0); 3088 3089 fail1: 3090 /* 3091 * EALREADY is not an error, but indicates that the MC has rebooted and 3092 * that the TXQ has already been destroyed. 3093 */ 3094 if (rc != EALREADY) 3095 EFSYS_PROBE1(fail1, efx_rc_t, rc); 3096 3097 return (rc); 3098 } 3099 3100 #endif /* EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() */ 3101 3102 #endif /* EFSYS_OPT_MCDI */ 3103