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