1227569Sphilip/*- 2300607Sarybchik * Copyright (c) 2009-2016 Solarflare Communications Inc. 3283514Sarybchik * All rights reserved. 4227569Sphilip * 5227569Sphilip * Redistribution and use in source and binary forms, with or without 6283514Sarybchik * modification, are permitted provided that the following conditions are met: 7227569Sphilip * 8283514Sarybchik * 1. Redistributions of source code must retain the above copyright notice, 9283514Sarybchik * this list of conditions and the following disclaimer. 10283514Sarybchik * 2. Redistributions in binary form must reproduce the above copyright notice, 11283514Sarybchik * this list of conditions and the following disclaimer in the documentation 12283514Sarybchik * and/or other materials provided with the distribution. 13283514Sarybchik * 14283514Sarybchik * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15283514Sarybchik * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16283514Sarybchik * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17283514Sarybchik * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18283514Sarybchik * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19283514Sarybchik * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20283514Sarybchik * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21283514Sarybchik * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22283514Sarybchik * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23283514Sarybchik * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24283514Sarybchik * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25283514Sarybchik * 26283514Sarybchik * The views and conclusions contained in the software and documentation are 27283514Sarybchik * those of the authors and should not be interpreted as representing official 28283514Sarybchik * policies, either expressed or implied, of the FreeBSD Project. 29227569Sphilip */ 30228078Sphilip 31228078Sphilip#include <sys/cdefs.h> 32228078Sphilip__FBSDID("$FreeBSD: stable/11/sys/dev/sfxge/common/siena_nic.c 342445 2018-12-25 07:27:45Z arybchik $"); 33228078Sphilip 34227569Sphilip#include "efx.h" 35227569Sphilip#include "efx_impl.h" 36283514Sarybchik#include "mcdi_mon.h" 37227569Sphilip 38227569Sphilip#if EFSYS_OPT_SIENA 39227569Sphilip 40310933Sarybchik#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM 41310933Sarybchik 42291436Sarybchikstatic __checkReturn efx_rc_t 43227569Sphilipsiena_nic_get_partn_mask( 44227569Sphilip __in efx_nic_t *enp, 45227569Sphilip __out unsigned int *maskp) 46227569Sphilip{ 47227569Sphilip efx_mcdi_req_t req; 48342445Sarybchik EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_TYPES_IN_LEN, 49342445Sarybchik MC_CMD_NVRAM_TYPES_OUT_LEN); 50291436Sarybchik efx_rc_t rc; 51227569Sphilip 52227569Sphilip req.emr_cmd = MC_CMD_NVRAM_TYPES; 53283514Sarybchik req.emr_in_buf = payload; 54283514Sarybchik req.emr_in_length = MC_CMD_NVRAM_TYPES_IN_LEN; 55283514Sarybchik req.emr_out_buf = payload; 56283514Sarybchik req.emr_out_length = MC_CMD_NVRAM_TYPES_OUT_LEN; 57227569Sphilip 58227569Sphilip efx_mcdi_execute(enp, &req); 59227569Sphilip 60227569Sphilip if (req.emr_rc != 0) { 61227569Sphilip rc = req.emr_rc; 62227569Sphilip goto fail1; 63227569Sphilip } 64227569Sphilip 65227569Sphilip if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) { 66227569Sphilip rc = EMSGSIZE; 67227569Sphilip goto fail2; 68227569Sphilip } 69227569Sphilip 70227569Sphilip *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES); 71227569Sphilip 72227569Sphilip return (0); 73227569Sphilip 74227569Sphilipfail2: 75227569Sphilip EFSYS_PROBE(fail2); 76227569Sphilipfail1: 77291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 78227569Sphilip 79227569Sphilip return (rc); 80227569Sphilip} 81227569Sphilip 82310933Sarybchik#endif /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */ 83310933Sarybchik 84291436Sarybchikstatic __checkReturn efx_rc_t 85227569Sphilipsiena_board_cfg( 86227569Sphilip __in efx_nic_t *enp) 87227569Sphilip{ 88227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 89283514Sarybchik uint8_t mac_addr[6]; 90283514Sarybchik efx_dword_t capabilities; 91283514Sarybchik uint32_t board_type; 92283514Sarybchik uint32_t nevq, nrxq, ntxq; 93291436Sarybchik efx_rc_t rc; 94227569Sphilip 95283514Sarybchik /* External port identifier using one-based port numbering */ 96283514Sarybchik encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port; 97283514Sarybchik 98227569Sphilip /* Board configuration */ 99283514Sarybchik if ((rc = efx_mcdi_get_board_cfg(enp, &board_type, 100283514Sarybchik &capabilities, mac_addr)) != 0) 101227569Sphilip goto fail1; 102227569Sphilip 103279048Sarybchik EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr); 104227569Sphilip 105283514Sarybchik encp->enc_board_type = board_type; 106227569Sphilip 107311016Sarybchik /* 108311016Sarybchik * There is no possibility to determine the number of PFs on Siena 109311016Sarybchik * by issuing MCDI request, and it is not an easy task to find the 110311016Sarybchik * value based on the board type, so 'enc_hw_pf_count' is set to 1 111311016Sarybchik */ 112311016Sarybchik encp->enc_hw_pf_count = 1; 113311016Sarybchik 114279048Sarybchik /* Additional capabilities */ 115279048Sarybchik encp->enc_clk_mult = 1; 116283514Sarybchik if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) { 117279048Sarybchik enp->en_features |= EFX_FEATURE_TURBO; 118279048Sarybchik 119283514Sarybchik if (EFX_DWORD_FIELD(capabilities, 120283514Sarybchik MC_CMD_CAPABILITIES_TURBO_ACTIVE)) { 121279048Sarybchik encp->enc_clk_mult = 2; 122283514Sarybchik } 123279048Sarybchik } 124279048Sarybchik 125279182Sarybchik encp->enc_evq_timer_quantum_ns = 126279182Sarybchik EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult; 127279182Sarybchik encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns << 128279182Sarybchik FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000; 129279048Sarybchik 130283514Sarybchik /* When hash header insertion is enabled, Siena inserts 16 bytes */ 131283514Sarybchik encp->enc_rx_prefix_size = 16; 132227569Sphilip 133283514Sarybchik /* Alignment for receive packet DMA buffers */ 134283514Sarybchik encp->enc_rx_buf_align_start = 1; 135283514Sarybchik encp->enc_rx_buf_align_end = 1; 136227569Sphilip 137283514Sarybchik /* Alignment for WPTR updates */ 138283514Sarybchik encp->enc_rx_push_align = 1; 139227569Sphilip 140311765Sarybchik encp->enc_tx_dma_desc_size_max = EFX_MASK32(FSF_AZ_TX_KER_BYTE_COUNT); 141311765Sarybchik /* Fragments must not span 4k boundaries. */ 142311765Sarybchik encp->enc_tx_dma_desc_boundary = 4096; 143311765Sarybchik 144283514Sarybchik /* Resource limits */ 145283514Sarybchik rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq); 146283514Sarybchik if (rc != 0) { 147283514Sarybchik if (rc != ENOTSUP) 148283514Sarybchik goto fail2; 149283514Sarybchik 150283514Sarybchik nevq = 1024; 151283514Sarybchik nrxq = EFX_RXQ_LIMIT_TARGET; 152283514Sarybchik ntxq = EFX_TXQ_LIMIT_TARGET; 153227569Sphilip } 154283514Sarybchik encp->enc_evq_limit = nevq; 155283514Sarybchik encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq); 156283514Sarybchik encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq); 157227569Sphilip 158342407Sarybchik encp->enc_txq_max_ndescs = 4096; 159342407Sarybchik 160227569Sphilip encp->enc_buftbl_limit = SIENA_SRAM_ROWS - 161279098Sarybchik (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) - 162279098Sarybchik (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE)); 163227569Sphilip 164283514Sarybchik encp->enc_hw_tx_insert_vlan_enabled = B_FALSE; 165283514Sarybchik encp->enc_fw_assisted_tso_enabled = B_FALSE; 166293891Sarybchik encp->enc_fw_assisted_tso_v2_enabled = B_FALSE; 167311015Sarybchik encp->enc_fw_assisted_tso_v2_n_contexts = 0; 168291922Sarybchik encp->enc_allow_set_mac_with_installed_filters = B_TRUE; 169283514Sarybchik 170299904Sarybchik /* Siena supports two 10G ports, and 8 lanes of PCIe Gen2 */ 171299904Sarybchik encp->enc_required_pcie_bandwidth_mbps = 2 * 10000; 172299904Sarybchik encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN2; 173299904Sarybchik 174311481Sarybchik encp->enc_fw_verified_nvram_update_required = B_FALSE; 175311481Sarybchik 176227569Sphilip return (0); 177227569Sphilip 178227569Sphilipfail2: 179227569Sphilip EFSYS_PROBE(fail2); 180227569Sphilipfail1: 181291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 182227569Sphilip 183227569Sphilip return (rc); 184227569Sphilip} 185227569Sphilip 186291436Sarybchikstatic __checkReturn efx_rc_t 187227569Sphilipsiena_phy_cfg( 188227569Sphilip __in efx_nic_t *enp) 189227569Sphilip{ 190342424Sarybchik#if EFSYS_OPT_PHY_STATS 191227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 192342424Sarybchik#endif /* EFSYS_OPT_PHY_STATS */ 193291436Sarybchik efx_rc_t rc; 194227569Sphilip 195283514Sarybchik /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */ 196283514Sarybchik if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0) 197227569Sphilip goto fail1; 198227569Sphilip 199227569Sphilip#if EFSYS_OPT_PHY_STATS 200227569Sphilip /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */ 201283514Sarybchik siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask, 202227569Sphilip NULL, &encp->enc_phy_stat_mask, NULL); 203227569Sphilip#endif /* EFSYS_OPT_PHY_STATS */ 204227569Sphilip 205227569Sphilip return (0); 206227569Sphilip 207227569Sphilipfail1: 208291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 209227569Sphilip 210227569Sphilip return (rc); 211227569Sphilip} 212227569Sphilip 213342436Sarybchik#define SIENA_BIU_MAGIC0 0x01234567 214342436Sarybchik#define SIENA_BIU_MAGIC1 0xfedcba98 215342436Sarybchik 216342436Sarybchikstatic __checkReturn efx_rc_t 217342436Sarybchiksiena_nic_biu_test( 218342436Sarybchik __in efx_nic_t *enp) 219342436Sarybchik{ 220342436Sarybchik efx_oword_t oword; 221342436Sarybchik efx_rc_t rc; 222342436Sarybchik 223342436Sarybchik /* 224342436Sarybchik * Write magic values to scratch registers 0 and 1, then 225342436Sarybchik * verify that the values were written correctly. Interleave 226342436Sarybchik * the accesses to ensure that the BIU is not just reading 227342436Sarybchik * back the cached value that was last written. 228342436Sarybchik */ 229342436Sarybchik EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC0); 230342436Sarybchik EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); 231342436Sarybchik 232342436Sarybchik EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC1); 233342436Sarybchik EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); 234342436Sarybchik 235342436Sarybchik EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); 236342436Sarybchik if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC0) { 237342436Sarybchik rc = EIO; 238342436Sarybchik goto fail1; 239342436Sarybchik } 240342436Sarybchik 241342436Sarybchik EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); 242342436Sarybchik if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC1) { 243342436Sarybchik rc = EIO; 244342436Sarybchik goto fail2; 245342436Sarybchik } 246342436Sarybchik 247342436Sarybchik /* 248342436Sarybchik * Perform the same test, with the values swapped. This 249342436Sarybchik * ensures that subsequent tests don't start with the correct 250342436Sarybchik * values already written into the scratch registers. 251342436Sarybchik */ 252342436Sarybchik EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC1); 253342436Sarybchik EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); 254342436Sarybchik 255342436Sarybchik EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, SIENA_BIU_MAGIC0); 256342436Sarybchik EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); 257342436Sarybchik 258342436Sarybchik EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE); 259342436Sarybchik if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC1) { 260342436Sarybchik rc = EIO; 261342436Sarybchik goto fail3; 262342436Sarybchik } 263342436Sarybchik 264342436Sarybchik EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE); 265342436Sarybchik if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != SIENA_BIU_MAGIC0) { 266342436Sarybchik rc = EIO; 267342436Sarybchik goto fail4; 268342436Sarybchik } 269342436Sarybchik 270342436Sarybchik return (0); 271342436Sarybchik 272342436Sarybchikfail4: 273342436Sarybchik EFSYS_PROBE(fail4); 274342436Sarybchikfail3: 275342436Sarybchik EFSYS_PROBE(fail3); 276342436Sarybchikfail2: 277342436Sarybchik EFSYS_PROBE(fail2); 278342436Sarybchikfail1: 279342436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 280342436Sarybchik 281342436Sarybchik return (rc); 282342436Sarybchik} 283342436Sarybchik 284291436Sarybchik __checkReturn efx_rc_t 285227569Sphilipsiena_nic_probe( 286227569Sphilip __in efx_nic_t *enp) 287227569Sphilip{ 288227569Sphilip efx_port_t *epp = &(enp->en_port); 289227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 290227569Sphilip siena_link_state_t sls; 291227569Sphilip unsigned int mask; 292283514Sarybchik efx_oword_t oword; 293291436Sarybchik efx_rc_t rc; 294227569Sphilip 295227569Sphilip EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 296227569Sphilip 297283514Sarybchik /* Test BIU */ 298342436Sarybchik if ((rc = siena_nic_biu_test(enp)) != 0) 299227569Sphilip goto fail1; 300227569Sphilip 301283514Sarybchik /* Clear the region register */ 302283514Sarybchik EFX_POPULATE_OWORD_4(oword, 303283514Sarybchik FRF_AZ_ADR_REGION0, 0, 304283514Sarybchik FRF_AZ_ADR_REGION1, (1 << 16), 305283514Sarybchik FRF_AZ_ADR_REGION2, (2 << 16), 306283514Sarybchik FRF_AZ_ADR_REGION3, (3 << 16)); 307283514Sarybchik EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword); 308283514Sarybchik 309283514Sarybchik /* Read clear any assertion state */ 310283514Sarybchik if ((rc = efx_mcdi_read_assertion(enp)) != 0) 311227569Sphilip goto fail2; 312227569Sphilip 313283514Sarybchik /* Exit the assertion handler */ 314283514Sarybchik if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 315227569Sphilip goto fail3; 316227569Sphilip 317283514Sarybchik /* Wrestle control from the BMC */ 318283514Sarybchik if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0) 319227569Sphilip goto fail4; 320227569Sphilip 321283514Sarybchik if ((rc = siena_board_cfg(enp)) != 0) 322227569Sphilip goto fail5; 323227569Sphilip 324283514Sarybchik if ((rc = siena_phy_cfg(enp)) != 0) 325283514Sarybchik goto fail6; 326283514Sarybchik 327227569Sphilip /* Obtain the default PHY advertised capabilities */ 328227569Sphilip if ((rc = siena_nic_reset(enp)) != 0) 329283514Sarybchik goto fail7; 330227569Sphilip if ((rc = siena_phy_get_link(enp, &sls)) != 0) 331283514Sarybchik goto fail8; 332227569Sphilip epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask; 333227569Sphilip epp->ep_adv_cap_mask = sls.sls_adv_cap_mask; 334227569Sphilip 335227569Sphilip#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM 336227569Sphilip if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0) 337283514Sarybchik goto fail9; 338227569Sphilip enp->en_u.siena.enu_partn_mask = mask; 339227569Sphilip#endif 340227569Sphilip 341227569Sphilip#if EFSYS_OPT_MAC_STATS 342227569Sphilip /* Wipe the MAC statistics */ 343283514Sarybchik if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0) 344283514Sarybchik goto fail10; 345227569Sphilip#endif 346227569Sphilip 347227569Sphilip#if EFSYS_OPT_LOOPBACK 348283514Sarybchik if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0) 349283514Sarybchik goto fail11; 350227569Sphilip#endif 351227569Sphilip 352227569Sphilip#if EFSYS_OPT_MON_STATS 353283514Sarybchik if ((rc = mcdi_mon_cfg_build(enp)) != 0) 354283514Sarybchik goto fail12; 355227569Sphilip#endif 356227569Sphilip 357227569Sphilip encp->enc_features = enp->en_features; 358227569Sphilip 359227569Sphilip return (0); 360227569Sphilip 361227569Sphilip#if EFSYS_OPT_MON_STATS 362283514Sarybchikfail12: 363283514Sarybchik EFSYS_PROBE(fail12); 364283514Sarybchik#endif 365283514Sarybchik#if EFSYS_OPT_LOOPBACK 366227569Sphilipfail11: 367227569Sphilip EFSYS_PROBE(fail11); 368227569Sphilip#endif 369283514Sarybchik#if EFSYS_OPT_MAC_STATS 370227569Sphilipfail10: 371227569Sphilip EFSYS_PROBE(fail10); 372227569Sphilip#endif 373283514Sarybchik#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM 374227569Sphilipfail9: 375227569Sphilip EFSYS_PROBE(fail9); 376227569Sphilip#endif 377227569Sphilipfail8: 378227569Sphilip EFSYS_PROBE(fail8); 379227569Sphilipfail7: 380227569Sphilip EFSYS_PROBE(fail7); 381227569Sphilipfail6: 382227569Sphilip EFSYS_PROBE(fail6); 383227569Sphilipfail5: 384227569Sphilip EFSYS_PROBE(fail5); 385227569Sphilipfail4: 386227569Sphilip EFSYS_PROBE(fail4); 387227569Sphilipfail3: 388227569Sphilip EFSYS_PROBE(fail3); 389227569Sphilipfail2: 390227569Sphilip EFSYS_PROBE(fail2); 391227569Sphilipfail1: 392291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 393227569Sphilip 394227569Sphilip return (rc); 395227569Sphilip} 396227569Sphilip 397291436Sarybchik __checkReturn efx_rc_t 398227569Sphilipsiena_nic_reset( 399227569Sphilip __in efx_nic_t *enp) 400227569Sphilip{ 401227569Sphilip efx_mcdi_req_t req; 402291436Sarybchik efx_rc_t rc; 403227569Sphilip 404227569Sphilip EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 405227569Sphilip 406227569Sphilip /* siena_nic_reset() is called to recover from BADASSERT failures. */ 407283514Sarybchik if ((rc = efx_mcdi_read_assertion(enp)) != 0) 408227569Sphilip goto fail1; 409283514Sarybchik if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0) 410227569Sphilip goto fail2; 411227569Sphilip 412283514Sarybchik /* 413283514Sarybchik * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied 414283514Sarybchik * for backwards compatibility with PORT_RESET_IN_LEN. 415283514Sarybchik */ 416283514Sarybchik EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0); 417283514Sarybchik 418283514Sarybchik req.emr_cmd = MC_CMD_ENTITY_RESET; 419227569Sphilip req.emr_in_buf = NULL; 420227569Sphilip req.emr_in_length = 0; 421227569Sphilip req.emr_out_buf = NULL; 422227569Sphilip req.emr_out_length = 0; 423227569Sphilip 424227569Sphilip efx_mcdi_execute(enp, &req); 425227569Sphilip 426227569Sphilip if (req.emr_rc != 0) { 427227569Sphilip rc = req.emr_rc; 428227569Sphilip goto fail3; 429227569Sphilip } 430227569Sphilip 431227569Sphilip return (0); 432227569Sphilip 433227569Sphilipfail3: 434227569Sphilip EFSYS_PROBE(fail3); 435227569Sphilipfail2: 436227569Sphilip EFSYS_PROBE(fail2); 437227569Sphilipfail1: 438291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 439227569Sphilip 440227569Sphilip return (0); 441227569Sphilip} 442227569Sphilip 443227569Sphilipstatic void 444227569Sphilipsiena_nic_rx_cfg( 445227569Sphilip __in efx_nic_t *enp) 446227569Sphilip{ 447227569Sphilip efx_oword_t oword; 448227569Sphilip 449227569Sphilip /* 450227569Sphilip * RX_INGR_EN is always enabled on Siena, because we rely on 451227569Sphilip * the RX parser to be resiliant to missing SOP/EOP. 452227569Sphilip */ 453227569Sphilip EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword); 454227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1); 455227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword); 456227569Sphilip 457227569Sphilip /* Disable parsing of additional 802.1Q in Q packets */ 458227569Sphilip EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); 459227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0); 460227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); 461227569Sphilip} 462227569Sphilip 463227569Sphilipstatic void 464227569Sphilipsiena_nic_usrev_dis( 465227569Sphilip __in efx_nic_t *enp) 466227569Sphilip{ 467227569Sphilip efx_oword_t oword; 468227569Sphilip 469227569Sphilip EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1); 470227569Sphilip EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword); 471227569Sphilip} 472227569Sphilip 473291436Sarybchik __checkReturn efx_rc_t 474227569Sphilipsiena_nic_init( 475227569Sphilip __in efx_nic_t *enp) 476227569Sphilip{ 477291436Sarybchik efx_rc_t rc; 478227569Sphilip 479227569Sphilip EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 480227569Sphilip 481283514Sarybchik /* Enable reporting of some events (e.g. link change) */ 482283514Sarybchik if ((rc = efx_mcdi_log_ctrl(enp)) != 0) 483227569Sphilip goto fail1; 484227569Sphilip 485227569Sphilip siena_sram_init(enp); 486227569Sphilip 487227569Sphilip /* Configure Siena's RX block */ 488227569Sphilip siena_nic_rx_cfg(enp); 489227569Sphilip 490227569Sphilip /* Disable USR_EVents for now */ 491227569Sphilip siena_nic_usrev_dis(enp); 492227569Sphilip 493227569Sphilip /* bug17057: Ensure set_link is called */ 494227569Sphilip if ((rc = siena_phy_reconfigure(enp)) != 0) 495227569Sphilip goto fail2; 496227569Sphilip 497291923Sarybchik enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V1; 498291923Sarybchik 499227569Sphilip return (0); 500227569Sphilip 501227569Sphilipfail2: 502227569Sphilip EFSYS_PROBE(fail2); 503227569Sphilipfail1: 504291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 505227569Sphilip 506227569Sphilip return (rc); 507227569Sphilip} 508227569Sphilip 509227569Sphilip void 510227569Sphilipsiena_nic_fini( 511227569Sphilip __in efx_nic_t *enp) 512227569Sphilip{ 513227569Sphilip _NOTE(ARGUNUSED(enp)) 514227569Sphilip} 515227569Sphilip 516227569Sphilip void 517227569Sphilipsiena_nic_unprobe( 518227569Sphilip __in efx_nic_t *enp) 519227569Sphilip{ 520283514Sarybchik#if EFSYS_OPT_MON_STATS 521283514Sarybchik mcdi_mon_cfg_free(enp); 522283514Sarybchik#endif /* EFSYS_OPT_MON_STATS */ 523283514Sarybchik (void) efx_mcdi_drv_attach(enp, B_FALSE); 524227569Sphilip} 525227569Sphilip 526227569Sphilip#if EFSYS_OPT_DIAG 527227569Sphilip 528342425Sarybchikstatic siena_register_set_t __siena_registers[] = { 529227569Sphilip { FR_AZ_ADR_REGION_REG_OFST, 0, 1 }, 530227569Sphilip { FR_CZ_USR_EV_CFG_OFST, 0, 1 }, 531227569Sphilip { FR_AZ_RX_CFG_REG_OFST, 0, 1 }, 532227569Sphilip { FR_AZ_TX_CFG_REG_OFST, 0, 1 }, 533227569Sphilip { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 }, 534227569Sphilip { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 }, 535227569Sphilip { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 }, 536227569Sphilip { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 }, 537227569Sphilip { FR_AZ_DP_CTRL_REG_OFST, 0, 1 }, 538227569Sphilip { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1}, 539227569Sphilip { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1}, 540227569Sphilip { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1}, 541227569Sphilip { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1} 542227569Sphilip}; 543227569Sphilip 544283514Sarybchikstatic const uint32_t __siena_register_masks[] = { 545227569Sphilip 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 546227569Sphilip 0x000103FF, 0x00000000, 0x00000000, 0x00000000, 547227569Sphilip 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000, 548227569Sphilip 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF, 549227569Sphilip 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF, 550227569Sphilip 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000, 551227569Sphilip 0x00000003, 0x00000000, 0x00000000, 0x00000000, 552227569Sphilip 0x000003FF, 0x00000000, 0x00000000, 0x00000000, 553227569Sphilip 0x00000FFF, 0x00000000, 0x00000000, 0x00000000, 554227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 555227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 556227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 557227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000 558227569Sphilip}; 559227569Sphilip 560342425Sarybchikstatic siena_register_set_t __siena_tables[] = { 561227569Sphilip { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP, 562227569Sphilip FR_AZ_RX_FILTER_TBL0_ROWS }, 563227569Sphilip { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP, 564227569Sphilip FR_CZ_RX_MAC_FILTER_TBL0_ROWS }, 565227569Sphilip { FR_AZ_RX_DESC_PTR_TBL_OFST, 566227569Sphilip FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS }, 567227569Sphilip { FR_AZ_TX_DESC_PTR_TBL_OFST, 568227569Sphilip FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS }, 569227569Sphilip { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS }, 570227569Sphilip { FR_CZ_TX_FILTER_TBL0_OFST, 571227569Sphilip FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS }, 572227569Sphilip { FR_CZ_TX_MAC_FILTER_TBL0_OFST, 573227569Sphilip FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS } 574227569Sphilip}; 575227569Sphilip 576283514Sarybchikstatic const uint32_t __siena_table_masks[] = { 577227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF, 578227569Sphilip 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000, 579279095Sarybchik 0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000, 580227569Sphilip 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000, 581227569Sphilip 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000, 582227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF, 583227569Sphilip 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000, 584227569Sphilip}; 585227569Sphilip 586291436Sarybchik __checkReturn efx_rc_t 587342425Sarybchiksiena_nic_test_registers( 588342425Sarybchik __in efx_nic_t *enp, 589342425Sarybchik __in siena_register_set_t *rsp, 590342425Sarybchik __in size_t count) 591342425Sarybchik{ 592342425Sarybchik unsigned int bit; 593342425Sarybchik efx_oword_t original; 594342425Sarybchik efx_oword_t reg; 595342425Sarybchik efx_oword_t buf; 596342425Sarybchik efx_rc_t rc; 597342425Sarybchik 598342425Sarybchik while (count > 0) { 599342425Sarybchik /* This function is only suitable for registers */ 600342425Sarybchik EFSYS_ASSERT(rsp->rows == 1); 601342425Sarybchik 602342425Sarybchik /* bit sweep on and off */ 603342425Sarybchik EFSYS_BAR_READO(enp->en_esbp, rsp->address, &original, 604342425Sarybchik B_TRUE); 605342425Sarybchik for (bit = 0; bit < 128; bit++) { 606342425Sarybchik /* Is this bit in the mask? */ 607342425Sarybchik if (~(rsp->mask.eo_u32[bit >> 5]) & (1 << bit)) 608342425Sarybchik continue; 609342425Sarybchik 610342425Sarybchik /* Test this bit can be set in isolation */ 611342425Sarybchik reg = original; 612342425Sarybchik EFX_AND_OWORD(reg, rsp->mask); 613342425Sarybchik EFX_SET_OWORD_BIT(reg, bit); 614342425Sarybchik 615342425Sarybchik EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®, 616342425Sarybchik B_TRUE); 617342425Sarybchik EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf, 618342425Sarybchik B_TRUE); 619342425Sarybchik 620342425Sarybchik EFX_AND_OWORD(buf, rsp->mask); 621342425Sarybchik if (memcmp(®, &buf, sizeof (reg))) { 622342425Sarybchik rc = EIO; 623342425Sarybchik goto fail1; 624342425Sarybchik } 625342425Sarybchik 626342425Sarybchik /* Test this bit can be cleared in isolation */ 627342425Sarybchik EFX_OR_OWORD(reg, rsp->mask); 628342425Sarybchik EFX_CLEAR_OWORD_BIT(reg, bit); 629342425Sarybchik 630342425Sarybchik EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, ®, 631342425Sarybchik B_TRUE); 632342425Sarybchik EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf, 633342425Sarybchik B_TRUE); 634342425Sarybchik 635342425Sarybchik EFX_AND_OWORD(buf, rsp->mask); 636342425Sarybchik if (memcmp(®, &buf, sizeof (reg))) { 637342425Sarybchik rc = EIO; 638342425Sarybchik goto fail2; 639342425Sarybchik } 640342425Sarybchik } 641342425Sarybchik 642342425Sarybchik /* Restore the old value */ 643342425Sarybchik EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, 644342425Sarybchik B_TRUE); 645342425Sarybchik 646342425Sarybchik --count; 647342425Sarybchik ++rsp; 648342425Sarybchik } 649342425Sarybchik 650342425Sarybchik return (0); 651342425Sarybchik 652342425Sarybchikfail2: 653342425Sarybchik EFSYS_PROBE(fail2); 654342425Sarybchikfail1: 655342425Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 656342425Sarybchik 657342425Sarybchik /* Restore the old value */ 658342425Sarybchik EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, B_TRUE); 659342425Sarybchik 660342425Sarybchik return (rc); 661342425Sarybchik} 662342425Sarybchik 663342425Sarybchik __checkReturn efx_rc_t 664342425Sarybchiksiena_nic_test_tables( 665342425Sarybchik __in efx_nic_t *enp, 666342425Sarybchik __in siena_register_set_t *rsp, 667342425Sarybchik __in efx_pattern_type_t pattern, 668342425Sarybchik __in size_t count) 669342425Sarybchik{ 670342425Sarybchik efx_sram_pattern_fn_t func; 671342425Sarybchik unsigned int index; 672342425Sarybchik unsigned int address; 673342425Sarybchik efx_oword_t reg; 674342425Sarybchik efx_oword_t buf; 675342425Sarybchik efx_rc_t rc; 676342425Sarybchik 677342425Sarybchik EFSYS_ASSERT(pattern < EFX_PATTERN_NTYPES); 678342425Sarybchik func = __efx_sram_pattern_fns[pattern]; 679342425Sarybchik 680342425Sarybchik while (count > 0) { 681342425Sarybchik /* Write */ 682342425Sarybchik address = rsp->address; 683342425Sarybchik for (index = 0; index < rsp->rows; ++index) { 684342425Sarybchik func(2 * index + 0, B_FALSE, ®.eo_qword[0]); 685342425Sarybchik func(2 * index + 1, B_FALSE, ®.eo_qword[1]); 686342425Sarybchik EFX_AND_OWORD(reg, rsp->mask); 687342425Sarybchik EFSYS_BAR_WRITEO(enp->en_esbp, address, ®, B_TRUE); 688342425Sarybchik 689342425Sarybchik address += rsp->step; 690342425Sarybchik } 691342425Sarybchik 692342425Sarybchik /* Read */ 693342425Sarybchik address = rsp->address; 694342425Sarybchik for (index = 0; index < rsp->rows; ++index) { 695342425Sarybchik func(2 * index + 0, B_FALSE, ®.eo_qword[0]); 696342425Sarybchik func(2 * index + 1, B_FALSE, ®.eo_qword[1]); 697342425Sarybchik EFX_AND_OWORD(reg, rsp->mask); 698342425Sarybchik EFSYS_BAR_READO(enp->en_esbp, address, &buf, B_TRUE); 699342425Sarybchik if (memcmp(®, &buf, sizeof (reg))) { 700342425Sarybchik rc = EIO; 701342425Sarybchik goto fail1; 702342425Sarybchik } 703342425Sarybchik 704342425Sarybchik address += rsp->step; 705342425Sarybchik } 706342425Sarybchik 707342425Sarybchik ++rsp; 708342425Sarybchik --count; 709342425Sarybchik } 710342425Sarybchik 711342425Sarybchik return (0); 712342425Sarybchik 713342425Sarybchikfail1: 714342425Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 715342425Sarybchik 716342425Sarybchik return (rc); 717342425Sarybchik} 718342425Sarybchik 719342425Sarybchik 720342425Sarybchik __checkReturn efx_rc_t 721227569Sphilipsiena_nic_register_test( 722227569Sphilip __in efx_nic_t *enp) 723227569Sphilip{ 724342425Sarybchik siena_register_set_t *rsp; 725227569Sphilip const uint32_t *dwordp; 726227569Sphilip unsigned int nitems; 727227569Sphilip unsigned int count; 728291436Sarybchik efx_rc_t rc; 729227569Sphilip 730227569Sphilip /* Fill out the register mask entries */ 731227569Sphilip EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks) 732227569Sphilip == EFX_ARRAY_SIZE(__siena_registers) * 4); 733227569Sphilip 734227569Sphilip nitems = EFX_ARRAY_SIZE(__siena_registers); 735227569Sphilip dwordp = __siena_register_masks; 736227569Sphilip for (count = 0; count < nitems; ++count) { 737227569Sphilip rsp = __siena_registers + count; 738227569Sphilip rsp->mask.eo_u32[0] = *dwordp++; 739227569Sphilip rsp->mask.eo_u32[1] = *dwordp++; 740227569Sphilip rsp->mask.eo_u32[2] = *dwordp++; 741227569Sphilip rsp->mask.eo_u32[3] = *dwordp++; 742227569Sphilip } 743227569Sphilip 744227569Sphilip /* Fill out the register table entries */ 745227569Sphilip EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks) 746227569Sphilip == EFX_ARRAY_SIZE(__siena_tables) * 4); 747227569Sphilip 748227569Sphilip nitems = EFX_ARRAY_SIZE(__siena_tables); 749227569Sphilip dwordp = __siena_table_masks; 750227569Sphilip for (count = 0; count < nitems; ++count) { 751227569Sphilip rsp = __siena_tables + count; 752227569Sphilip rsp->mask.eo_u32[0] = *dwordp++; 753227569Sphilip rsp->mask.eo_u32[1] = *dwordp++; 754227569Sphilip rsp->mask.eo_u32[2] = *dwordp++; 755227569Sphilip rsp->mask.eo_u32[3] = *dwordp++; 756227569Sphilip } 757227569Sphilip 758342425Sarybchik if ((rc = siena_nic_test_registers(enp, __siena_registers, 759227569Sphilip EFX_ARRAY_SIZE(__siena_registers))) != 0) 760227569Sphilip goto fail1; 761227569Sphilip 762342425Sarybchik if ((rc = siena_nic_test_tables(enp, __siena_tables, 763227569Sphilip EFX_PATTERN_BYTE_ALTERNATE, 764227569Sphilip EFX_ARRAY_SIZE(__siena_tables))) != 0) 765227569Sphilip goto fail2; 766227569Sphilip 767342425Sarybchik if ((rc = siena_nic_test_tables(enp, __siena_tables, 768227569Sphilip EFX_PATTERN_BYTE_CHANGING, 769227569Sphilip EFX_ARRAY_SIZE(__siena_tables))) != 0) 770227569Sphilip goto fail3; 771227569Sphilip 772342425Sarybchik if ((rc = siena_nic_test_tables(enp, __siena_tables, 773227569Sphilip EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0) 774227569Sphilip goto fail4; 775227569Sphilip 776227569Sphilip return (0); 777227569Sphilip 778227569Sphilipfail4: 779227569Sphilip EFSYS_PROBE(fail4); 780227569Sphilipfail3: 781227569Sphilip EFSYS_PROBE(fail3); 782227569Sphilipfail2: 783227569Sphilip EFSYS_PROBE(fail2); 784227569Sphilipfail1: 785291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 786227569Sphilip 787227569Sphilip return (rc); 788227569Sphilip} 789227569Sphilip 790227569Sphilip#endif /* EFSYS_OPT_DIAG */ 791227569Sphilip 792227569Sphilip#endif /* EFSYS_OPT_SIENA */ 793