1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2009-2016 Solarflare Communications Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * The views and conclusions contained in the software and documentation are 29 * those of the authors and should not be interpreted as representing official 30 * policies, either expressed or implied, of the FreeBSD Project. 31 */ 32 33#include <sys/cdefs.h> 34__FBSDID("$FreeBSD$"); 35 36#include "efx.h" 37#include "efx_impl.h" 38#include "mcdi_mon.h" 39 40#if EFSYS_OPT_SIENA 41 42#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM 43 44static __checkReturn efx_rc_t 45siena_nic_get_partn_mask( 46 __in efx_nic_t *enp, 47 __out unsigned int *maskp) 48{ 49 efx_mcdi_req_t req; 50 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_TYPES_IN_LEN, 51 MC_CMD_NVRAM_TYPES_OUT_LEN); 52 efx_rc_t rc; 53 54 req.emr_cmd = MC_CMD_NVRAM_TYPES; 55 req.emr_in_buf = payload; 56 req.emr_in_length = MC_CMD_NVRAM_TYPES_IN_LEN; 57 req.emr_out_buf = payload; 58 req.emr_out_length = MC_CMD_NVRAM_TYPES_OUT_LEN; 59 60 efx_mcdi_execute(enp, &req); 61 62 if (req.emr_rc != 0) { 63 rc = req.emr_rc; 64 goto fail1; 65 } 66 67 if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) { 68 rc = EMSGSIZE; 69 goto fail2; 70 } 71 72 *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES); 73 74 return (0); 75 76fail2: 77 EFSYS_PROBE(fail2); 78fail1: 79 EFSYS_PROBE1(fail1, efx_rc_t, rc); 80 81 return (rc); 82} 83 84#endif /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */ 85 86static __checkReturn efx_rc_t 87siena_board_cfg( 88 __in efx_nic_t *enp) 89{ 90 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 91 uint8_t mac_addr[6]; 92 efx_dword_t capabilities; 93 uint32_t board_type; 94 uint32_t nevq, nrxq, ntxq; 95 efx_rc_t rc; 96 97 /* External port identifier using one-based port numbering */ 98 encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port; 99 100 /* Board configuration */ 101 if ((rc = efx_mcdi_get_board_cfg(enp, &board_type, 102 &capabilities, mac_addr)) != 0) 103 goto fail1; 104 105 EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr); 106 107 encp->enc_board_type = board_type; 108 109 /* 110 * There is no possibility to determine the number of PFs on Siena 111 * by issuing MCDI request, and it is not an easy task to find the 112 * value based on the board type, so 'enc_hw_pf_count' is set to 1 113 */ 114 encp->enc_hw_pf_count = 1; 115 116 /* Additional capabilities */ 117 encp->enc_clk_mult = 1; 118 if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) { 119 enp->en_features |= EFX_FEATURE_TURBO; 120 121 if (EFX_DWORD_FIELD(capabilities, 122 MC_CMD_CAPABILITIES_TURBO_ACTIVE)) { 123 encp->enc_clk_mult = 2; 124 } 125 } 126 127 encp->enc_evq_timer_quantum_ns = 128 EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult; 129 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns << 130 FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000; 131 132 /* When hash header insertion is enabled, Siena inserts 16 bytes */ 133 encp->enc_rx_prefix_size = 16; 134 135 /* Alignment for receive packet DMA buffers */ 136 encp->enc_rx_buf_align_start = 1; 137 encp->enc_rx_buf_align_end = 1; 138 139 /* Alignment for WPTR updates */ 140 encp->enc_rx_push_align = 1; 141 142 encp->enc_tx_dma_desc_size_max = EFX_MASK32(FSF_AZ_TX_KER_BYTE_COUNT); 143 /* Fragments must not span 4k boundaries. */ 144 encp->enc_tx_dma_desc_boundary = 4096; 145 146 /* Resource limits */ 147 rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq); 148 if (rc != 0) { 149 if (rc != ENOTSUP) 150 goto fail2; 151 152 nevq = 1024; 153 nrxq = EFX_RXQ_LIMIT_TARGET; 154 ntxq = EFX_TXQ_LIMIT_TARGET; 155 } 156 encp->enc_evq_limit = nevq; 157 encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq); 158 encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq); 159 160 encp->enc_txq_max_ndescs = 4096; 161 162 encp->enc_buftbl_limit = SIENA_SRAM_ROWS - 163 (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) - 164 (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE)); 165 166 encp->enc_hw_tx_insert_vlan_enabled = B_FALSE; 167 encp->enc_fw_assisted_tso_enabled = B_FALSE; 168 encp->enc_fw_assisted_tso_v2_enabled = B_FALSE; 169 encp->enc_fw_assisted_tso_v2_n_contexts = 0; 170 encp->enc_allow_set_mac_with_installed_filters = B_TRUE; 171 172 /* Siena supports two 10G ports, and 8 lanes of PCIe Gen2 */ 173 encp->enc_required_pcie_bandwidth_mbps = 2 * 10000; 174 encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN2; 175 176 encp->enc_fw_verified_nvram_update_required = B_FALSE; 177 178 return (0); 179 180fail2: 181 EFSYS_PROBE(fail2); 182fail1: 183 EFSYS_PROBE1(fail1, efx_rc_t, rc); 184 185 return (rc); 186} 187 188static __checkReturn efx_rc_t 189siena_phy_cfg( 190 __in efx_nic_t *enp) 191{ 192#if EFSYS_OPT_PHY_STATS 193 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 194#endif /* EFSYS_OPT_PHY_STATS */ 195 efx_rc_t rc; 196 197 /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */ 198 if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0) 199 goto fail1; 200 201#if EFSYS_OPT_PHY_STATS 202 /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */ 203 siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask, 204 NULL, &encp->enc_phy_stat_mask, NULL); 205#endif /* EFSYS_OPT_PHY_STATS */ 206 207 return (0); 208 209fail1: 210 EFSYS_PROBE1(fail1, efx_rc_t, rc); 211 212 return (rc); 213} 214 215#define SIENA_BIU_MAGIC0 0x01234567 216#define SIENA_BIU_MAGIC1 0xfedcba98 217 218static __checkReturn efx_rc_t 219siena_nic_biu_test( 220 __in efx_nic_t *enp) 221{ 222 efx_oword_t oword; 223 efx_rc_t rc; 224 225 /* 226 * Write magic values to scratch registers 0 and 1, then 227 * verify that the values were written correctly. Interleave 228 * the accesses to ensure that the BIU is not just reading 229 * back the cached value that was last written. 230 */ 231 EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC0); 232 EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); 233 234 EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC1); 235 EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); 236 237 EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); 238 if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC0) { 239 rc = EIO; 240 goto fail1; 241 } 242 243 EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); 244 if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC1) { 245 rc = EIO; 246 goto fail2; 247 } 248 249 /* 250 * Perform the same test, with the values swapped. This 251 * ensures that subsequent tests don't start with the correct 252 * values already written into the scratch registers. 253 */ 254 EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC1); 255 EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); 256 257 EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC0); 258 EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); 259 260 EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); 261 if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC1) { 262 rc = EIO; 263 goto fail3; 264 } 265 266 EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); 267 if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC0) { 268 rc = EIO; 269 goto fail4; 270 } 271 272 return (0); 273 274fail4: 275 EFSYS_PROBE(fail4); 276fail3: 277 EFSYS_PROBE(fail3); 278fail2: 279 EFSYS_PROBE(fail2); 280fail1: 281 EFSYS_PROBE1(fail1, efx_rc_t, rc); 282 283 return (rc); 284} 285 286 __checkReturn efx_rc_t 287siena_nic_probe( 288 __in efx_nic_t *enp) 289{ 290 efx_port_t *epp = &(enp->en_port); 291 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 292 siena_link_state_t sls; 293 unsigned int mask; 294 efx_oword_t oword; 295 efx_rc_t rc; 296 297 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 298 299 /* Test BIU */ 300 if ((rc = siena_nic_biu_test(enp)) != 0) 301 goto fail1; 302 303 /* Clear the region register */ 304 EFX_POPULATE_OWORD_4(oword, 305 FRF_AZ_ADR_REGION0, 0, 306 FRF_AZ_ADR_REGION1, (1 << 16), 307 FRF_AZ_ADR_REGION2, (2 << 16), 308 FRF_AZ_ADR_REGION3, (3 << 16)); 309 EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword); 310 311 /* Read clear any assertion state */ 312 if ((rc = efx_mcdi_read_assertion(enp)) != 0) 313 goto fail2; 314 315 /* Exit the assertion handler */ 316 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 317 goto fail3; 318 319 /* Wrestle control from the BMC */ 320 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0) 321 goto fail4; 322 323 if ((rc = siena_board_cfg(enp)) != 0) 324 goto fail5; 325 326 if ((rc = siena_phy_cfg(enp)) != 0) 327 goto fail6; 328 329 /* Obtain the default PHY advertised capabilities */ 330 if ((rc = siena_nic_reset(enp)) != 0) 331 goto fail7; 332 if ((rc = siena_phy_get_link(enp, &sls)) != 0) 333 goto fail8; 334 epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask; 335 epp->ep_adv_cap_mask = sls.sls_adv_cap_mask; 336 337#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM 338 if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0) 339 goto fail9; 340 enp->en_u.siena.enu_partn_mask = mask; 341#endif 342 343#if EFSYS_OPT_MAC_STATS 344 /* Wipe the MAC statistics */ 345 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0) 346 goto fail10; 347#endif 348 349#if EFSYS_OPT_LOOPBACK 350 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0) 351 goto fail11; 352#endif 353 354#if EFSYS_OPT_MON_STATS 355 if ((rc = mcdi_mon_cfg_build(enp)) != 0) 356 goto fail12; 357#endif 358 359 encp->enc_features = enp->en_features; 360 361 return (0); 362 363#if EFSYS_OPT_MON_STATS 364fail12: 365 EFSYS_PROBE(fail12); 366#endif 367#if EFSYS_OPT_LOOPBACK 368fail11: 369 EFSYS_PROBE(fail11); 370#endif 371#if EFSYS_OPT_MAC_STATS 372fail10: 373 EFSYS_PROBE(fail10); 374#endif 375#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM 376fail9: 377 EFSYS_PROBE(fail9); 378#endif 379fail8: 380 EFSYS_PROBE(fail8); 381fail7: 382 EFSYS_PROBE(fail7); 383fail6: 384 EFSYS_PROBE(fail6); 385fail5: 386 EFSYS_PROBE(fail5); 387fail4: 388 EFSYS_PROBE(fail4); 389fail3: 390 EFSYS_PROBE(fail3); 391fail2: 392 EFSYS_PROBE(fail2); 393fail1: 394 EFSYS_PROBE1(fail1, efx_rc_t, rc); 395 396 return (rc); 397} 398 399 __checkReturn efx_rc_t 400siena_nic_reset( 401 __in efx_nic_t *enp) 402{ 403 efx_mcdi_req_t req; 404 efx_rc_t rc; 405 406 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 407 408 /* siena_nic_reset() is called to recover from BADASSERT failures. */ 409 if ((rc = efx_mcdi_read_assertion(enp)) != 0) 410 goto fail1; 411 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 412 goto fail2; 413 414 /* 415 * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied 416 * for backwards compatibility with PORT_RESET_IN_LEN. 417 */ 418 EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0); 419 420 req.emr_cmd = MC_CMD_ENTITY_RESET; 421 req.emr_in_buf = NULL; 422 req.emr_in_length = 0; 423 req.emr_out_buf = NULL; 424 req.emr_out_length = 0; 425 426 efx_mcdi_execute(enp, &req); 427 428 if (req.emr_rc != 0) { 429 rc = req.emr_rc; 430 goto fail3; 431 } 432 433 return (0); 434 435fail3: 436 EFSYS_PROBE(fail3); 437fail2: 438 EFSYS_PROBE(fail2); 439fail1: 440 EFSYS_PROBE1(fail1, efx_rc_t, rc); 441 442 return (0); 443} 444 445static void 446siena_nic_rx_cfg( 447 __in efx_nic_t *enp) 448{ 449 efx_oword_t oword; 450 451 /* 452 * RX_INGR_EN is always enabled on Siena, because we rely on 453 * the RX parser to be resiliant to missing SOP/EOP. 454 */ 455 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword); 456 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1); 457 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword); 458 459 /* Disable parsing of additional 802.1Q in Q packets */ 460 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); 461 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0); 462 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); 463} 464 465static void 466siena_nic_usrev_dis( 467 __in efx_nic_t *enp) 468{ 469 efx_oword_t oword; 470 471 EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1); 472 EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword); 473} 474 475 __checkReturn efx_rc_t 476siena_nic_init( 477 __in efx_nic_t *enp) 478{ 479 efx_rc_t rc; 480 481 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 482 483 /* Enable reporting of some events (e.g. link change) */ 484 if ((rc = efx_mcdi_log_ctrl(enp)) != 0) 485 goto fail1; 486 487 siena_sram_init(enp); 488 489 /* Configure Siena's RX block */ 490 siena_nic_rx_cfg(enp); 491 492 /* Disable USR_EVents for now */ 493 siena_nic_usrev_dis(enp); 494 495 /* bug17057: Ensure set_link is called */ 496 if ((rc = siena_phy_reconfigure(enp)) != 0) 497 goto fail2; 498 499 enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V1; 500 501 return (0); 502 503fail2: 504 EFSYS_PROBE(fail2); 505fail1: 506 EFSYS_PROBE1(fail1, efx_rc_t, rc); 507 508 return (rc); 509} 510 511 void 512siena_nic_fini( 513 __in efx_nic_t *enp) 514{ 515 _NOTE(ARGUNUSED(enp)) 516} 517 518 void 519siena_nic_unprobe( 520 __in efx_nic_t *enp) 521{ 522#if EFSYS_OPT_MON_STATS 523 mcdi_mon_cfg_free(enp); 524#endif /* EFSYS_OPT_MON_STATS */ 525 (void) efx_mcdi_drv_attach(enp, B_FALSE); 526} 527 528#if EFSYS_OPT_DIAG 529 530static siena_register_set_t __siena_registers[] = { 531 { FR_AZ_ADR_REGION_REG_OFST, 0, 1 }, 532 { FR_CZ_USR_EV_CFG_OFST, 0, 1 }, 533 { FR_AZ_RX_CFG_REG_OFST, 0, 1 }, 534 { FR_AZ_TX_CFG_REG_OFST, 0, 1 }, 535 { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 }, 536 { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 }, 537 { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 }, 538 { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 }, 539 { FR_AZ_DP_CTRL_REG_OFST, 0, 1 }, 540 { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1}, 541 { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1}, 542 { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1}, 543 { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1} 544}; 545 546static const uint32_t __siena_register_masks[] = { 547 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 548 0x000103FF, 0x00000000, 0x00000000, 0x00000000, 549 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000, 550 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF, 551 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF, 552 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000, 553 0x00000003, 0x00000000, 0x00000000, 0x00000000, 554 0x000003FF, 0x00000000, 0x00000000, 0x00000000, 555 0x00000FFF, 0x00000000, 0x00000000, 0x00000000, 556 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 557 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 558 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 559 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000 560}; 561 562static siena_register_set_t __siena_tables[] = { 563 { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP, 564 FR_AZ_RX_FILTER_TBL0_ROWS }, 565 { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP, 566 FR_CZ_RX_MAC_FILTER_TBL0_ROWS }, 567 { FR_AZ_RX_DESC_PTR_TBL_OFST, 568 FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS }, 569 { FR_AZ_TX_DESC_PTR_TBL_OFST, 570 FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS }, 571 { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS }, 572 { FR_CZ_TX_FILTER_TBL0_OFST, 573 FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS }, 574 { FR_CZ_TX_MAC_FILTER_TBL0_OFST, 575 FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS } 576}; 577 578static const uint32_t __siena_table_masks[] = { 579 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF, 580 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000, 581 0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000, 582 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000, 583 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000, 584 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF, 585 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000, 586}; 587 588 __checkReturn efx_rc_t 589siena_nic_test_registers( 590 __in efx_nic_t *enp, 591 __in siena_register_set_t *rsp, 592 __in size_t count) 593{ 594 unsigned int bit; 595 efx_oword_t original; 596 efx_oword_t reg; 597 efx_oword_t buf; 598 efx_rc_t rc; 599 600 while (count > 0) { 601 /* This function is only suitable for registers */ 602 EFSYS_ASSERT(rsp->rows == 1); 603 604 /* bit sweep on and off */ 605 EFSYS_BAR_READO(enp->en_esbp, rsp->address, &original, 606 B_TRUE); 607 for (bit = 0; bit < 128; bit++) { 608 /* Is this bit in the mask? */ 609 if (~(rsp->mask.eo_u32[bit >> 5]) & (1 << bit)) 610 continue; 611 612 /* Test this bit can be set in isolation */ 613 reg = original; 614 EFX_AND_OWORD(reg, rsp->mask); 615 EFX_SET_OWORD_BIT(reg, bit); 616 617 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®, 618 B_TRUE); 619 EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf, 620 B_TRUE); 621 622 EFX_AND_OWORD(buf, rsp->mask); 623 if (memcmp(®, &buf, sizeof (reg))) { 624 rc = EIO; 625 goto fail1; 626 } 627 628 /* Test this bit can be cleared in isolation */ 629 EFX_OR_OWORD(reg, rsp->mask); 630 EFX_CLEAR_OWORD_BIT(reg, bit); 631 632 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®, 633 B_TRUE); 634 EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf, 635 B_TRUE); 636 637 EFX_AND_OWORD(buf, rsp->mask); 638 if (memcmp(®, &buf, sizeof (reg))) { 639 rc = EIO; 640 goto fail2; 641 } 642 } 643 644 /* Restore the old value */ 645 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, 646 B_TRUE); 647 648 --count; 649 ++rsp; 650 } 651 652 return (0); 653 654fail2: 655 EFSYS_PROBE(fail2); 656fail1: 657 EFSYS_PROBE1(fail1, efx_rc_t, rc); 658 659 /* Restore the old value */ 660 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, B_TRUE); 661 662 return (rc); 663} 664 665 __checkReturn efx_rc_t 666siena_nic_test_tables( 667 __in efx_nic_t *enp, 668 __in siena_register_set_t *rsp, 669 __in efx_pattern_type_t pattern, 670 __in size_t count) 671{ 672 efx_sram_pattern_fn_t func; 673 unsigned int index; 674 unsigned int address; 675 efx_oword_t reg; 676 efx_oword_t buf; 677 efx_rc_t rc; 678 679 EFSYS_ASSERT(pattern < EFX_PATTERN_NTYPES); 680 func = __efx_sram_pattern_fns[pattern]; 681 682 while (count > 0) { 683 /* Write */ 684 address = rsp->address; 685 for (index = 0; index < rsp->rows; ++index) { 686 func(2 * index + 0, B_FALSE, ®.eo_qword[0]); 687 func(2 * index + 1, B_FALSE, ®.eo_qword[1]); 688 EFX_AND_OWORD(reg, rsp->mask); 689 EFSYS_BAR_WRITEO(enp->en_esbp, address, ®, B_TRUE); 690 691 address += rsp->step; 692 } 693 694 /* Read */ 695 address = rsp->address; 696 for (index = 0; index < rsp->rows; ++index) { 697 func(2 * index + 0, B_FALSE, ®.eo_qword[0]); 698 func(2 * index + 1, B_FALSE, ®.eo_qword[1]); 699 EFX_AND_OWORD(reg, rsp->mask); 700 EFSYS_BAR_READO(enp->en_esbp, address, &buf, B_TRUE); 701 if (memcmp(®, &buf, sizeof (reg))) { 702 rc = EIO; 703 goto fail1; 704 } 705 706 address += rsp->step; 707 } 708 709 ++rsp; 710 --count; 711 } 712 713 return (0); 714 715fail1: 716 EFSYS_PROBE1(fail1, efx_rc_t, rc); 717 718 return (rc); 719} 720 721 722 __checkReturn efx_rc_t 723siena_nic_register_test( 724 __in efx_nic_t *enp) 725{ 726 siena_register_set_t *rsp; 727 const uint32_t *dwordp; 728 unsigned int nitems; 729 unsigned int count; 730 efx_rc_t rc; 731 732 /* Fill out the register mask entries */ 733 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks) 734 == EFX_ARRAY_SIZE(__siena_registers) * 4); 735 736 nitems = EFX_ARRAY_SIZE(__siena_registers); 737 dwordp = __siena_register_masks; 738 for (count = 0; count < nitems; ++count) { 739 rsp = __siena_registers + count; 740 rsp->mask.eo_u32[0] = *dwordp++; 741 rsp->mask.eo_u32[1] = *dwordp++; 742 rsp->mask.eo_u32[2] = *dwordp++; 743 rsp->mask.eo_u32[3] = *dwordp++; 744 } 745 746 /* Fill out the register table entries */ 747 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks) 748 == EFX_ARRAY_SIZE(__siena_tables) * 4); 749 750 nitems = EFX_ARRAY_SIZE(__siena_tables); 751 dwordp = __siena_table_masks; 752 for (count = 0; count < nitems; ++count) { 753 rsp = __siena_tables + count; 754 rsp->mask.eo_u32[0] = *dwordp++; 755 rsp->mask.eo_u32[1] = *dwordp++; 756 rsp->mask.eo_u32[2] = *dwordp++; 757 rsp->mask.eo_u32[3] = *dwordp++; 758 } 759 760 if ((rc = siena_nic_test_registers(enp, __siena_registers, 761 EFX_ARRAY_SIZE(__siena_registers))) != 0) 762 goto fail1; 763 764 if ((rc = siena_nic_test_tables(enp, __siena_tables, 765 EFX_PATTERN_BYTE_ALTERNATE, 766 EFX_ARRAY_SIZE(__siena_tables))) != 0) 767 goto fail2; 768 769 if ((rc = siena_nic_test_tables(enp, __siena_tables, 770 EFX_PATTERN_BYTE_CHANGING, 771 EFX_ARRAY_SIZE(__siena_tables))) != 0) 772 goto fail3; 773 774 if ((rc = siena_nic_test_tables(enp, __siena_tables, 775 EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0) 776 goto fail4; 777 778 return (0); 779 780fail4: 781 EFSYS_PROBE(fail4); 782fail3: 783 EFSYS_PROBE(fail3); 784fail2: 785 EFSYS_PROBE(fail2); 786fail1: 787 EFSYS_PROBE1(fail1, efx_rc_t, rc); 788 789 return (rc); 790} 791 792#endif /* EFSYS_OPT_DIAG */ 793 794#endif /* EFSYS_OPT_SIENA */ 795