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