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