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