1 /*- 2 * Copyright 2009 Solarflare Communications Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 #include "efsys.h" 26 #include "efx.h" 27 #include "efx_impl.h" 28 29 #if EFSYS_OPT_SIENA 30 31 static __checkReturn int 32 siena_nic_get_partn_mask( 33 __in efx_nic_t *enp, 34 __out unsigned int *maskp) 35 { 36 efx_mcdi_req_t req; 37 uint8_t outbuf[MC_CMD_NVRAM_TYPES_OUT_LEN]; 38 int rc; 39 40 req.emr_cmd = MC_CMD_NVRAM_TYPES; 41 EFX_STATIC_ASSERT(MC_CMD_NVRAM_TYPES_IN_LEN == 0); 42 req.emr_in_buf = NULL; 43 req.emr_in_length = 0; 44 req.emr_out_buf = outbuf; 45 req.emr_out_length = sizeof (outbuf); 46 47 efx_mcdi_execute(enp, &req); 48 49 if (req.emr_rc != 0) { 50 rc = req.emr_rc; 51 goto fail1; 52 } 53 54 if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) { 55 rc = EMSGSIZE; 56 goto fail2; 57 } 58 59 *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES); 60 61 return (0); 62 63 fail2: 64 EFSYS_PROBE(fail2); 65 fail1: 66 EFSYS_PROBE1(fail1, int, rc); 67 68 return (rc); 69 } 70 71 static __checkReturn int 72 siena_nic_exit_assertion_handler( 73 __in efx_nic_t *enp) 74 { 75 efx_mcdi_req_t req; 76 uint8_t payload[MC_CMD_REBOOT_IN_LEN]; 77 int rc; 78 79 req.emr_cmd = MC_CMD_REBOOT; 80 req.emr_in_buf = payload; 81 req.emr_in_length = MC_CMD_REBOOT_IN_LEN; 82 EFX_STATIC_ASSERT(MC_CMD_REBOOT_OUT_LEN == 0); 83 req.emr_out_buf = NULL; 84 req.emr_out_length = 0; 85 86 MCDI_IN_SET_DWORD(req, REBOOT_IN_FLAGS, 87 MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION); 88 89 efx_mcdi_execute(enp, &req); 90 91 if (req.emr_rc != 0 && req.emr_rc != EIO) { 92 rc = req.emr_rc; 93 goto fail1; 94 } 95 96 return (0); 97 98 fail1: 99 EFSYS_PROBE1(fail1, int, rc); 100 101 return (rc); 102 } 103 104 static __checkReturn int 105 siena_nic_read_assertion( 106 __in efx_nic_t *enp) 107 { 108 efx_mcdi_req_t req; 109 uint8_t payload[MAX(MC_CMD_GET_ASSERTS_IN_LEN, 110 MC_CMD_GET_ASSERTS_OUT_LEN)]; 111 const char *reason; 112 unsigned int flags; 113 unsigned int index; 114 unsigned int ofst; 115 int retry; 116 int rc; 117 118 /* 119 * Before we attempt to chat to the MC, we should verify that the MC 120 * isn't in it's assertion handler, either due to a previous reboot, 121 * or because we're reinitializing due to an eec_exception(). 122 * 123 * Use GET_ASSERTS to read any assertion state that may be present. 124 * Retry this command twice. Once because a boot-time assertion failure 125 * might cause the 1st MCDI request to fail. And once again because 126 * we might race with siena_nic_exit_assertion_handler() running on the 127 * other port. 128 */ 129 retry = 2; 130 do { 131 req.emr_cmd = MC_CMD_GET_ASSERTS; 132 req.emr_in_buf = payload; 133 req.emr_in_length = MC_CMD_GET_ASSERTS_IN_LEN; 134 req.emr_out_buf = payload; 135 req.emr_out_length = MC_CMD_GET_ASSERTS_OUT_LEN; 136 137 MCDI_IN_SET_DWORD(req, GET_ASSERTS_IN_CLEAR, 1); 138 efx_mcdi_execute(enp, &req); 139 140 } while ((req.emr_rc == EINTR || req.emr_rc == EIO) && retry-- > 0); 141 142 if (req.emr_rc != 0) { 143 rc = req.emr_rc; 144 goto fail1; 145 } 146 147 if (req.emr_out_length_used < MC_CMD_GET_ASSERTS_OUT_LEN) { 148 rc = EMSGSIZE; 149 goto fail2; 150 } 151 152 /* Print out any assertion state recorded */ 153 flags = MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_GLOBAL_FLAGS); 154 if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS) 155 return (0); 156 157 reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL) 158 ? "system-level assertion" 159 : (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL) 160 ? "thread-level assertion" 161 : (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED) 162 ? "watchdog reset" 163 : "unknown assertion"; 164 EFSYS_PROBE3(mcpu_assertion, 165 const char *, reason, unsigned int, 166 MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_SAVED_PC_OFFS), 167 unsigned int, 168 MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_THREAD_OFFS)); 169 170 /* Print out the registers */ 171 ofst = MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST; 172 for (index = 1; index < 32; index++) { 173 EFSYS_PROBE2(mcpu_register, unsigned int, index, unsigned int, 174 EFX_DWORD_FIELD(*MCDI_OUT(req, efx_dword_t, ofst), 175 EFX_DWORD_0)); 176 ofst += sizeof (efx_dword_t); 177 } 178 EFSYS_ASSERT(ofst <= MC_CMD_GET_ASSERTS_OUT_LEN); 179 180 return (0); 181 182 fail2: 183 EFSYS_PROBE(fail2); 184 fail1: 185 EFSYS_PROBE1(fail1, int, rc); 186 187 return (rc); 188 } 189 190 static __checkReturn int 191 siena_nic_attach( 192 __in efx_nic_t *enp, 193 __in boolean_t attach) 194 { 195 efx_mcdi_req_t req; 196 uint8_t payload[MC_CMD_DRV_ATTACH_IN_LEN]; 197 int rc; 198 199 req.emr_cmd = MC_CMD_DRV_ATTACH; 200 req.emr_in_buf = payload; 201 req.emr_in_length = MC_CMD_DRV_ATTACH_IN_LEN; 202 req.emr_out_buf = NULL; 203 req.emr_out_length = 0; 204 205 MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_NEW_STATE, attach ? 1 : 0); 206 MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_UPDATE, 1); 207 208 efx_mcdi_execute(enp, &req); 209 210 if (req.emr_rc != 0) { 211 rc = req.emr_rc; 212 goto fail1; 213 } 214 215 if (req.emr_out_length_used < MC_CMD_DRV_ATTACH_OUT_LEN) { 216 rc = EMSGSIZE; 217 goto fail2; 218 } 219 220 return (0); 221 222 fail2: 223 EFSYS_PROBE(fail2); 224 fail1: 225 EFSYS_PROBE1(fail1, int, rc); 226 227 return (rc); 228 } 229 230 #if EFSYS_OPT_PCIE_TUNE 231 232 __checkReturn int 233 siena_nic_pcie_extended_sync( 234 __in efx_nic_t *enp) 235 { 236 uint8_t inbuf[MC_CMD_WORKAROUND_IN_LEN]; 237 efx_mcdi_req_t req; 238 int rc; 239 240 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 241 242 req.emr_cmd = MC_CMD_WORKAROUND; 243 req.emr_in_buf = inbuf; 244 req.emr_in_length = sizeof (inbuf); 245 EFX_STATIC_ASSERT(MC_CMD_WORKAROUND_OUT_LEN == 0); 246 req.emr_out_buf = NULL; 247 req.emr_out_length = 0; 248 249 MCDI_IN_SET_DWORD(req, WORKAROUND_IN_TYPE, MC_CMD_WORKAROUND_BUG17230); 250 MCDI_IN_SET_DWORD(req, WORKAROUND_IN_ENABLED, 1); 251 252 efx_mcdi_execute(enp, &req); 253 254 if (req.emr_rc != 0) { 255 rc = req.emr_rc; 256 goto fail1; 257 } 258 259 return (0); 260 261 fail1: 262 EFSYS_PROBE1(fail1, int, rc); 263 264 return (rc); 265 } 266 267 #endif /* EFSYS_OPT_PCIE_TUNE */ 268 269 static __checkReturn int 270 siena_board_cfg( 271 __in efx_nic_t *enp) 272 { 273 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 274 efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip); 275 uint8_t outbuf[MAX(MC_CMD_GET_BOARD_CFG_OUT_LEN, 276 MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN)]; 277 efx_mcdi_req_t req; 278 uint8_t *src; 279 int rc; 280 281 /* Board configuration */ 282 req.emr_cmd = MC_CMD_GET_BOARD_CFG; 283 EFX_STATIC_ASSERT(MC_CMD_GET_BOARD_CFG_IN_LEN == 0); 284 req.emr_in_buf = NULL; 285 req.emr_in_length = 0; 286 req.emr_out_buf = outbuf; 287 req.emr_out_length = MC_CMD_GET_BOARD_CFG_OUT_LEN; 288 289 efx_mcdi_execute(enp, &req); 290 291 if (req.emr_rc != 0) { 292 rc = req.emr_rc; 293 goto fail1; 294 } 295 296 if (req.emr_out_length_used < MC_CMD_GET_BOARD_CFG_OUT_LEN) { 297 rc = EMSGSIZE; 298 goto fail2; 299 } 300 301 if (emip->emi_port == 1) 302 src = MCDI_OUT2(req, uint8_t, 303 GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0); 304 else 305 src = MCDI_OUT2(req, uint8_t, 306 GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1); 307 EFX_MAC_ADDR_COPY(encp->enc_mac_addr, src); 308 309 encp->enc_board_type = MCDI_OUT_DWORD(req, 310 GET_BOARD_CFG_OUT_BOARD_TYPE); 311 312 /* Resource limits */ 313 req.emr_cmd = MC_CMD_GET_RESOURCE_LIMITS; 314 EFX_STATIC_ASSERT(MC_CMD_GET_RESOURCE_LIMITS_IN_LEN == 0); 315 req.emr_in_buf = NULL; 316 req.emr_in_length = 0; 317 req.emr_out_buf = outbuf; 318 req.emr_out_length = MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN; 319 320 efx_mcdi_execute(enp, &req); 321 322 if (req.emr_rc == 0) { 323 if (req.emr_out_length_used < MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN) { 324 rc = EMSGSIZE; 325 goto fail3; 326 } 327 328 encp->enc_evq_limit = MCDI_OUT_DWORD(req, 329 GET_RESOURCE_LIMITS_OUT_EVQ); 330 encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, 331 MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_TXQ)); 332 encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, 333 MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_RXQ)); 334 } else if (req.emr_rc == ENOTSUP) { 335 encp->enc_evq_limit = 1024; 336 encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET; 337 encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET; 338 } else { 339 rc = req.emr_rc; 340 goto fail4; 341 } 342 343 encp->enc_buftbl_limit = SIENA_SRAM_ROWS - 344 (encp->enc_txq_limit * 16) - (encp->enc_rxq_limit * 64); 345 346 return (0); 347 348 fail4: 349 EFSYS_PROBE(fail4); 350 fail3: 351 EFSYS_PROBE(fail3); 352 fail2: 353 EFSYS_PROBE(fail2); 354 fail1: 355 EFSYS_PROBE1(fail1, int, rc); 356 357 return (rc); 358 } 359 360 static __checkReturn int 361 siena_phy_cfg( 362 __in efx_nic_t *enp) 363 { 364 efx_port_t *epp = &(enp->en_port); 365 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 366 efx_mcdi_req_t req; 367 uint8_t outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN]; 368 int rc; 369 370 req.emr_cmd = MC_CMD_GET_PHY_CFG; 371 EFX_STATIC_ASSERT(MC_CMD_GET_PHY_CFG_IN_LEN == 0); 372 req.emr_in_buf = NULL; 373 req.emr_in_length = 0; 374 req.emr_out_buf = outbuf; 375 req.emr_out_length = sizeof (outbuf); 376 377 efx_mcdi_execute(enp, &req); 378 379 if (req.emr_rc != 0) { 380 rc = req.emr_rc; 381 goto fail1; 382 } 383 384 if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN) { 385 rc = EMSGSIZE; 386 goto fail2; 387 } 388 389 encp->enc_phy_type = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_TYPE); 390 #if EFSYS_OPT_NAMES 391 (void) strncpy(encp->enc_phy_name, 392 MCDI_OUT2(req, char, GET_PHY_CFG_OUT_NAME), 393 MIN(sizeof (encp->enc_phy_name) - 1, 394 MC_CMD_GET_PHY_CFG_OUT_NAME_LEN)); 395 #endif /* EFSYS_OPT_NAMES */ 396 (void) memset(encp->enc_phy_revision, 0, 397 sizeof (encp->enc_phy_revision)); 398 memcpy(encp->enc_phy_revision, 399 MCDI_OUT2(req, char, GET_PHY_CFG_OUT_REVISION), 400 MIN(sizeof (encp->enc_phy_revision) - 1, 401 MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN)); 402 #if EFSYS_OPT_PHY_LED_CONTROL 403 encp->enc_led_mask = ((1 << EFX_PHY_LED_DEFAULT) | 404 (1 << EFX_PHY_LED_OFF) | 405 (1 << EFX_PHY_LED_ON)); 406 #endif /* EFSYS_OPT_PHY_LED_CONTROL */ 407 408 #if EFSYS_OPT_PHY_PROPS 409 encp->enc_phy_nprops = 0; 410 #endif /* EFSYS_OPT_PHY_PROPS */ 411 412 /* Get the media type of the fixed port, if recognised. */ 413 EFX_STATIC_ASSERT(MC_CMD_MEDIA_XAUI == EFX_PHY_MEDIA_XAUI); 414 EFX_STATIC_ASSERT(MC_CMD_MEDIA_CX4 == EFX_PHY_MEDIA_CX4); 415 EFX_STATIC_ASSERT(MC_CMD_MEDIA_KX4 == EFX_PHY_MEDIA_KX4); 416 EFX_STATIC_ASSERT(MC_CMD_MEDIA_XFP == EFX_PHY_MEDIA_XFP); 417 EFX_STATIC_ASSERT(MC_CMD_MEDIA_SFP_PLUS == EFX_PHY_MEDIA_SFP_PLUS); 418 EFX_STATIC_ASSERT(MC_CMD_MEDIA_BASE_T == EFX_PHY_MEDIA_BASE_T); 419 epp->ep_fixed_port_type = 420 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_MEDIA_TYPE); 421 if (epp->ep_fixed_port_type >= EFX_PHY_MEDIA_NTYPES) 422 epp->ep_fixed_port_type = EFX_PHY_MEDIA_INVALID; 423 424 epp->ep_phy_cap_mask = 425 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_SUPPORTED_CAP); 426 #if EFSYS_OPT_PHY_FLAGS 427 encp->enc_phy_flags_mask = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_FLAGS); 428 #endif /* EFSYS_OPT_PHY_FLAGS */ 429 430 encp->enc_port = (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_PRT); 431 432 /* Populate internal state */ 433 encp->enc_siena_channel = 434 (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_CHANNEL); 435 436 #if EFSYS_OPT_PHY_STATS 437 encp->enc_siena_phy_stat_mask = 438 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_STATS_MASK); 439 440 /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */ 441 siena_phy_decode_stats(enp, encp->enc_siena_phy_stat_mask, 442 NULL, &encp->enc_phy_stat_mask, NULL); 443 #endif /* EFSYS_OPT_PHY_STATS */ 444 445 #if EFSYS_OPT_PHY_BIST 446 encp->enc_bist_mask = 0; 447 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 448 GET_PHY_CFG_OUT_BIST_CABLE_SHORT)) 449 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_SHORT); 450 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 451 GET_PHY_CFG_OUT_BIST_CABLE_LONG)) 452 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_LONG); 453 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 454 GET_PHY_CFG_OUT_BIST)) 455 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_NORMAL); 456 #endif /* EFSYS_OPT_BIST */ 457 458 return (0); 459 460 fail2: 461 EFSYS_PROBE(fail2); 462 fail1: 463 EFSYS_PROBE1(fail1, int, rc); 464 465 return (rc); 466 } 467 468 #if EFSYS_OPT_LOOPBACK 469 470 static __checkReturn int 471 siena_loopback_cfg( 472 __in efx_nic_t *enp) 473 { 474 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 475 efx_mcdi_req_t req; 476 uint8_t outbuf[MC_CMD_GET_LOOPBACK_MODES_OUT_LEN]; 477 int rc; 478 479 req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES; 480 EFX_STATIC_ASSERT(MC_CMD_GET_LOOPBACK_MODES_IN_LEN == 0); 481 req.emr_in_buf = NULL; 482 req.emr_in_length = 0; 483 req.emr_out_buf = outbuf; 484 req.emr_out_length = sizeof (outbuf); 485 486 efx_mcdi_execute(enp, &req); 487 488 if (req.emr_rc != 0) { 489 rc = req.emr_rc; 490 goto fail1; 491 } 492 493 if (req.emr_out_length_used < MC_CMD_GET_LOOPBACK_MODES_OUT_LEN) { 494 rc = EMSGSIZE; 495 goto fail2; 496 } 497 498 /* 499 * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree 500 * in siena_phy.c:siena_phy_get_link() 501 */ 502 encp->enc_loopback_types[EFX_LINK_100FDX] = EFX_LOOPBACK_MASK & 503 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_100M) & 504 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED); 505 encp->enc_loopback_types[EFX_LINK_1000FDX] = EFX_LOOPBACK_MASK & 506 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_1G) & 507 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED); 508 encp->enc_loopback_types[EFX_LINK_10000FDX] = EFX_LOOPBACK_MASK & 509 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_10G) & 510 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED); 511 encp->enc_loopback_types[EFX_LINK_UNKNOWN] = 512 (1 << EFX_LOOPBACK_OFF) | 513 encp->enc_loopback_types[EFX_LINK_100FDX] | 514 encp->enc_loopback_types[EFX_LINK_1000FDX] | 515 encp->enc_loopback_types[EFX_LINK_10000FDX]; 516 517 return (0); 518 519 fail2: 520 EFSYS_PROBE(fail2); 521 fail1: 522 EFSYS_PROBE1(fail1, int, rc); 523 524 return (rc); 525 } 526 527 #endif /* EFSYS_OPT_LOOPBACK */ 528 529 #if EFSYS_OPT_MON_STATS 530 531 static __checkReturn int 532 siena_monitor_cfg( 533 __in efx_nic_t *enp) 534 { 535 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 536 efx_mcdi_req_t req; 537 uint8_t outbuf[MCDI_CTL_SDU_LEN_MAX]; 538 int rc; 539 540 req.emr_cmd = MC_CMD_SENSOR_INFO; 541 EFX_STATIC_ASSERT(MC_CMD_SENSOR_INFO_IN_LEN == 0); 542 req.emr_in_buf = NULL; 543 req.emr_in_length = 0; 544 req.emr_out_buf = outbuf; 545 req.emr_out_length = sizeof (outbuf); 546 547 efx_mcdi_execute(enp, &req); 548 549 if (req.emr_rc != 0) { 550 rc = req.emr_rc; 551 goto fail1; 552 } 553 554 if (req.emr_out_length_used < MC_CMD_SENSOR_INFO_OUT_MASK_OFST + 4) { 555 rc = EMSGSIZE; 556 goto fail2; 557 } 558 559 encp->enc_siena_mon_stat_mask = 560 MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK); 561 encp->enc_mon_type = EFX_MON_SFC90X0; 562 563 siena_mon_decode_stats(enp, encp->enc_siena_mon_stat_mask, 564 NULL, &(encp->enc_mon_stat_mask), NULL); 565 566 return (0); 567 568 fail2: 569 EFSYS_PROBE(fail2); 570 fail1: 571 EFSYS_PROBE1(fail1, int, rc); 572 573 return (rc); 574 } 575 576 #endif /* EFSYS_OPT_MON_STATS */ 577 578 __checkReturn int 579 siena_nic_probe( 580 __in efx_nic_t *enp) 581 { 582 efx_port_t *epp = &(enp->en_port); 583 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 584 siena_link_state_t sls; 585 unsigned int mask; 586 int rc; 587 588 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 589 590 /* Read clear any assertion state */ 591 if ((rc = siena_nic_read_assertion(enp)) != 0) 592 goto fail1; 593 594 /* Exit the assertion handler */ 595 if ((rc = siena_nic_exit_assertion_handler(enp)) != 0) 596 goto fail2; 597 598 /* Wrestle control from the BMC */ 599 if ((rc = siena_nic_attach(enp, B_TRUE)) != 0) 600 goto fail3; 601 602 if ((rc = siena_board_cfg(enp)) != 0) 603 goto fail4; 604 605 encp->enc_evq_moderation_max = 606 EFX_EV_TIMER_QUANTUM << FRF_CZ_TIMER_VAL_WIDTH; 607 608 if ((rc = siena_phy_cfg(enp)) != 0) 609 goto fail5; 610 611 /* Obtain the default PHY advertised capabilities */ 612 if ((rc = siena_nic_reset(enp)) != 0) 613 goto fail6; 614 if ((rc = siena_phy_get_link(enp, &sls)) != 0) 615 goto fail7; 616 epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask; 617 epp->ep_adv_cap_mask = sls.sls_adv_cap_mask; 618 619 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM 620 if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0) 621 goto fail8; 622 enp->en_u.siena.enu_partn_mask = mask; 623 #endif 624 625 #if EFSYS_OPT_MAC_STATS 626 /* Wipe the MAC statistics */ 627 if ((rc = siena_mac_stats_clear(enp)) != 0) 628 goto fail9; 629 #endif 630 631 #if EFSYS_OPT_LOOPBACK 632 if ((rc = siena_loopback_cfg(enp)) != 0) 633 goto fail10; 634 #endif 635 636 #if EFSYS_OPT_MON_STATS 637 if ((rc = siena_monitor_cfg(enp)) != 0) 638 goto fail11; 639 #endif 640 641 encp->enc_features = enp->en_features; 642 643 return (0); 644 645 #if EFSYS_OPT_MON_STATS 646 fail11: 647 EFSYS_PROBE(fail11); 648 #endif 649 #if EFSYS_OPT_LOOPBACK 650 fail10: 651 EFSYS_PROBE(fail10); 652 #endif 653 #if EFSYS_OPT_MAC_STATS 654 fail9: 655 EFSYS_PROBE(fail9); 656 #endif 657 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM 658 fail8: 659 EFSYS_PROBE(fail8); 660 #endif 661 fail7: 662 EFSYS_PROBE(fail7); 663 fail6: 664 EFSYS_PROBE(fail6); 665 fail5: 666 EFSYS_PROBE(fail5); 667 fail4: 668 EFSYS_PROBE(fail4); 669 fail3: 670 EFSYS_PROBE(fail3); 671 fail2: 672 EFSYS_PROBE(fail2); 673 fail1: 674 EFSYS_PROBE1(fail1, int, rc); 675 676 return (rc); 677 } 678 679 __checkReturn int 680 siena_nic_reset( 681 __in efx_nic_t *enp) 682 { 683 efx_mcdi_req_t req; 684 int rc; 685 686 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 687 688 /* siena_nic_reset() is called to recover from BADASSERT failures. */ 689 if ((rc = siena_nic_read_assertion(enp)) != 0) 690 goto fail1; 691 if ((rc = siena_nic_exit_assertion_handler(enp)) != 0) 692 goto fail2; 693 694 req.emr_cmd = MC_CMD_PORT_RESET; 695 EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_IN_LEN == 0); 696 req.emr_in_buf = NULL; 697 req.emr_in_length = 0; 698 EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_OUT_LEN == 0); 699 req.emr_out_buf = NULL; 700 req.emr_out_length = 0; 701 702 efx_mcdi_execute(enp, &req); 703 704 if (req.emr_rc != 0) { 705 rc = req.emr_rc; 706 goto fail3; 707 } 708 709 return (0); 710 711 fail3: 712 EFSYS_PROBE(fail3); 713 fail2: 714 EFSYS_PROBE(fail2); 715 fail1: 716 EFSYS_PROBE1(fail1, int, rc); 717 718 return (0); 719 } 720 721 static __checkReturn int 722 siena_nic_logging( 723 __in efx_nic_t *enp) 724 { 725 efx_mcdi_req_t req; 726 uint8_t payload[MC_CMD_LOG_CTRL_IN_LEN]; 727 int rc; 728 729 req.emr_cmd = MC_CMD_LOG_CTRL; 730 req.emr_in_buf = payload; 731 req.emr_in_length = MC_CMD_LOG_CTRL_IN_LEN; 732 EFX_STATIC_ASSERT(MC_CMD_LOG_CTRL_OUT_LEN == 0); 733 req.emr_out_buf = NULL; 734 req.emr_out_length = 0; 735 736 MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST, 737 MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ); 738 MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST_EVQ, 0); 739 740 efx_mcdi_execute(enp, &req); 741 742 if (req.emr_rc != 0) { 743 rc = req.emr_rc; 744 goto fail1; 745 } 746 747 return (0); 748 749 fail1: 750 EFSYS_PROBE1(fail1, int, rc); 751 752 return (rc); 753 } 754 755 static void 756 siena_nic_rx_cfg( 757 __in efx_nic_t *enp) 758 { 759 efx_oword_t oword; 760 761 /* 762 * RX_INGR_EN is always enabled on Siena, because we rely on 763 * the RX parser to be resiliant to missing SOP/EOP. 764 */ 765 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword); 766 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1); 767 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword); 768 769 /* Disable parsing of additional 802.1Q in Q packets */ 770 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); 771 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0); 772 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); 773 } 774 775 static void 776 siena_nic_usrev_dis( 777 __in efx_nic_t *enp) 778 { 779 efx_oword_t oword; 780 781 EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1); 782 EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword); 783 } 784 785 __checkReturn int 786 siena_nic_init( 787 __in efx_nic_t *enp) 788 { 789 int rc; 790 791 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 792 793 if ((rc = siena_nic_logging(enp)) != 0) 794 goto fail1; 795 796 siena_sram_init(enp); 797 798 /* Configure Siena's RX block */ 799 siena_nic_rx_cfg(enp); 800 801 /* Disable USR_EVents for now */ 802 siena_nic_usrev_dis(enp); 803 804 /* bug17057: Ensure set_link is called */ 805 if ((rc = siena_phy_reconfigure(enp)) != 0) 806 goto fail2; 807 808 return (0); 809 810 fail2: 811 EFSYS_PROBE(fail2); 812 fail1: 813 EFSYS_PROBE1(fail1, int, rc); 814 815 return (rc); 816 } 817 818 void 819 siena_nic_fini( 820 __in efx_nic_t *enp) 821 { 822 _NOTE(ARGUNUSED(enp)) 823 } 824 825 void 826 siena_nic_unprobe( 827 __in efx_nic_t *enp) 828 { 829 (void) siena_nic_attach(enp, B_FALSE); 830 } 831 832 #if EFSYS_OPT_DIAG 833 834 static efx_register_set_t __cs __siena_registers[] = { 835 { FR_AZ_ADR_REGION_REG_OFST, 0, 1 }, 836 { FR_CZ_USR_EV_CFG_OFST, 0, 1 }, 837 { FR_AZ_RX_CFG_REG_OFST, 0, 1 }, 838 { FR_AZ_TX_CFG_REG_OFST, 0, 1 }, 839 { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 }, 840 { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 }, 841 { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 }, 842 { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 }, 843 { FR_AZ_DP_CTRL_REG_OFST, 0, 1 }, 844 { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1}, 845 { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1}, 846 { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1}, 847 { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1} 848 }; 849 850 static const uint32_t __cs __siena_register_masks[] = { 851 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 852 0x000103FF, 0x00000000, 0x00000000, 0x00000000, 853 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000, 854 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF, 855 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF, 856 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000, 857 0x00000003, 0x00000000, 0x00000000, 0x00000000, 858 0x000003FF, 0x00000000, 0x00000000, 0x00000000, 859 0x00000FFF, 0x00000000, 0x00000000, 0x00000000, 860 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 861 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 862 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 863 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000 864 }; 865 866 static efx_register_set_t __cs __siena_tables[] = { 867 { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP, 868 FR_AZ_RX_FILTER_TBL0_ROWS }, 869 { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP, 870 FR_CZ_RX_MAC_FILTER_TBL0_ROWS }, 871 { FR_AZ_RX_DESC_PTR_TBL_OFST, 872 FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS }, 873 { FR_AZ_TX_DESC_PTR_TBL_OFST, 874 FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS }, 875 { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS }, 876 { FR_CZ_TX_FILTER_TBL0_OFST, 877 FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS }, 878 { FR_CZ_TX_MAC_FILTER_TBL0_OFST, 879 FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS } 880 }; 881 882 static const uint32_t __cs __siena_table_masks[] = { 883 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF, 884 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000, 885 0xFFFFFFFF, 0x0FFFFFFF, 0x01800000, 0x00000000, 886 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000, 887 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000, 888 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF, 889 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000, 890 }; 891 892 __checkReturn int 893 siena_nic_register_test( 894 __in efx_nic_t *enp) 895 { 896 efx_register_set_t *rsp; 897 const uint32_t *dwordp; 898 unsigned int nitems; 899 unsigned int count; 900 int rc; 901 902 /* Fill out the register mask entries */ 903 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks) 904 == EFX_ARRAY_SIZE(__siena_registers) * 4); 905 906 nitems = EFX_ARRAY_SIZE(__siena_registers); 907 dwordp = __siena_register_masks; 908 for (count = 0; count < nitems; ++count) { 909 rsp = __siena_registers + count; 910 rsp->mask.eo_u32[0] = *dwordp++; 911 rsp->mask.eo_u32[1] = *dwordp++; 912 rsp->mask.eo_u32[2] = *dwordp++; 913 rsp->mask.eo_u32[3] = *dwordp++; 914 } 915 916 /* Fill out the register table entries */ 917 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks) 918 == EFX_ARRAY_SIZE(__siena_tables) * 4); 919 920 nitems = EFX_ARRAY_SIZE(__siena_tables); 921 dwordp = __siena_table_masks; 922 for (count = 0; count < nitems; ++count) { 923 rsp = __siena_tables + count; 924 rsp->mask.eo_u32[0] = *dwordp++; 925 rsp->mask.eo_u32[1] = *dwordp++; 926 rsp->mask.eo_u32[2] = *dwordp++; 927 rsp->mask.eo_u32[3] = *dwordp++; 928 } 929 930 if ((rc = efx_nic_test_registers(enp, __siena_registers, 931 EFX_ARRAY_SIZE(__siena_registers))) != 0) 932 goto fail1; 933 934 if ((rc = efx_nic_test_tables(enp, __siena_tables, 935 EFX_PATTERN_BYTE_ALTERNATE, 936 EFX_ARRAY_SIZE(__siena_tables))) != 0) 937 goto fail2; 938 939 if ((rc = efx_nic_test_tables(enp, __siena_tables, 940 EFX_PATTERN_BYTE_CHANGING, 941 EFX_ARRAY_SIZE(__siena_tables))) != 0) 942 goto fail3; 943 944 if ((rc = efx_nic_test_tables(enp, __siena_tables, 945 EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0) 946 goto fail4; 947 948 return (0); 949 950 fail4: 951 EFSYS_PROBE(fail4); 952 fail3: 953 EFSYS_PROBE(fail3); 954 fail2: 955 EFSYS_PROBE(fail2); 956 fail1: 957 EFSYS_PROBE1(fail1, int, rc); 958 959 return (rc); 960 } 961 962 #endif /* EFSYS_OPT_DIAG */ 963 964 #endif /* EFSYS_OPT_SIENA */ 965