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 44 static __checkReturn efx_rc_t 45 siena_nic_get_partn_mask( 46 __in efx_nic_t *enp, 47 __out unsigned int *maskp) 48 { 49 efx_mcdi_req_t req; 50 uint8_t payload[MAX(MC_CMD_NVRAM_TYPES_IN_LEN, 51 MC_CMD_NVRAM_TYPES_OUT_LEN)]; 52 efx_rc_t rc; 53 54 (void) memset(payload, 0, sizeof (payload)); 55 req.emr_cmd = MC_CMD_NVRAM_TYPES; 56 req.emr_in_buf = payload; 57 req.emr_in_length = MC_CMD_NVRAM_TYPES_IN_LEN; 58 req.emr_out_buf = payload; 59 req.emr_out_length = MC_CMD_NVRAM_TYPES_OUT_LEN; 60 61 efx_mcdi_execute(enp, &req); 62 63 if (req.emr_rc != 0) { 64 rc = req.emr_rc; 65 goto fail1; 66 } 67 68 if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) { 69 rc = EMSGSIZE; 70 goto fail2; 71 } 72 73 *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES); 74 75 return (0); 76 77 fail2: 78 EFSYS_PROBE(fail2); 79 fail1: 80 EFSYS_PROBE1(fail1, efx_rc_t, rc); 81 82 return (rc); 83 } 84 85 #endif /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */ 86 87 static __checkReturn efx_rc_t 88 siena_board_cfg( 89 __in efx_nic_t *enp) 90 { 91 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 92 uint8_t mac_addr[6]; 93 efx_dword_t capabilities; 94 uint32_t board_type; 95 uint32_t nevq, nrxq, ntxq; 96 efx_rc_t rc; 97 98 /* External port identifier using one-based port numbering */ 99 encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port; 100 101 /* Board configuration */ 102 if ((rc = efx_mcdi_get_board_cfg(enp, &board_type, 103 &capabilities, mac_addr)) != 0) 104 goto fail1; 105 106 EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr); 107 108 encp->enc_board_type = board_type; 109 110 /* 111 * There is no possibility to determine the number of PFs on Siena 112 * by issuing MCDI request, and it is not an easy task to find the 113 * value based on the board type, so 'enc_hw_pf_count' is set to 1 114 */ 115 encp->enc_hw_pf_count = 1; 116 117 /* Additional capabilities */ 118 encp->enc_clk_mult = 1; 119 if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) { 120 enp->en_features |= EFX_FEATURE_TURBO; 121 122 if (EFX_DWORD_FIELD(capabilities, 123 MC_CMD_CAPABILITIES_TURBO_ACTIVE)) { 124 encp->enc_clk_mult = 2; 125 } 126 } 127 128 encp->enc_evq_timer_quantum_ns = 129 EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult; 130 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns << 131 FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000; 132 133 /* When hash header insertion is enabled, Siena inserts 16 bytes */ 134 encp->enc_rx_prefix_size = 16; 135 136 /* Alignment for receive packet DMA buffers */ 137 encp->enc_rx_buf_align_start = 1; 138 encp->enc_rx_buf_align_end = 1; 139 140 /* Alignment for WPTR updates */ 141 encp->enc_rx_push_align = 1; 142 143 /* There is one RSS context per function */ 144 encp->enc_rx_scale_max_exclusive_contexts = 1; 145 146 encp->enc_tx_dma_desc_size_max = EFX_MASK32(FSF_AZ_TX_KER_BYTE_COUNT); 147 /* Fragments must not span 4k boundaries. */ 148 encp->enc_tx_dma_desc_boundary = 4096; 149 150 /* Resource limits */ 151 rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq); 152 if (rc != 0) { 153 if (rc != ENOTSUP) 154 goto fail2; 155 156 nevq = 1024; 157 nrxq = EFX_RXQ_LIMIT_TARGET; 158 ntxq = EFX_TXQ_LIMIT_TARGET; 159 } 160 encp->enc_evq_limit = nevq; 161 encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq); 162 encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq); 163 164 encp->enc_txq_max_ndescs = 4096; 165 166 encp->enc_buftbl_limit = SIENA_SRAM_ROWS - 167 (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) - 168 (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE)); 169 170 encp->enc_hw_tx_insert_vlan_enabled = B_FALSE; 171 encp->enc_fw_assisted_tso_enabled = B_FALSE; 172 encp->enc_fw_assisted_tso_v2_enabled = B_FALSE; 173 encp->enc_fw_assisted_tso_v2_n_contexts = 0; 174 encp->enc_allow_set_mac_with_installed_filters = B_TRUE; 175 encp->enc_rx_packed_stream_supported = B_FALSE; 176 encp->enc_rx_var_packed_stream_supported = B_FALSE; 177 178 /* Siena supports two 10G ports, and 8 lanes of PCIe Gen2 */ 179 encp->enc_required_pcie_bandwidth_mbps = 2 * 10000; 180 encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN2; 181 182 encp->enc_nvram_update_verify_result_supported = B_FALSE; 183 184 return (0); 185 186 fail2: 187 EFSYS_PROBE(fail2); 188 fail1: 189 EFSYS_PROBE1(fail1, efx_rc_t, rc); 190 191 return (rc); 192 } 193 194 static __checkReturn efx_rc_t 195 siena_phy_cfg( 196 __in efx_nic_t *enp) 197 { 198 #if EFSYS_OPT_PHY_STATS 199 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 200 #endif /* EFSYS_OPT_PHY_STATS */ 201 efx_rc_t rc; 202 203 /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */ 204 if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0) 205 goto fail1; 206 207 #if EFSYS_OPT_PHY_STATS 208 /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */ 209 siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask, 210 NULL, &encp->enc_phy_stat_mask, NULL); 211 #endif /* EFSYS_OPT_PHY_STATS */ 212 213 return (0); 214 215 fail1: 216 EFSYS_PROBE1(fail1, efx_rc_t, rc); 217 218 return (rc); 219 } 220 221 __checkReturn efx_rc_t 222 siena_nic_probe( 223 __in efx_nic_t *enp) 224 { 225 efx_port_t *epp = &(enp->en_port); 226 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 227 siena_link_state_t sls; 228 unsigned int mask; 229 efx_oword_t oword; 230 efx_rc_t rc; 231 232 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 233 234 /* Test BIU */ 235 if ((rc = efx_nic_biu_test(enp)) != 0) 236 goto fail1; 237 238 /* Clear the region register */ 239 EFX_POPULATE_OWORD_4(oword, 240 FRF_AZ_ADR_REGION0, 0, 241 FRF_AZ_ADR_REGION1, (1 << 16), 242 FRF_AZ_ADR_REGION2, (2 << 16), 243 FRF_AZ_ADR_REGION3, (3 << 16)); 244 EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword); 245 246 /* Read clear any assertion state */ 247 if ((rc = efx_mcdi_read_assertion(enp)) != 0) 248 goto fail2; 249 250 /* Exit the assertion handler */ 251 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 252 goto fail3; 253 254 /* Wrestle control from the BMC */ 255 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0) 256 goto fail4; 257 258 if ((rc = siena_board_cfg(enp)) != 0) 259 goto fail5; 260 261 if ((rc = siena_phy_cfg(enp)) != 0) 262 goto fail6; 263 264 /* Obtain the default PHY advertised capabilities */ 265 if ((rc = siena_nic_reset(enp)) != 0) 266 goto fail7; 267 if ((rc = siena_phy_get_link(enp, &sls)) != 0) 268 goto fail8; 269 epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask; 270 epp->ep_adv_cap_mask = sls.sls_adv_cap_mask; 271 272 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM 273 if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0) 274 goto fail9; 275 enp->en_u.siena.enu_partn_mask = mask; 276 #endif 277 278 #if EFSYS_OPT_MAC_STATS 279 /* Wipe the MAC statistics */ 280 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0) 281 goto fail10; 282 #endif 283 284 #if EFSYS_OPT_LOOPBACK 285 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0) 286 goto fail11; 287 #endif 288 289 #if EFSYS_OPT_MON_STATS 290 if ((rc = mcdi_mon_cfg_build(enp)) != 0) 291 goto fail12; 292 #endif 293 294 encp->enc_features = enp->en_features; 295 296 return (0); 297 298 #if EFSYS_OPT_MON_STATS 299 fail12: 300 EFSYS_PROBE(fail12); 301 #endif 302 #if EFSYS_OPT_LOOPBACK 303 fail11: 304 EFSYS_PROBE(fail11); 305 #endif 306 #if EFSYS_OPT_MAC_STATS 307 fail10: 308 EFSYS_PROBE(fail10); 309 #endif 310 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM 311 fail9: 312 EFSYS_PROBE(fail9); 313 #endif 314 fail8: 315 EFSYS_PROBE(fail8); 316 fail7: 317 EFSYS_PROBE(fail7); 318 fail6: 319 EFSYS_PROBE(fail6); 320 fail5: 321 EFSYS_PROBE(fail5); 322 fail4: 323 EFSYS_PROBE(fail4); 324 fail3: 325 EFSYS_PROBE(fail3); 326 fail2: 327 EFSYS_PROBE(fail2); 328 fail1: 329 EFSYS_PROBE1(fail1, efx_rc_t, rc); 330 331 return (rc); 332 } 333 334 __checkReturn efx_rc_t 335 siena_nic_reset( 336 __in efx_nic_t *enp) 337 { 338 efx_mcdi_req_t req; 339 efx_rc_t rc; 340 341 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 342 343 /* siena_nic_reset() is called to recover from BADASSERT failures. */ 344 if ((rc = efx_mcdi_read_assertion(enp)) != 0) 345 goto fail1; 346 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 347 goto fail2; 348 349 /* 350 * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied 351 * for backwards compatibility with PORT_RESET_IN_LEN. 352 */ 353 EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0); 354 355 req.emr_cmd = MC_CMD_ENTITY_RESET; 356 req.emr_in_buf = NULL; 357 req.emr_in_length = 0; 358 req.emr_out_buf = NULL; 359 req.emr_out_length = 0; 360 361 efx_mcdi_execute(enp, &req); 362 363 if (req.emr_rc != 0) { 364 rc = req.emr_rc; 365 goto fail3; 366 } 367 368 return (0); 369 370 fail3: 371 EFSYS_PROBE(fail3); 372 fail2: 373 EFSYS_PROBE(fail2); 374 fail1: 375 EFSYS_PROBE1(fail1, efx_rc_t, rc); 376 377 return (0); 378 } 379 380 static void 381 siena_nic_rx_cfg( 382 __in efx_nic_t *enp) 383 { 384 efx_oword_t oword; 385 386 /* 387 * RX_INGR_EN is always enabled on Siena, because we rely on 388 * the RX parser to be resiliant to missing SOP/EOP. 389 */ 390 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword); 391 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1); 392 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword); 393 394 /* Disable parsing of additional 802.1Q in Q packets */ 395 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); 396 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0); 397 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); 398 } 399 400 static void 401 siena_nic_usrev_dis( 402 __in efx_nic_t *enp) 403 { 404 efx_oword_t oword; 405 406 EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1); 407 EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword); 408 } 409 410 __checkReturn efx_rc_t 411 siena_nic_init( 412 __in efx_nic_t *enp) 413 { 414 efx_rc_t rc; 415 416 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 417 418 /* Enable reporting of some events (e.g. link change) */ 419 if ((rc = efx_mcdi_log_ctrl(enp)) != 0) 420 goto fail1; 421 422 siena_sram_init(enp); 423 424 /* Configure Siena's RX block */ 425 siena_nic_rx_cfg(enp); 426 427 /* Disable USR_EVents for now */ 428 siena_nic_usrev_dis(enp); 429 430 /* bug17057: Ensure set_link is called */ 431 if ((rc = siena_phy_reconfigure(enp)) != 0) 432 goto fail2; 433 434 enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V1; 435 436 return (0); 437 438 fail2: 439 EFSYS_PROBE(fail2); 440 fail1: 441 EFSYS_PROBE1(fail1, efx_rc_t, rc); 442 443 return (rc); 444 } 445 446 void 447 siena_nic_fini( 448 __in efx_nic_t *enp) 449 { 450 _NOTE(ARGUNUSED(enp)) 451 } 452 453 void 454 siena_nic_unprobe( 455 __in efx_nic_t *enp) 456 { 457 #if EFSYS_OPT_MON_STATS 458 mcdi_mon_cfg_free(enp); 459 #endif /* EFSYS_OPT_MON_STATS */ 460 (void) efx_mcdi_drv_attach(enp, B_FALSE); 461 } 462 463 #if EFSYS_OPT_DIAG 464 465 static siena_register_set_t __siena_registers[] = { 466 { FR_AZ_ADR_REGION_REG_OFST, 0, 1 }, 467 { FR_CZ_USR_EV_CFG_OFST, 0, 1 }, 468 { FR_AZ_RX_CFG_REG_OFST, 0, 1 }, 469 { FR_AZ_TX_CFG_REG_OFST, 0, 1 }, 470 { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 }, 471 { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 }, 472 { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 }, 473 { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 }, 474 { FR_AZ_DP_CTRL_REG_OFST, 0, 1 }, 475 { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1}, 476 { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1}, 477 { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1}, 478 { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1} 479 }; 480 481 static const uint32_t __siena_register_masks[] = { 482 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 483 0x000103FF, 0x00000000, 0x00000000, 0x00000000, 484 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000, 485 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF, 486 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF, 487 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000, 488 0x00000003, 0x00000000, 0x00000000, 0x00000000, 489 0x000003FF, 0x00000000, 0x00000000, 0x00000000, 490 0x00000FFF, 0x00000000, 0x00000000, 0x00000000, 491 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 492 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 493 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 494 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000 495 }; 496 497 static siena_register_set_t __siena_tables[] = { 498 { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP, 499 FR_AZ_RX_FILTER_TBL0_ROWS }, 500 { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP, 501 FR_CZ_RX_MAC_FILTER_TBL0_ROWS }, 502 { FR_AZ_RX_DESC_PTR_TBL_OFST, 503 FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS }, 504 { FR_AZ_TX_DESC_PTR_TBL_OFST, 505 FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS }, 506 { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS }, 507 { FR_CZ_TX_FILTER_TBL0_OFST, 508 FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS }, 509 { FR_CZ_TX_MAC_FILTER_TBL0_OFST, 510 FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS } 511 }; 512 513 static const uint32_t __siena_table_masks[] = { 514 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF, 515 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000, 516 0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000, 517 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000, 518 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000, 519 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF, 520 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000, 521 }; 522 523 __checkReturn efx_rc_t 524 siena_nic_test_registers( 525 __in efx_nic_t *enp, 526 __in siena_register_set_t *rsp, 527 __in size_t count) 528 { 529 unsigned int bit; 530 efx_oword_t original; 531 efx_oword_t reg; 532 efx_oword_t buf; 533 efx_rc_t rc; 534 535 while (count > 0) { 536 /* This function is only suitable for registers */ 537 EFSYS_ASSERT(rsp->rows == 1); 538 539 /* bit sweep on and off */ 540 EFSYS_BAR_READO(enp->en_esbp, rsp->address, &original, 541 B_TRUE); 542 for (bit = 0; bit < 128; bit++) { 543 /* Is this bit in the mask? */ 544 if (~(rsp->mask.eo_u32[bit >> 5]) & (1 << bit)) 545 continue; 546 547 /* Test this bit can be set in isolation */ 548 reg = original; 549 EFX_AND_OWORD(reg, rsp->mask); 550 EFX_SET_OWORD_BIT(reg, bit); 551 552 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®, 553 B_TRUE); 554 EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf, 555 B_TRUE); 556 557 EFX_AND_OWORD(buf, rsp->mask); 558 if (memcmp(®, &buf, sizeof (reg))) { 559 rc = EIO; 560 goto fail1; 561 } 562 563 /* Test this bit can be cleared in isolation */ 564 EFX_OR_OWORD(reg, rsp->mask); 565 EFX_CLEAR_OWORD_BIT(reg, bit); 566 567 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®, 568 B_TRUE); 569 EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf, 570 B_TRUE); 571 572 EFX_AND_OWORD(buf, rsp->mask); 573 if (memcmp(®, &buf, sizeof (reg))) { 574 rc = EIO; 575 goto fail2; 576 } 577 } 578 579 /* Restore the old value */ 580 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, 581 B_TRUE); 582 583 --count; 584 ++rsp; 585 } 586 587 return (0); 588 589 fail2: 590 EFSYS_PROBE(fail2); 591 fail1: 592 EFSYS_PROBE1(fail1, efx_rc_t, rc); 593 594 /* Restore the old value */ 595 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, B_TRUE); 596 597 return (rc); 598 } 599 600 __checkReturn efx_rc_t 601 siena_nic_test_tables( 602 __in efx_nic_t *enp, 603 __in siena_register_set_t *rsp, 604 __in efx_pattern_type_t pattern, 605 __in size_t count) 606 { 607 efx_sram_pattern_fn_t func; 608 unsigned int index; 609 unsigned int address; 610 efx_oword_t reg; 611 efx_oword_t buf; 612 efx_rc_t rc; 613 614 EFSYS_ASSERT(pattern < EFX_PATTERN_NTYPES); 615 func = __efx_sram_pattern_fns[pattern]; 616 617 while (count > 0) { 618 /* Write */ 619 address = rsp->address; 620 for (index = 0; index < rsp->rows; ++index) { 621 func(2 * index + 0, B_FALSE, ®.eo_qword[0]); 622 func(2 * index + 1, B_FALSE, ®.eo_qword[1]); 623 EFX_AND_OWORD(reg, rsp->mask); 624 EFSYS_BAR_WRITEO(enp->en_esbp, address, ®, B_TRUE); 625 626 address += rsp->step; 627 } 628 629 /* Read */ 630 address = rsp->address; 631 for (index = 0; index < rsp->rows; ++index) { 632 func(2 * index + 0, B_FALSE, ®.eo_qword[0]); 633 func(2 * index + 1, B_FALSE, ®.eo_qword[1]); 634 EFX_AND_OWORD(reg, rsp->mask); 635 EFSYS_BAR_READO(enp->en_esbp, address, &buf, B_TRUE); 636 if (memcmp(®, &buf, sizeof (reg))) { 637 rc = EIO; 638 goto fail1; 639 } 640 641 address += rsp->step; 642 } 643 644 ++rsp; 645 --count; 646 } 647 648 return (0); 649 650 fail1: 651 EFSYS_PROBE1(fail1, efx_rc_t, rc); 652 653 return (rc); 654 } 655 656 657 __checkReturn efx_rc_t 658 siena_nic_register_test( 659 __in efx_nic_t *enp) 660 { 661 siena_register_set_t *rsp; 662 const uint32_t *dwordp; 663 unsigned int nitems; 664 unsigned int count; 665 efx_rc_t rc; 666 667 /* Fill out the register mask entries */ 668 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks) 669 == EFX_ARRAY_SIZE(__siena_registers) * 4); 670 671 nitems = EFX_ARRAY_SIZE(__siena_registers); 672 dwordp = __siena_register_masks; 673 for (count = 0; count < nitems; ++count) { 674 rsp = __siena_registers + count; 675 rsp->mask.eo_u32[0] = *dwordp++; 676 rsp->mask.eo_u32[1] = *dwordp++; 677 rsp->mask.eo_u32[2] = *dwordp++; 678 rsp->mask.eo_u32[3] = *dwordp++; 679 } 680 681 /* Fill out the register table entries */ 682 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks) 683 == EFX_ARRAY_SIZE(__siena_tables) * 4); 684 685 nitems = EFX_ARRAY_SIZE(__siena_tables); 686 dwordp = __siena_table_masks; 687 for (count = 0; count < nitems; ++count) { 688 rsp = __siena_tables + count; 689 rsp->mask.eo_u32[0] = *dwordp++; 690 rsp->mask.eo_u32[1] = *dwordp++; 691 rsp->mask.eo_u32[2] = *dwordp++; 692 rsp->mask.eo_u32[3] = *dwordp++; 693 } 694 695 if ((rc = siena_nic_test_registers(enp, __siena_registers, 696 EFX_ARRAY_SIZE(__siena_registers))) != 0) 697 goto fail1; 698 699 if ((rc = siena_nic_test_tables(enp, __siena_tables, 700 EFX_PATTERN_BYTE_ALTERNATE, 701 EFX_ARRAY_SIZE(__siena_tables))) != 0) 702 goto fail2; 703 704 if ((rc = siena_nic_test_tables(enp, __siena_tables, 705 EFX_PATTERN_BYTE_CHANGING, 706 EFX_ARRAY_SIZE(__siena_tables))) != 0) 707 goto fail3; 708 709 if ((rc = siena_nic_test_tables(enp, __siena_tables, 710 EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0) 711 goto fail4; 712 713 return (0); 714 715 fail4: 716 EFSYS_PROBE(fail4); 717 fail3: 718 EFSYS_PROBE(fail3); 719 fail2: 720 EFSYS_PROBE(fail2); 721 fail1: 722 EFSYS_PROBE1(fail1, efx_rc_t, rc); 723 724 return (rc); 725 } 726 727 #endif /* EFSYS_OPT_DIAG */ 728 729 #endif /* EFSYS_OPT_SIENA */ 730