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_LENMIN, 276 MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN)]; 277 efx_mcdi_req_t req; 278 uint8_t *mac_addr; 279 efx_dword_t *capabilities; 280 int rc; 281 282 /* Board configuration */ 283 req.emr_cmd = MC_CMD_GET_BOARD_CFG; 284 EFX_STATIC_ASSERT(MC_CMD_GET_BOARD_CFG_IN_LEN == 0); 285 req.emr_in_buf = NULL; 286 req.emr_in_length = 0; 287 req.emr_out_buf = outbuf; 288 req.emr_out_length = MC_CMD_GET_BOARD_CFG_OUT_LENMIN; 289 290 efx_mcdi_execute(enp, &req); 291 292 if (req.emr_rc != 0) { 293 rc = req.emr_rc; 294 goto fail1; 295 } 296 297 if (req.emr_out_length_used < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) { 298 rc = EMSGSIZE; 299 goto fail2; 300 } 301 302 if (emip->emi_port == 1) { 303 mac_addr = MCDI_OUT2(req, uint8_t, 304 GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0); 305 capabilities = MCDI_OUT2(req, efx_dword_t, 306 GET_BOARD_CFG_OUT_CAPABILITIES_PORT0); 307 } else { 308 mac_addr = MCDI_OUT2(req, uint8_t, 309 GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1); 310 capabilities = MCDI_OUT2(req, efx_dword_t, 311 GET_BOARD_CFG_OUT_CAPABILITIES_PORT1); 312 } 313 EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr); 314 315 encp->enc_board_type = MCDI_OUT_DWORD(req, 316 GET_BOARD_CFG_OUT_BOARD_TYPE); 317 318 /* Additional capabilities */ 319 encp->enc_clk_mult = 1; 320 if (MCDI_CMD_DWORD_FIELD(capabilities, CAPABILITIES_TURBO)) { 321 enp->en_features |= EFX_FEATURE_TURBO; 322 323 if (MCDI_CMD_DWORD_FIELD(capabilities, 324 CAPABILITIES_TURBO_ACTIVE)) 325 encp->enc_clk_mult = 2; 326 } 327 328 encp->enc_evq_timer_quantum_ns = 329 EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult; 330 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns << 331 FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000; 332 333 /* Resource limits */ 334 req.emr_cmd = MC_CMD_GET_RESOURCE_LIMITS; 335 EFX_STATIC_ASSERT(MC_CMD_GET_RESOURCE_LIMITS_IN_LEN == 0); 336 req.emr_in_buf = NULL; 337 req.emr_in_length = 0; 338 req.emr_out_buf = outbuf; 339 req.emr_out_length = MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN; 340 341 efx_mcdi_execute(enp, &req); 342 343 if (req.emr_rc == 0) { 344 if (req.emr_out_length_used < 345 MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN) { 346 rc = EMSGSIZE; 347 goto fail3; 348 } 349 350 encp->enc_evq_limit = MCDI_OUT_DWORD(req, 351 GET_RESOURCE_LIMITS_OUT_EVQ); 352 encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, 353 MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_TXQ)); 354 encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, 355 MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_RXQ)); 356 } else if (req.emr_rc == ENOTSUP) { 357 encp->enc_evq_limit = 1024; 358 encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET; 359 encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET; 360 } else { 361 rc = req.emr_rc; 362 goto fail4; 363 } 364 365 encp->enc_buftbl_limit = SIENA_SRAM_ROWS - 366 (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) - 367 (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE)); 368 369 return (0); 370 371 fail4: 372 EFSYS_PROBE(fail4); 373 fail3: 374 EFSYS_PROBE(fail3); 375 fail2: 376 EFSYS_PROBE(fail2); 377 fail1: 378 EFSYS_PROBE1(fail1, int, rc); 379 380 return (rc); 381 } 382 383 static __checkReturn int 384 siena_phy_cfg( 385 __in efx_nic_t *enp) 386 { 387 efx_port_t *epp = &(enp->en_port); 388 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 389 efx_mcdi_req_t req; 390 uint8_t outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN]; 391 int rc; 392 393 req.emr_cmd = MC_CMD_GET_PHY_CFG; 394 EFX_STATIC_ASSERT(MC_CMD_GET_PHY_CFG_IN_LEN == 0); 395 req.emr_in_buf = NULL; 396 req.emr_in_length = 0; 397 req.emr_out_buf = outbuf; 398 req.emr_out_length = sizeof (outbuf); 399 400 efx_mcdi_execute(enp, &req); 401 402 if (req.emr_rc != 0) { 403 rc = req.emr_rc; 404 goto fail1; 405 } 406 407 if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN) { 408 rc = EMSGSIZE; 409 goto fail2; 410 } 411 412 encp->enc_phy_type = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_TYPE); 413 #if EFSYS_OPT_NAMES 414 (void) strncpy(encp->enc_phy_name, 415 MCDI_OUT2(req, char, GET_PHY_CFG_OUT_NAME), 416 MIN(sizeof (encp->enc_phy_name) - 1, 417 MC_CMD_GET_PHY_CFG_OUT_NAME_LEN)); 418 #endif /* EFSYS_OPT_NAMES */ 419 (void) memset(encp->enc_phy_revision, 0, 420 sizeof (encp->enc_phy_revision)); 421 memcpy(encp->enc_phy_revision, 422 MCDI_OUT2(req, char, GET_PHY_CFG_OUT_REVISION), 423 MIN(sizeof (encp->enc_phy_revision) - 1, 424 MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN)); 425 #if EFSYS_OPT_PHY_LED_CONTROL 426 encp->enc_led_mask = ((1 << EFX_PHY_LED_DEFAULT) | 427 (1 << EFX_PHY_LED_OFF) | 428 (1 << EFX_PHY_LED_ON)); 429 #endif /* EFSYS_OPT_PHY_LED_CONTROL */ 430 431 #if EFSYS_OPT_PHY_PROPS 432 encp->enc_phy_nprops = 0; 433 #endif /* EFSYS_OPT_PHY_PROPS */ 434 435 /* Get the media type of the fixed port, if recognised. */ 436 EFX_STATIC_ASSERT(MC_CMD_MEDIA_XAUI == EFX_PHY_MEDIA_XAUI); 437 EFX_STATIC_ASSERT(MC_CMD_MEDIA_CX4 == EFX_PHY_MEDIA_CX4); 438 EFX_STATIC_ASSERT(MC_CMD_MEDIA_KX4 == EFX_PHY_MEDIA_KX4); 439 EFX_STATIC_ASSERT(MC_CMD_MEDIA_XFP == EFX_PHY_MEDIA_XFP); 440 EFX_STATIC_ASSERT(MC_CMD_MEDIA_SFP_PLUS == EFX_PHY_MEDIA_SFP_PLUS); 441 EFX_STATIC_ASSERT(MC_CMD_MEDIA_BASE_T == EFX_PHY_MEDIA_BASE_T); 442 epp->ep_fixed_port_type = 443 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_MEDIA_TYPE); 444 if (epp->ep_fixed_port_type >= EFX_PHY_MEDIA_NTYPES) 445 epp->ep_fixed_port_type = EFX_PHY_MEDIA_INVALID; 446 447 epp->ep_phy_cap_mask = 448 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_SUPPORTED_CAP); 449 #if EFSYS_OPT_PHY_FLAGS 450 encp->enc_phy_flags_mask = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_FLAGS); 451 #endif /* EFSYS_OPT_PHY_FLAGS */ 452 453 encp->enc_port = (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_PRT); 454 455 /* Populate internal state */ 456 encp->enc_siena_channel = 457 (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_CHANNEL); 458 459 #if EFSYS_OPT_PHY_STATS 460 encp->enc_siena_phy_stat_mask = 461 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_STATS_MASK); 462 463 /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */ 464 siena_phy_decode_stats(enp, encp->enc_siena_phy_stat_mask, 465 NULL, &encp->enc_phy_stat_mask, NULL); 466 #endif /* EFSYS_OPT_PHY_STATS */ 467 468 #if EFSYS_OPT_PHY_BIST 469 encp->enc_bist_mask = 0; 470 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 471 GET_PHY_CFG_OUT_BIST_CABLE_SHORT)) 472 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_SHORT); 473 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 474 GET_PHY_CFG_OUT_BIST_CABLE_LONG)) 475 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_LONG); 476 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 477 GET_PHY_CFG_OUT_BIST)) 478 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_NORMAL); 479 #endif /* EFSYS_OPT_PHY_BIST */ 480 481 return (0); 482 483 fail2: 484 EFSYS_PROBE(fail2); 485 fail1: 486 EFSYS_PROBE1(fail1, int, rc); 487 488 return (rc); 489 } 490 491 #if EFSYS_OPT_LOOPBACK 492 493 static __checkReturn int 494 siena_loopback_cfg( 495 __in efx_nic_t *enp) 496 { 497 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 498 efx_mcdi_req_t req; 499 uint8_t outbuf[MC_CMD_GET_LOOPBACK_MODES_OUT_LEN]; 500 int rc; 501 502 req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES; 503 EFX_STATIC_ASSERT(MC_CMD_GET_LOOPBACK_MODES_IN_LEN == 0); 504 req.emr_in_buf = NULL; 505 req.emr_in_length = 0; 506 req.emr_out_buf = outbuf; 507 req.emr_out_length = sizeof (outbuf); 508 509 efx_mcdi_execute(enp, &req); 510 511 if (req.emr_rc != 0) { 512 rc = req.emr_rc; 513 goto fail1; 514 } 515 516 if (req.emr_out_length_used < MC_CMD_GET_LOOPBACK_MODES_OUT_LEN) { 517 rc = EMSGSIZE; 518 goto fail2; 519 } 520 521 /* 522 * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree 523 * in siena_phy.c:siena_phy_get_link() 524 */ 525 encp->enc_loopback_types[EFX_LINK_100FDX] = EFX_LOOPBACK_MASK & 526 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_100M) & 527 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED); 528 encp->enc_loopback_types[EFX_LINK_1000FDX] = EFX_LOOPBACK_MASK & 529 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_1G) & 530 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED); 531 encp->enc_loopback_types[EFX_LINK_10000FDX] = EFX_LOOPBACK_MASK & 532 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_10G) & 533 MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED); 534 encp->enc_loopback_types[EFX_LINK_UNKNOWN] = 535 (1 << EFX_LOOPBACK_OFF) | 536 encp->enc_loopback_types[EFX_LINK_100FDX] | 537 encp->enc_loopback_types[EFX_LINK_1000FDX] | 538 encp->enc_loopback_types[EFX_LINK_10000FDX]; 539 540 return (0); 541 542 fail2: 543 EFSYS_PROBE(fail2); 544 fail1: 545 EFSYS_PROBE1(fail1, int, rc); 546 547 return (rc); 548 } 549 550 #endif /* EFSYS_OPT_LOOPBACK */ 551 552 #if EFSYS_OPT_MON_STATS 553 554 static __checkReturn int 555 siena_monitor_cfg( 556 __in efx_nic_t *enp) 557 { 558 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 559 efx_mcdi_req_t req; 560 uint8_t outbuf[MCDI_CTL_SDU_LEN_MAX]; 561 int rc; 562 563 req.emr_cmd = MC_CMD_SENSOR_INFO; 564 EFX_STATIC_ASSERT(MC_CMD_SENSOR_INFO_IN_LEN == 0); 565 req.emr_in_buf = NULL; 566 req.emr_in_length = 0; 567 req.emr_out_buf = outbuf; 568 req.emr_out_length = sizeof (outbuf); 569 570 efx_mcdi_execute(enp, &req); 571 572 if (req.emr_rc != 0) { 573 rc = req.emr_rc; 574 goto fail1; 575 } 576 577 if (req.emr_out_length_used < MC_CMD_SENSOR_INFO_OUT_MASK_OFST + 4) { 578 rc = EMSGSIZE; 579 goto fail2; 580 } 581 582 encp->enc_siena_mon_stat_mask = 583 MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK); 584 encp->enc_mon_type = EFX_MON_SFC90X0; 585 586 siena_mon_decode_stats(enp, encp->enc_siena_mon_stat_mask, 587 NULL, &(encp->enc_mon_stat_mask), NULL); 588 589 return (0); 590 591 fail2: 592 EFSYS_PROBE(fail2); 593 fail1: 594 EFSYS_PROBE1(fail1, int, rc); 595 596 return (rc); 597 } 598 599 #endif /* EFSYS_OPT_MON_STATS */ 600 601 __checkReturn int 602 siena_nic_probe( 603 __in efx_nic_t *enp) 604 { 605 efx_port_t *epp = &(enp->en_port); 606 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 607 siena_link_state_t sls; 608 unsigned int mask; 609 int rc; 610 611 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 612 613 /* Read clear any assertion state */ 614 if ((rc = siena_nic_read_assertion(enp)) != 0) 615 goto fail1; 616 617 /* Exit the assertion handler */ 618 if ((rc = siena_nic_exit_assertion_handler(enp)) != 0) 619 goto fail2; 620 621 /* Wrestle control from the BMC */ 622 if ((rc = siena_nic_attach(enp, B_TRUE)) != 0) 623 goto fail3; 624 625 if ((rc = siena_board_cfg(enp)) != 0) 626 goto fail4; 627 628 if ((rc = siena_phy_cfg(enp)) != 0) 629 goto fail5; 630 631 /* Obtain the default PHY advertised capabilities */ 632 if ((rc = siena_nic_reset(enp)) != 0) 633 goto fail6; 634 if ((rc = siena_phy_get_link(enp, &sls)) != 0) 635 goto fail7; 636 epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask; 637 epp->ep_adv_cap_mask = sls.sls_adv_cap_mask; 638 639 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM 640 if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0) 641 goto fail8; 642 enp->en_u.siena.enu_partn_mask = mask; 643 #endif 644 645 #if EFSYS_OPT_MAC_STATS 646 /* Wipe the MAC statistics */ 647 if ((rc = siena_mac_stats_clear(enp)) != 0) 648 goto fail9; 649 #endif 650 651 #if EFSYS_OPT_LOOPBACK 652 if ((rc = siena_loopback_cfg(enp)) != 0) 653 goto fail10; 654 #endif 655 656 #if EFSYS_OPT_MON_STATS 657 if ((rc = siena_monitor_cfg(enp)) != 0) 658 goto fail11; 659 #endif 660 661 encp->enc_features = enp->en_features; 662 663 return (0); 664 665 #if EFSYS_OPT_MON_STATS 666 fail11: 667 EFSYS_PROBE(fail11); 668 #endif 669 #if EFSYS_OPT_LOOPBACK 670 fail10: 671 EFSYS_PROBE(fail10); 672 #endif 673 #if EFSYS_OPT_MAC_STATS 674 fail9: 675 EFSYS_PROBE(fail9); 676 #endif 677 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM 678 fail8: 679 EFSYS_PROBE(fail8); 680 #endif 681 fail7: 682 EFSYS_PROBE(fail7); 683 fail6: 684 EFSYS_PROBE(fail6); 685 fail5: 686 EFSYS_PROBE(fail5); 687 fail4: 688 EFSYS_PROBE(fail4); 689 fail3: 690 EFSYS_PROBE(fail3); 691 fail2: 692 EFSYS_PROBE(fail2); 693 fail1: 694 EFSYS_PROBE1(fail1, int, rc); 695 696 return (rc); 697 } 698 699 __checkReturn int 700 siena_nic_reset( 701 __in efx_nic_t *enp) 702 { 703 efx_mcdi_req_t req; 704 int rc; 705 706 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 707 708 /* siena_nic_reset() is called to recover from BADASSERT failures. */ 709 if ((rc = siena_nic_read_assertion(enp)) != 0) 710 goto fail1; 711 if ((rc = siena_nic_exit_assertion_handler(enp)) != 0) 712 goto fail2; 713 714 req.emr_cmd = MC_CMD_PORT_RESET; 715 EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_IN_LEN == 0); 716 req.emr_in_buf = NULL; 717 req.emr_in_length = 0; 718 EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_OUT_LEN == 0); 719 req.emr_out_buf = NULL; 720 req.emr_out_length = 0; 721 722 efx_mcdi_execute(enp, &req); 723 724 if (req.emr_rc != 0) { 725 rc = req.emr_rc; 726 goto fail3; 727 } 728 729 return (0); 730 731 fail3: 732 EFSYS_PROBE(fail3); 733 fail2: 734 EFSYS_PROBE(fail2); 735 fail1: 736 EFSYS_PROBE1(fail1, int, rc); 737 738 return (0); 739 } 740 741 static __checkReturn int 742 siena_nic_logging( 743 __in efx_nic_t *enp) 744 { 745 efx_mcdi_req_t req; 746 uint8_t payload[MC_CMD_LOG_CTRL_IN_LEN]; 747 int rc; 748 749 req.emr_cmd = MC_CMD_LOG_CTRL; 750 req.emr_in_buf = payload; 751 req.emr_in_length = MC_CMD_LOG_CTRL_IN_LEN; 752 EFX_STATIC_ASSERT(MC_CMD_LOG_CTRL_OUT_LEN == 0); 753 req.emr_out_buf = NULL; 754 req.emr_out_length = 0; 755 756 MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST, 757 MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ); 758 MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST_EVQ, 0); 759 760 efx_mcdi_execute(enp, &req); 761 762 if (req.emr_rc != 0) { 763 rc = req.emr_rc; 764 goto fail1; 765 } 766 767 return (0); 768 769 fail1: 770 EFSYS_PROBE1(fail1, int, rc); 771 772 return (rc); 773 } 774 775 static void 776 siena_nic_rx_cfg( 777 __in efx_nic_t *enp) 778 { 779 efx_oword_t oword; 780 781 /* 782 * RX_INGR_EN is always enabled on Siena, because we rely on 783 * the RX parser to be resiliant to missing SOP/EOP. 784 */ 785 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword); 786 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1); 787 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword); 788 789 /* Disable parsing of additional 802.1Q in Q packets */ 790 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); 791 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0); 792 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); 793 } 794 795 static void 796 siena_nic_usrev_dis( 797 __in efx_nic_t *enp) 798 { 799 efx_oword_t oword; 800 801 EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1); 802 EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword); 803 } 804 805 __checkReturn int 806 siena_nic_init( 807 __in efx_nic_t *enp) 808 { 809 int rc; 810 811 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 812 813 if ((rc = siena_nic_logging(enp)) != 0) 814 goto fail1; 815 816 siena_sram_init(enp); 817 818 /* Configure Siena's RX block */ 819 siena_nic_rx_cfg(enp); 820 821 /* Disable USR_EVents for now */ 822 siena_nic_usrev_dis(enp); 823 824 /* bug17057: Ensure set_link is called */ 825 if ((rc = siena_phy_reconfigure(enp)) != 0) 826 goto fail2; 827 828 return (0); 829 830 fail2: 831 EFSYS_PROBE(fail2); 832 fail1: 833 EFSYS_PROBE1(fail1, int, rc); 834 835 return (rc); 836 } 837 838 void 839 siena_nic_fini( 840 __in efx_nic_t *enp) 841 { 842 _NOTE(ARGUNUSED(enp)) 843 } 844 845 void 846 siena_nic_unprobe( 847 __in efx_nic_t *enp) 848 { 849 (void) siena_nic_attach(enp, B_FALSE); 850 } 851 852 #if EFSYS_OPT_DIAG 853 854 static efx_register_set_t __cs __siena_registers[] = { 855 { FR_AZ_ADR_REGION_REG_OFST, 0, 1 }, 856 { FR_CZ_USR_EV_CFG_OFST, 0, 1 }, 857 { FR_AZ_RX_CFG_REG_OFST, 0, 1 }, 858 { FR_AZ_TX_CFG_REG_OFST, 0, 1 }, 859 { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 }, 860 { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 }, 861 { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 }, 862 { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 }, 863 { FR_AZ_DP_CTRL_REG_OFST, 0, 1 }, 864 { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1}, 865 { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1}, 866 { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1}, 867 { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1} 868 }; 869 870 static const uint32_t __cs __siena_register_masks[] = { 871 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 872 0x000103FF, 0x00000000, 0x00000000, 0x00000000, 873 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000, 874 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF, 875 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF, 876 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000, 877 0x00000003, 0x00000000, 0x00000000, 0x00000000, 878 0x000003FF, 0x00000000, 0x00000000, 0x00000000, 879 0x00000FFF, 0x00000000, 0x00000000, 0x00000000, 880 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 881 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 882 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 883 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000 884 }; 885 886 static efx_register_set_t __cs __siena_tables[] = { 887 { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP, 888 FR_AZ_RX_FILTER_TBL0_ROWS }, 889 { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP, 890 FR_CZ_RX_MAC_FILTER_TBL0_ROWS }, 891 { FR_AZ_RX_DESC_PTR_TBL_OFST, 892 FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS }, 893 { FR_AZ_TX_DESC_PTR_TBL_OFST, 894 FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS }, 895 { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS }, 896 { FR_CZ_TX_FILTER_TBL0_OFST, 897 FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS }, 898 { FR_CZ_TX_MAC_FILTER_TBL0_OFST, 899 FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS } 900 }; 901 902 static const uint32_t __cs __siena_table_masks[] = { 903 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF, 904 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000, 905 0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000, 906 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000, 907 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000, 908 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF, 909 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000, 910 }; 911 912 __checkReturn int 913 siena_nic_register_test( 914 __in efx_nic_t *enp) 915 { 916 efx_register_set_t *rsp; 917 const uint32_t *dwordp; 918 unsigned int nitems; 919 unsigned int count; 920 int rc; 921 922 /* Fill out the register mask entries */ 923 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks) 924 == EFX_ARRAY_SIZE(__siena_registers) * 4); 925 926 nitems = EFX_ARRAY_SIZE(__siena_registers); 927 dwordp = __siena_register_masks; 928 for (count = 0; count < nitems; ++count) { 929 rsp = __siena_registers + count; 930 rsp->mask.eo_u32[0] = *dwordp++; 931 rsp->mask.eo_u32[1] = *dwordp++; 932 rsp->mask.eo_u32[2] = *dwordp++; 933 rsp->mask.eo_u32[3] = *dwordp++; 934 } 935 936 /* Fill out the register table entries */ 937 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks) 938 == EFX_ARRAY_SIZE(__siena_tables) * 4); 939 940 nitems = EFX_ARRAY_SIZE(__siena_tables); 941 dwordp = __siena_table_masks; 942 for (count = 0; count < nitems; ++count) { 943 rsp = __siena_tables + count; 944 rsp->mask.eo_u32[0] = *dwordp++; 945 rsp->mask.eo_u32[1] = *dwordp++; 946 rsp->mask.eo_u32[2] = *dwordp++; 947 rsp->mask.eo_u32[3] = *dwordp++; 948 } 949 950 if ((rc = efx_nic_test_registers(enp, __siena_registers, 951 EFX_ARRAY_SIZE(__siena_registers))) != 0) 952 goto fail1; 953 954 if ((rc = efx_nic_test_tables(enp, __siena_tables, 955 EFX_PATTERN_BYTE_ALTERNATE, 956 EFX_ARRAY_SIZE(__siena_tables))) != 0) 957 goto fail2; 958 959 if ((rc = efx_nic_test_tables(enp, __siena_tables, 960 EFX_PATTERN_BYTE_CHANGING, 961 EFX_ARRAY_SIZE(__siena_tables))) != 0) 962 goto fail3; 963 964 if ((rc = efx_nic_test_tables(enp, __siena_tables, 965 EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0) 966 goto fail4; 967 968 return (0); 969 970 fail4: 971 EFSYS_PROBE(fail4); 972 fail3: 973 EFSYS_PROBE(fail3); 974 fail2: 975 EFSYS_PROBE(fail2); 976 fail1: 977 EFSYS_PROBE1(fail1, int, rc); 978 979 return (rc); 980 } 981 982 #endif /* EFSYS_OPT_DIAG */ 983 984 #endif /* EFSYS_OPT_SIENA */