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 * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) - 369 (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE)); 370 371 return (0); 372 373fail4: 374 EFSYS_PROBE(fail4); 375fail3: 376 EFSYS_PROBE(fail3); 377fail2: 378 EFSYS_PROBE(fail2); 379fail1: 380 EFSYS_PROBE1(fail1, int, rc); 381 382 return (rc); 383} 384 385static __checkReturn int 386siena_phy_cfg( 387 __in efx_nic_t *enp) 388{ 389 efx_port_t *epp = &(enp->en_port); 390 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 391 efx_mcdi_req_t req; 392 uint8_t outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN]; 393 int rc; 394 395 req.emr_cmd = MC_CMD_GET_PHY_CFG; 396 EFX_STATIC_ASSERT(MC_CMD_GET_PHY_CFG_IN_LEN == 0); 397 req.emr_in_buf = NULL; 398 req.emr_in_length = 0; 399 req.emr_out_buf = outbuf; 400 req.emr_out_length = sizeof (outbuf); 401 402 efx_mcdi_execute(enp, &req); 403 404 if (req.emr_rc != 0) { 405 rc = req.emr_rc; 406 goto fail1; 407 } 408 409 if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN) { 410 rc = EMSGSIZE; 411 goto fail2; 412 } 413 414 encp->enc_phy_type = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_TYPE); 415#if EFSYS_OPT_NAMES 416 (void) strncpy(encp->enc_phy_name, 417 MCDI_OUT2(req, char, GET_PHY_CFG_OUT_NAME), 418 MIN(sizeof (encp->enc_phy_name) - 1, 419 MC_CMD_GET_PHY_CFG_OUT_NAME_LEN)); 420#endif /* EFSYS_OPT_NAMES */ 421 (void) memset(encp->enc_phy_revision, 0, 422 sizeof (encp->enc_phy_revision)); 423 memcpy(encp->enc_phy_revision, 424 MCDI_OUT2(req, char, GET_PHY_CFG_OUT_REVISION), 425 MIN(sizeof (encp->enc_phy_revision) - 1, 426 MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN)); 427#if EFSYS_OPT_PHY_LED_CONTROL 428 encp->enc_led_mask = ((1 << EFX_PHY_LED_DEFAULT) | 429 (1 << EFX_PHY_LED_OFF) | 430 (1 << EFX_PHY_LED_ON)); 431#endif /* EFSYS_OPT_PHY_LED_CONTROL */ 432 433#if EFSYS_OPT_PHY_PROPS 434 encp->enc_phy_nprops = 0; 435#endif /* EFSYS_OPT_PHY_PROPS */ 436 437 /* Get the media type of the fixed port, if recognised. */ 438 EFX_STATIC_ASSERT(MC_CMD_MEDIA_XAUI == EFX_PHY_MEDIA_XAUI); 439 EFX_STATIC_ASSERT(MC_CMD_MEDIA_CX4 == EFX_PHY_MEDIA_CX4); 440 EFX_STATIC_ASSERT(MC_CMD_MEDIA_KX4 == EFX_PHY_MEDIA_KX4); 441 EFX_STATIC_ASSERT(MC_CMD_MEDIA_XFP == EFX_PHY_MEDIA_XFP); 442 EFX_STATIC_ASSERT(MC_CMD_MEDIA_SFP_PLUS == EFX_PHY_MEDIA_SFP_PLUS); 443 EFX_STATIC_ASSERT(MC_CMD_MEDIA_BASE_T == EFX_PHY_MEDIA_BASE_T); 444 epp->ep_fixed_port_type = 445 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_MEDIA_TYPE); 446 if (epp->ep_fixed_port_type >= EFX_PHY_MEDIA_NTYPES) 447 epp->ep_fixed_port_type = EFX_PHY_MEDIA_INVALID; 448 449 epp->ep_phy_cap_mask = 450 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_SUPPORTED_CAP); 451#if EFSYS_OPT_PHY_FLAGS 452 encp->enc_phy_flags_mask = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_FLAGS); 453#endif /* EFSYS_OPT_PHY_FLAGS */ 454 455 encp->enc_port = (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_PRT); 456 457 /* Populate internal state */ 458 encp->enc_siena_channel = 459 (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_CHANNEL); 460 461#if EFSYS_OPT_PHY_STATS 462 encp->enc_siena_phy_stat_mask = 463 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_STATS_MASK); 464 465 /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */ 466 siena_phy_decode_stats(enp, encp->enc_siena_phy_stat_mask, 467 NULL, &encp->enc_phy_stat_mask, NULL); 468#endif /* EFSYS_OPT_PHY_STATS */ 469 470#if EFSYS_OPT_PHY_BIST 471 encp->enc_bist_mask = 0; 472 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 473 GET_PHY_CFG_OUT_BIST_CABLE_SHORT)) 474 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_SHORT); 475 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 476 GET_PHY_CFG_OUT_BIST_CABLE_LONG)) 477 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_LONG); 478 if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 479 GET_PHY_CFG_OUT_BIST)) 480 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_NORMAL);
|
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 0xFFFFFFFE, 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 */
|