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