siena_nic.c revision 279182
1227569Sphilip/*- 2227569Sphilip * Copyright 2009 Solarflare Communications Inc. All rights reserved. 3227569Sphilip * 4227569Sphilip * Redistribution and use in source and binary forms, with or without 5227569Sphilip * modification, are permitted provided that the following conditions 6227569Sphilip * are met: 7227569Sphilip * 1. Redistributions of source code must retain the above copyright 8227569Sphilip * notice, this list of conditions and the following disclaimer. 9227569Sphilip * 2. Redistributions in binary form must reproduce the above copyright 10227569Sphilip * notice, this list of conditions and the following disclaimer in the 11227569Sphilip * documentation and/or other materials provided with the distribution. 12227569Sphilip * 13227569Sphilip * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND 14227569Sphilip * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15227569Sphilip * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16227569Sphilip * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17227569Sphilip * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18227569Sphilip * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19227569Sphilip * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20227569Sphilip * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21227569Sphilip * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22227569Sphilip * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23227569Sphilip * SUCH DAMAGE. 24227569Sphilip */ 25228078Sphilip 26228078Sphilip#include <sys/cdefs.h> 27228078Sphilip__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/siena_nic.c 279182 2015-02-22 19:13:52Z arybchik $"); 28228078Sphilip 29227569Sphilip#include "efsys.h" 30227569Sphilip#include "efx.h" 31227569Sphilip#include "efx_impl.h" 32227569Sphilip 33227569Sphilip#if EFSYS_OPT_SIENA 34227569Sphilip 35227569Sphilipstatic __checkReturn int 36227569Sphilipsiena_nic_get_partn_mask( 37227569Sphilip __in efx_nic_t *enp, 38227569Sphilip __out unsigned int *maskp) 39227569Sphilip{ 40227569Sphilip efx_mcdi_req_t req; 41227569Sphilip uint8_t outbuf[MC_CMD_NVRAM_TYPES_OUT_LEN]; 42227569Sphilip int rc; 43227569Sphilip 44227569Sphilip req.emr_cmd = MC_CMD_NVRAM_TYPES; 45227569Sphilip EFX_STATIC_ASSERT(MC_CMD_NVRAM_TYPES_IN_LEN == 0); 46227569Sphilip req.emr_in_buf = NULL; 47227569Sphilip req.emr_in_length = 0; 48227569Sphilip req.emr_out_buf = outbuf; 49227569Sphilip req.emr_out_length = sizeof (outbuf); 50227569Sphilip 51227569Sphilip efx_mcdi_execute(enp, &req); 52227569Sphilip 53227569Sphilip if (req.emr_rc != 0) { 54227569Sphilip rc = req.emr_rc; 55227569Sphilip goto fail1; 56227569Sphilip } 57227569Sphilip 58227569Sphilip if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) { 59227569Sphilip rc = EMSGSIZE; 60227569Sphilip goto fail2; 61227569Sphilip } 62227569Sphilip 63227569Sphilip *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES); 64227569Sphilip 65227569Sphilip return (0); 66227569Sphilip 67227569Sphilipfail2: 68227569Sphilip EFSYS_PROBE(fail2); 69227569Sphilipfail1: 70227569Sphilip EFSYS_PROBE1(fail1, int, rc); 71227569Sphilip 72227569Sphilip return (rc); 73227569Sphilip} 74227569Sphilip 75227569Sphilipstatic __checkReturn int 76227569Sphilipsiena_nic_exit_assertion_handler( 77227569Sphilip __in efx_nic_t *enp) 78227569Sphilip{ 79227569Sphilip efx_mcdi_req_t req; 80227569Sphilip uint8_t payload[MC_CMD_REBOOT_IN_LEN]; 81227569Sphilip int rc; 82227569Sphilip 83227569Sphilip req.emr_cmd = MC_CMD_REBOOT; 84227569Sphilip req.emr_in_buf = payload; 85227569Sphilip req.emr_in_length = MC_CMD_REBOOT_IN_LEN; 86227569Sphilip EFX_STATIC_ASSERT(MC_CMD_REBOOT_OUT_LEN == 0); 87227569Sphilip req.emr_out_buf = NULL; 88227569Sphilip req.emr_out_length = 0; 89227569Sphilip 90227569Sphilip MCDI_IN_SET_DWORD(req, REBOOT_IN_FLAGS, 91227569Sphilip MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION); 92227569Sphilip 93227569Sphilip efx_mcdi_execute(enp, &req); 94227569Sphilip 95227569Sphilip if (req.emr_rc != 0 && req.emr_rc != EIO) { 96227569Sphilip rc = req.emr_rc; 97227569Sphilip goto fail1; 98227569Sphilip } 99227569Sphilip 100227569Sphilip return (0); 101227569Sphilip 102227569Sphilipfail1: 103227569Sphilip EFSYS_PROBE1(fail1, int, rc); 104227569Sphilip 105227569Sphilip return (rc); 106227569Sphilip} 107227569Sphilip 108227569Sphilipstatic __checkReturn int 109227569Sphilipsiena_nic_read_assertion( 110227569Sphilip __in efx_nic_t *enp) 111227569Sphilip{ 112227569Sphilip efx_mcdi_req_t req; 113227569Sphilip uint8_t payload[MAX(MC_CMD_GET_ASSERTS_IN_LEN, 114227569Sphilip MC_CMD_GET_ASSERTS_OUT_LEN)]; 115227569Sphilip const char *reason; 116227569Sphilip unsigned int flags; 117227569Sphilip unsigned int index; 118227569Sphilip unsigned int ofst; 119227569Sphilip int retry; 120227569Sphilip int rc; 121227569Sphilip 122227569Sphilip /* 123227569Sphilip * Before we attempt to chat to the MC, we should verify that the MC 124227569Sphilip * isn't in it's assertion handler, either due to a previous reboot, 125227569Sphilip * or because we're reinitializing due to an eec_exception(). 126227569Sphilip * 127227569Sphilip * Use GET_ASSERTS to read any assertion state that may be present. 128227569Sphilip * Retry this command twice. Once because a boot-time assertion failure 129227569Sphilip * might cause the 1st MCDI request to fail. And once again because 130227569Sphilip * we might race with siena_nic_exit_assertion_handler() running on the 131227569Sphilip * other port. 132227569Sphilip */ 133227569Sphilip retry = 2; 134227569Sphilip do { 135227569Sphilip req.emr_cmd = MC_CMD_GET_ASSERTS; 136227569Sphilip req.emr_in_buf = payload; 137227569Sphilip req.emr_in_length = MC_CMD_GET_ASSERTS_IN_LEN; 138227569Sphilip req.emr_out_buf = payload; 139227569Sphilip req.emr_out_length = MC_CMD_GET_ASSERTS_OUT_LEN; 140227569Sphilip 141227569Sphilip MCDI_IN_SET_DWORD(req, GET_ASSERTS_IN_CLEAR, 1); 142227569Sphilip efx_mcdi_execute(enp, &req); 143227569Sphilip 144227569Sphilip } while ((req.emr_rc == EINTR || req.emr_rc == EIO) && retry-- > 0); 145227569Sphilip 146227569Sphilip if (req.emr_rc != 0) { 147227569Sphilip rc = req.emr_rc; 148227569Sphilip goto fail1; 149227569Sphilip } 150227569Sphilip 151227569Sphilip if (req.emr_out_length_used < MC_CMD_GET_ASSERTS_OUT_LEN) { 152227569Sphilip rc = EMSGSIZE; 153227569Sphilip goto fail2; 154227569Sphilip } 155227569Sphilip 156227569Sphilip /* Print out any assertion state recorded */ 157227569Sphilip flags = MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_GLOBAL_FLAGS); 158227569Sphilip if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS) 159227569Sphilip return (0); 160227569Sphilip 161227569Sphilip reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL) 162227569Sphilip ? "system-level assertion" 163227569Sphilip : (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL) 164227569Sphilip ? "thread-level assertion" 165227569Sphilip : (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED) 166227569Sphilip ? "watchdog reset" 167227569Sphilip : "unknown assertion"; 168227569Sphilip EFSYS_PROBE3(mcpu_assertion, 169227569Sphilip const char *, reason, unsigned int, 170227569Sphilip MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_SAVED_PC_OFFS), 171227569Sphilip unsigned int, 172227569Sphilip MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_THREAD_OFFS)); 173227569Sphilip 174227569Sphilip /* Print out the registers */ 175227569Sphilip ofst = MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST; 176227569Sphilip for (index = 1; index < 32; index++) { 177227569Sphilip EFSYS_PROBE2(mcpu_register, unsigned int, index, unsigned int, 178227569Sphilip EFX_DWORD_FIELD(*MCDI_OUT(req, efx_dword_t, ofst), 179227569Sphilip EFX_DWORD_0)); 180227569Sphilip ofst += sizeof (efx_dword_t); 181227569Sphilip } 182227569Sphilip EFSYS_ASSERT(ofst <= MC_CMD_GET_ASSERTS_OUT_LEN); 183227569Sphilip 184227569Sphilip return (0); 185227569Sphilip 186227569Sphilipfail2: 187227569Sphilip EFSYS_PROBE(fail2); 188227569Sphilipfail1: 189227569Sphilip EFSYS_PROBE1(fail1, int, rc); 190227569Sphilip 191227569Sphilip return (rc); 192227569Sphilip} 193227569Sphilip 194227569Sphilipstatic __checkReturn int 195227569Sphilipsiena_nic_attach( 196227569Sphilip __in efx_nic_t *enp, 197227569Sphilip __in boolean_t attach) 198227569Sphilip{ 199227569Sphilip efx_mcdi_req_t req; 200227569Sphilip uint8_t payload[MC_CMD_DRV_ATTACH_IN_LEN]; 201227569Sphilip int rc; 202227569Sphilip 203227569Sphilip req.emr_cmd = MC_CMD_DRV_ATTACH; 204227569Sphilip req.emr_in_buf = payload; 205227569Sphilip req.emr_in_length = MC_CMD_DRV_ATTACH_IN_LEN; 206227569Sphilip req.emr_out_buf = NULL; 207227569Sphilip req.emr_out_length = 0; 208227569Sphilip 209227569Sphilip MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_NEW_STATE, attach ? 1 : 0); 210227569Sphilip MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_UPDATE, 1); 211227569Sphilip 212227569Sphilip efx_mcdi_execute(enp, &req); 213227569Sphilip 214227569Sphilip if (req.emr_rc != 0) { 215227569Sphilip rc = req.emr_rc; 216227569Sphilip goto fail1; 217227569Sphilip } 218227569Sphilip 219227569Sphilip if (req.emr_out_length_used < MC_CMD_DRV_ATTACH_OUT_LEN) { 220227569Sphilip rc = EMSGSIZE; 221227569Sphilip goto fail2; 222227569Sphilip } 223227569Sphilip 224227569Sphilip return (0); 225227569Sphilip 226227569Sphilipfail2: 227227569Sphilip EFSYS_PROBE(fail2); 228227569Sphilipfail1: 229227569Sphilip EFSYS_PROBE1(fail1, int, rc); 230227569Sphilip 231227569Sphilip return (rc); 232227569Sphilip} 233227569Sphilip 234227569Sphilip#if EFSYS_OPT_PCIE_TUNE 235227569Sphilip 236227569Sphilip __checkReturn int 237227569Sphilipsiena_nic_pcie_extended_sync( 238227569Sphilip __in efx_nic_t *enp) 239227569Sphilip{ 240227569Sphilip uint8_t inbuf[MC_CMD_WORKAROUND_IN_LEN]; 241227569Sphilip efx_mcdi_req_t req; 242227569Sphilip int rc; 243227569Sphilip 244227569Sphilip EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 245227569Sphilip 246227569Sphilip req.emr_cmd = MC_CMD_WORKAROUND; 247227569Sphilip req.emr_in_buf = inbuf; 248227569Sphilip req.emr_in_length = sizeof (inbuf); 249227569Sphilip EFX_STATIC_ASSERT(MC_CMD_WORKAROUND_OUT_LEN == 0); 250227569Sphilip req.emr_out_buf = NULL; 251227569Sphilip req.emr_out_length = 0; 252227569Sphilip 253227569Sphilip MCDI_IN_SET_DWORD(req, WORKAROUND_IN_TYPE, MC_CMD_WORKAROUND_BUG17230); 254227569Sphilip MCDI_IN_SET_DWORD(req, WORKAROUND_IN_ENABLED, 1); 255227569Sphilip 256227569Sphilip efx_mcdi_execute(enp, &req); 257227569Sphilip 258227569Sphilip if (req.emr_rc != 0) { 259227569Sphilip rc = req.emr_rc; 260227569Sphilip goto fail1; 261227569Sphilip } 262227569Sphilip 263227569Sphilip return (0); 264227569Sphilip 265227569Sphilipfail1: 266227569Sphilip EFSYS_PROBE1(fail1, int, rc); 267227569Sphilip 268227569Sphilip return (rc); 269227569Sphilip} 270227569Sphilip 271227569Sphilip#endif /* EFSYS_OPT_PCIE_TUNE */ 272227569Sphilip 273227569Sphilipstatic __checkReturn int 274227569Sphilipsiena_board_cfg( 275227569Sphilip __in efx_nic_t *enp) 276227569Sphilip{ 277227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 278227569Sphilip efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip); 279278941Sarybchik uint8_t outbuf[MAX(MC_CMD_GET_BOARD_CFG_OUT_LENMIN, 280227569Sphilip MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN)]; 281227569Sphilip efx_mcdi_req_t req; 282279048Sarybchik uint8_t *mac_addr; 283279048Sarybchik efx_dword_t *capabilities; 284227569Sphilip int rc; 285227569Sphilip 286227569Sphilip /* Board configuration */ 287227569Sphilip req.emr_cmd = MC_CMD_GET_BOARD_CFG; 288227569Sphilip EFX_STATIC_ASSERT(MC_CMD_GET_BOARD_CFG_IN_LEN == 0); 289227569Sphilip req.emr_in_buf = NULL; 290227569Sphilip req.emr_in_length = 0; 291227569Sphilip req.emr_out_buf = outbuf; 292278941Sarybchik req.emr_out_length = MC_CMD_GET_BOARD_CFG_OUT_LENMIN; 293227569Sphilip 294227569Sphilip efx_mcdi_execute(enp, &req); 295227569Sphilip 296227569Sphilip if (req.emr_rc != 0) { 297227569Sphilip rc = req.emr_rc; 298227569Sphilip goto fail1; 299227569Sphilip } 300227569Sphilip 301278941Sarybchik if (req.emr_out_length_used < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) { 302227569Sphilip rc = EMSGSIZE; 303227569Sphilip goto fail2; 304227569Sphilip } 305227569Sphilip 306279048Sarybchik if (emip->emi_port == 1) { 307279048Sarybchik mac_addr = MCDI_OUT2(req, uint8_t, 308227569Sphilip GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0); 309279048Sarybchik capabilities = MCDI_OUT2(req, efx_dword_t, 310279048Sarybchik GET_BOARD_CFG_OUT_CAPABILITIES_PORT0); 311279048Sarybchik } else { 312279048Sarybchik mac_addr = MCDI_OUT2(req, uint8_t, 313227569Sphilip GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1); 314279048Sarybchik capabilities = MCDI_OUT2(req, efx_dword_t, 315279048Sarybchik GET_BOARD_CFG_OUT_CAPABILITIES_PORT1); 316279048Sarybchik } 317279048Sarybchik EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr); 318227569Sphilip 319227569Sphilip encp->enc_board_type = MCDI_OUT_DWORD(req, 320227569Sphilip GET_BOARD_CFG_OUT_BOARD_TYPE); 321227569Sphilip 322279048Sarybchik /* Additional capabilities */ 323279048Sarybchik encp->enc_clk_mult = 1; 324279048Sarybchik if (MCDI_CMD_DWORD_FIELD(capabilities, CAPABILITIES_TURBO)) { 325279048Sarybchik enp->en_features |= EFX_FEATURE_TURBO; 326279048Sarybchik 327279048Sarybchik if (MCDI_CMD_DWORD_FIELD(capabilities, 328279048Sarybchik CAPABILITIES_TURBO_ACTIVE)) 329279048Sarybchik encp->enc_clk_mult = 2; 330279048Sarybchik } 331279048Sarybchik 332279182Sarybchik encp->enc_evq_timer_quantum_ns = 333279182Sarybchik EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult; 334279182Sarybchik encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns << 335279182Sarybchik FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000; 336279048Sarybchik 337227569Sphilip /* Resource limits */ 338227569Sphilip req.emr_cmd = MC_CMD_GET_RESOURCE_LIMITS; 339227569Sphilip EFX_STATIC_ASSERT(MC_CMD_GET_RESOURCE_LIMITS_IN_LEN == 0); 340227569Sphilip req.emr_in_buf = NULL; 341227569Sphilip req.emr_in_length = 0; 342227569Sphilip req.emr_out_buf = outbuf; 343227569Sphilip req.emr_out_length = MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN; 344227569Sphilip 345227569Sphilip efx_mcdi_execute(enp, &req); 346227569Sphilip 347227569Sphilip if (req.emr_rc == 0) { 348278839Sarybchik if (req.emr_out_length_used < 349278839Sarybchik MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN) { 350227569Sphilip rc = EMSGSIZE; 351227569Sphilip goto fail3; 352227569Sphilip } 353227569Sphilip 354227569Sphilip encp->enc_evq_limit = MCDI_OUT_DWORD(req, 355227569Sphilip GET_RESOURCE_LIMITS_OUT_EVQ); 356227569Sphilip encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, 357227569Sphilip MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_TXQ)); 358227569Sphilip encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, 359227569Sphilip MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_RXQ)); 360227569Sphilip } else if (req.emr_rc == ENOTSUP) { 361227569Sphilip encp->enc_evq_limit = 1024; 362227569Sphilip encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET; 363227569Sphilip encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET; 364227569Sphilip } else { 365227569Sphilip rc = req.emr_rc; 366227569Sphilip goto fail4; 367227569Sphilip } 368227569Sphilip 369227569Sphilip encp->enc_buftbl_limit = SIENA_SRAM_ROWS - 370279098Sarybchik (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) - 371279098Sarybchik (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE)); 372227569Sphilip 373227569Sphilip return (0); 374227569Sphilip 375227569Sphilipfail4: 376227569Sphilip EFSYS_PROBE(fail4); 377227569Sphilipfail3: 378227569Sphilip EFSYS_PROBE(fail3); 379227569Sphilipfail2: 380227569Sphilip EFSYS_PROBE(fail2); 381227569Sphilipfail1: 382227569Sphilip EFSYS_PROBE1(fail1, int, rc); 383227569Sphilip 384227569Sphilip return (rc); 385227569Sphilip} 386227569Sphilip 387227569Sphilipstatic __checkReturn int 388227569Sphilipsiena_phy_cfg( 389227569Sphilip __in efx_nic_t *enp) 390227569Sphilip{ 391227569Sphilip efx_port_t *epp = &(enp->en_port); 392227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 393227569Sphilip efx_mcdi_req_t req; 394227569Sphilip uint8_t outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN]; 395227569Sphilip int rc; 396227569Sphilip 397227569Sphilip req.emr_cmd = MC_CMD_GET_PHY_CFG; 398227569Sphilip EFX_STATIC_ASSERT(MC_CMD_GET_PHY_CFG_IN_LEN == 0); 399227569Sphilip req.emr_in_buf = NULL; 400227569Sphilip req.emr_in_length = 0; 401227569Sphilip req.emr_out_buf = outbuf; 402227569Sphilip req.emr_out_length = sizeof (outbuf); 403227569Sphilip 404227569Sphilip efx_mcdi_execute(enp, &req); 405227569Sphilip 406227569Sphilip if (req.emr_rc != 0) { 407227569Sphilip rc = req.emr_rc; 408227569Sphilip goto fail1; 409227569Sphilip } 410227569Sphilip 411227569Sphilip if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN) { 412227569Sphilip rc = EMSGSIZE; 413227569Sphilip goto fail2; 414227569Sphilip } 415227569Sphilip 416227569Sphilip encp->enc_phy_type = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_TYPE); 417227569Sphilip#if EFSYS_OPT_NAMES 418227569Sphilip (void) strncpy(encp->enc_phy_name, 419227569Sphilip MCDI_OUT2(req, char, GET_PHY_CFG_OUT_NAME), 420227569Sphilip MIN(sizeof (encp->enc_phy_name) - 1, 421227569Sphilip MC_CMD_GET_PHY_CFG_OUT_NAME_LEN)); 422227569Sphilip#endif /* EFSYS_OPT_NAMES */ 423227569Sphilip (void) memset(encp->enc_phy_revision, 0, 424227569Sphilip sizeof (encp->enc_phy_revision)); 425227569Sphilip memcpy(encp->enc_phy_revision, 426227569Sphilip MCDI_OUT2(req, char, GET_PHY_CFG_OUT_REVISION), 427227569Sphilip MIN(sizeof (encp->enc_phy_revision) - 1, 428227569Sphilip MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN)); 429227569Sphilip#if EFSYS_OPT_PHY_LED_CONTROL 430227569Sphilip encp->enc_led_mask = ((1 << EFX_PHY_LED_DEFAULT) | 431227569Sphilip (1 << EFX_PHY_LED_OFF) | 432227569Sphilip (1 << EFX_PHY_LED_ON)); 433227569Sphilip#endif /* EFSYS_OPT_PHY_LED_CONTROL */ 434227569Sphilip 435227569Sphilip#if EFSYS_OPT_PHY_PROPS 436227569Sphilip encp->enc_phy_nprops = 0; 437227569Sphilip#endif /* EFSYS_OPT_PHY_PROPS */ 438227569Sphilip 439227569Sphilip /* Get the media type of the fixed port, if recognised. */ 440227569Sphilip EFX_STATIC_ASSERT(MC_CMD_MEDIA_XAUI == EFX_PHY_MEDIA_XAUI); 441227569Sphilip EFX_STATIC_ASSERT(MC_CMD_MEDIA_CX4 == EFX_PHY_MEDIA_CX4); 442227569Sphilip EFX_STATIC_ASSERT(MC_CMD_MEDIA_KX4 == EFX_PHY_MEDIA_KX4); 443227569Sphilip EFX_STATIC_ASSERT(MC_CMD_MEDIA_XFP == EFX_PHY_MEDIA_XFP); 444227569Sphilip EFX_STATIC_ASSERT(MC_CMD_MEDIA_SFP_PLUS == EFX_PHY_MEDIA_SFP_PLUS); 445227569Sphilip EFX_STATIC_ASSERT(MC_CMD_MEDIA_BASE_T == EFX_PHY_MEDIA_BASE_T); 446227569Sphilip epp->ep_fixed_port_type = 447227569Sphilip MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_MEDIA_TYPE); 448227569Sphilip if (epp->ep_fixed_port_type >= EFX_PHY_MEDIA_NTYPES) 449227569Sphilip epp->ep_fixed_port_type = EFX_PHY_MEDIA_INVALID; 450227569Sphilip 451227569Sphilip epp->ep_phy_cap_mask = 452227569Sphilip MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_SUPPORTED_CAP); 453227569Sphilip#if EFSYS_OPT_PHY_FLAGS 454227569Sphilip encp->enc_phy_flags_mask = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_FLAGS); 455227569Sphilip#endif /* EFSYS_OPT_PHY_FLAGS */ 456227569Sphilip 457227569Sphilip encp->enc_port = (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_PRT); 458227569Sphilip 459227569Sphilip /* Populate internal state */ 460227569Sphilip encp->enc_siena_channel = 461227569Sphilip (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_CHANNEL); 462227569Sphilip 463227569Sphilip#if EFSYS_OPT_PHY_STATS 464227569Sphilip encp->enc_siena_phy_stat_mask = 465227569Sphilip MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_STATS_MASK); 466227569Sphilip 467227569Sphilip /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */ 468227569Sphilip siena_phy_decode_stats(enp, encp->enc_siena_phy_stat_mask, 469227569Sphilip NULL, &encp->enc_phy_stat_mask, NULL); 470227569Sphilip#endif /* EFSYS_OPT_PHY_STATS */ 471227569Sphilip 472227569Sphilip#if EFSYS_OPT_PHY_BIST 473227569Sphilip encp->enc_bist_mask = 0; 474227569Sphilip if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 475227569Sphilip GET_PHY_CFG_OUT_BIST_CABLE_SHORT)) 476227569Sphilip encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_SHORT); 477227569Sphilip if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 478227569Sphilip GET_PHY_CFG_OUT_BIST_CABLE_LONG)) 479227569Sphilip encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_LONG); 480227569Sphilip if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS, 481227569Sphilip GET_PHY_CFG_OUT_BIST)) 482227569Sphilip encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_NORMAL); 483279141Sarybchik#endif /* EFSYS_OPT_PHY_BIST */ 484227569Sphilip 485227569Sphilip return (0); 486227569Sphilip 487227569Sphilipfail2: 488227569Sphilip EFSYS_PROBE(fail2); 489227569Sphilipfail1: 490227569Sphilip EFSYS_PROBE1(fail1, int, rc); 491227569Sphilip 492227569Sphilip return (rc); 493227569Sphilip} 494227569Sphilip 495227569Sphilip#if EFSYS_OPT_LOOPBACK 496227569Sphilip 497227569Sphilipstatic __checkReturn int 498227569Sphilipsiena_loopback_cfg( 499227569Sphilip __in efx_nic_t *enp) 500227569Sphilip{ 501227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 502227569Sphilip efx_mcdi_req_t req; 503227569Sphilip uint8_t outbuf[MC_CMD_GET_LOOPBACK_MODES_OUT_LEN]; 504227569Sphilip int rc; 505227569Sphilip 506227569Sphilip req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES; 507227569Sphilip EFX_STATIC_ASSERT(MC_CMD_GET_LOOPBACK_MODES_IN_LEN == 0); 508227569Sphilip req.emr_in_buf = NULL; 509227569Sphilip req.emr_in_length = 0; 510227569Sphilip req.emr_out_buf = outbuf; 511227569Sphilip req.emr_out_length = sizeof (outbuf); 512227569Sphilip 513227569Sphilip efx_mcdi_execute(enp, &req); 514227569Sphilip 515227569Sphilip if (req.emr_rc != 0) { 516227569Sphilip rc = req.emr_rc; 517227569Sphilip goto fail1; 518227569Sphilip } 519227569Sphilip 520227569Sphilip if (req.emr_out_length_used < MC_CMD_GET_LOOPBACK_MODES_OUT_LEN) { 521227569Sphilip rc = EMSGSIZE; 522227569Sphilip goto fail2; 523227569Sphilip } 524227569Sphilip 525227569Sphilip /* 526227569Sphilip * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree 527227569Sphilip * in siena_phy.c:siena_phy_get_link() 528227569Sphilip */ 529227569Sphilip encp->enc_loopback_types[EFX_LINK_100FDX] = EFX_LOOPBACK_MASK & 530227569Sphilip MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_100M) & 531227569Sphilip MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED); 532227569Sphilip encp->enc_loopback_types[EFX_LINK_1000FDX] = EFX_LOOPBACK_MASK & 533227569Sphilip MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_1G) & 534227569Sphilip MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED); 535227569Sphilip encp->enc_loopback_types[EFX_LINK_10000FDX] = EFX_LOOPBACK_MASK & 536227569Sphilip MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_10G) & 537227569Sphilip MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED); 538227569Sphilip encp->enc_loopback_types[EFX_LINK_UNKNOWN] = 539227569Sphilip (1 << EFX_LOOPBACK_OFF) | 540227569Sphilip encp->enc_loopback_types[EFX_LINK_100FDX] | 541227569Sphilip encp->enc_loopback_types[EFX_LINK_1000FDX] | 542227569Sphilip encp->enc_loopback_types[EFX_LINK_10000FDX]; 543227569Sphilip 544227569Sphilip return (0); 545227569Sphilip 546227569Sphilipfail2: 547227569Sphilip EFSYS_PROBE(fail2); 548227569Sphilipfail1: 549227569Sphilip EFSYS_PROBE1(fail1, int, rc); 550227569Sphilip 551227569Sphilip return (rc); 552227569Sphilip} 553227569Sphilip 554227569Sphilip#endif /* EFSYS_OPT_LOOPBACK */ 555227569Sphilip 556227569Sphilip#if EFSYS_OPT_MON_STATS 557227569Sphilip 558227569Sphilipstatic __checkReturn int 559227569Sphilipsiena_monitor_cfg( 560227569Sphilip __in efx_nic_t *enp) 561227569Sphilip{ 562227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 563227569Sphilip efx_mcdi_req_t req; 564227569Sphilip uint8_t outbuf[MCDI_CTL_SDU_LEN_MAX]; 565227569Sphilip int rc; 566227569Sphilip 567227569Sphilip req.emr_cmd = MC_CMD_SENSOR_INFO; 568227569Sphilip EFX_STATIC_ASSERT(MC_CMD_SENSOR_INFO_IN_LEN == 0); 569227569Sphilip req.emr_in_buf = NULL; 570227569Sphilip req.emr_in_length = 0; 571227569Sphilip req.emr_out_buf = outbuf; 572227569Sphilip req.emr_out_length = sizeof (outbuf); 573227569Sphilip 574227569Sphilip efx_mcdi_execute(enp, &req); 575227569Sphilip 576227569Sphilip if (req.emr_rc != 0) { 577227569Sphilip rc = req.emr_rc; 578227569Sphilip goto fail1; 579227569Sphilip } 580227569Sphilip 581227569Sphilip if (req.emr_out_length_used < MC_CMD_SENSOR_INFO_OUT_MASK_OFST + 4) { 582227569Sphilip rc = EMSGSIZE; 583227569Sphilip goto fail2; 584227569Sphilip } 585227569Sphilip 586227569Sphilip encp->enc_siena_mon_stat_mask = 587227569Sphilip MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK); 588227569Sphilip encp->enc_mon_type = EFX_MON_SFC90X0; 589227569Sphilip 590227569Sphilip siena_mon_decode_stats(enp, encp->enc_siena_mon_stat_mask, 591227569Sphilip NULL, &(encp->enc_mon_stat_mask), NULL); 592227569Sphilip 593227569Sphilip return (0); 594227569Sphilip 595227569Sphilipfail2: 596227569Sphilip EFSYS_PROBE(fail2); 597227569Sphilipfail1: 598227569Sphilip EFSYS_PROBE1(fail1, int, rc); 599227569Sphilip 600227569Sphilip return (rc); 601227569Sphilip} 602227569Sphilip 603227569Sphilip#endif /* EFSYS_OPT_MON_STATS */ 604227569Sphilip 605227569Sphilip __checkReturn int 606227569Sphilipsiena_nic_probe( 607227569Sphilip __in efx_nic_t *enp) 608227569Sphilip{ 609227569Sphilip efx_port_t *epp = &(enp->en_port); 610227569Sphilip efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 611227569Sphilip siena_link_state_t sls; 612227569Sphilip unsigned int mask; 613227569Sphilip int rc; 614227569Sphilip 615227569Sphilip EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 616227569Sphilip 617227569Sphilip /* Read clear any assertion state */ 618227569Sphilip if ((rc = siena_nic_read_assertion(enp)) != 0) 619227569Sphilip goto fail1; 620227569Sphilip 621227569Sphilip /* Exit the assertion handler */ 622227569Sphilip if ((rc = siena_nic_exit_assertion_handler(enp)) != 0) 623227569Sphilip goto fail2; 624227569Sphilip 625227569Sphilip /* Wrestle control from the BMC */ 626227569Sphilip if ((rc = siena_nic_attach(enp, B_TRUE)) != 0) 627227569Sphilip goto fail3; 628227569Sphilip 629227569Sphilip if ((rc = siena_board_cfg(enp)) != 0) 630227569Sphilip goto fail4; 631227569Sphilip 632227569Sphilip if ((rc = siena_phy_cfg(enp)) != 0) 633227569Sphilip goto fail5; 634227569Sphilip 635227569Sphilip /* Obtain the default PHY advertised capabilities */ 636227569Sphilip if ((rc = siena_nic_reset(enp)) != 0) 637227569Sphilip goto fail6; 638227569Sphilip if ((rc = siena_phy_get_link(enp, &sls)) != 0) 639227569Sphilip goto fail7; 640227569Sphilip epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask; 641227569Sphilip epp->ep_adv_cap_mask = sls.sls_adv_cap_mask; 642227569Sphilip 643227569Sphilip#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM 644227569Sphilip if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0) 645227569Sphilip goto fail8; 646227569Sphilip enp->en_u.siena.enu_partn_mask = mask; 647227569Sphilip#endif 648227569Sphilip 649227569Sphilip#if EFSYS_OPT_MAC_STATS 650227569Sphilip /* Wipe the MAC statistics */ 651227569Sphilip if ((rc = siena_mac_stats_clear(enp)) != 0) 652227569Sphilip goto fail9; 653227569Sphilip#endif 654227569Sphilip 655227569Sphilip#if EFSYS_OPT_LOOPBACK 656227569Sphilip if ((rc = siena_loopback_cfg(enp)) != 0) 657227569Sphilip goto fail10; 658227569Sphilip#endif 659227569Sphilip 660227569Sphilip#if EFSYS_OPT_MON_STATS 661227569Sphilip if ((rc = siena_monitor_cfg(enp)) != 0) 662227569Sphilip goto fail11; 663227569Sphilip#endif 664227569Sphilip 665227569Sphilip encp->enc_features = enp->en_features; 666227569Sphilip 667227569Sphilip return (0); 668227569Sphilip 669227569Sphilip#if EFSYS_OPT_MON_STATS 670227569Sphilipfail11: 671227569Sphilip EFSYS_PROBE(fail11); 672227569Sphilip#endif 673227569Sphilip#if EFSYS_OPT_LOOPBACK 674227569Sphilipfail10: 675227569Sphilip EFSYS_PROBE(fail10); 676227569Sphilip#endif 677227569Sphilip#if EFSYS_OPT_MAC_STATS 678227569Sphilipfail9: 679227569Sphilip EFSYS_PROBE(fail9); 680227569Sphilip#endif 681227569Sphilip#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM 682227569Sphilipfail8: 683227569Sphilip EFSYS_PROBE(fail8); 684227569Sphilip#endif 685227569Sphilipfail7: 686227569Sphilip EFSYS_PROBE(fail7); 687227569Sphilipfail6: 688227569Sphilip EFSYS_PROBE(fail6); 689227569Sphilipfail5: 690227569Sphilip EFSYS_PROBE(fail5); 691227569Sphilipfail4: 692227569Sphilip EFSYS_PROBE(fail4); 693227569Sphilipfail3: 694227569Sphilip EFSYS_PROBE(fail3); 695227569Sphilipfail2: 696227569Sphilip EFSYS_PROBE(fail2); 697227569Sphilipfail1: 698227569Sphilip EFSYS_PROBE1(fail1, int, rc); 699227569Sphilip 700227569Sphilip return (rc); 701227569Sphilip} 702227569Sphilip 703227569Sphilip __checkReturn int 704227569Sphilipsiena_nic_reset( 705227569Sphilip __in efx_nic_t *enp) 706227569Sphilip{ 707227569Sphilip efx_mcdi_req_t req; 708227569Sphilip int rc; 709227569Sphilip 710227569Sphilip EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 711227569Sphilip 712227569Sphilip /* siena_nic_reset() is called to recover from BADASSERT failures. */ 713227569Sphilip if ((rc = siena_nic_read_assertion(enp)) != 0) 714227569Sphilip goto fail1; 715227569Sphilip if ((rc = siena_nic_exit_assertion_handler(enp)) != 0) 716227569Sphilip goto fail2; 717227569Sphilip 718227569Sphilip req.emr_cmd = MC_CMD_PORT_RESET; 719227569Sphilip EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_IN_LEN == 0); 720227569Sphilip req.emr_in_buf = NULL; 721227569Sphilip req.emr_in_length = 0; 722227569Sphilip EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_OUT_LEN == 0); 723227569Sphilip req.emr_out_buf = NULL; 724227569Sphilip req.emr_out_length = 0; 725227569Sphilip 726227569Sphilip efx_mcdi_execute(enp, &req); 727227569Sphilip 728227569Sphilip if (req.emr_rc != 0) { 729227569Sphilip rc = req.emr_rc; 730227569Sphilip goto fail3; 731227569Sphilip } 732227569Sphilip 733227569Sphilip return (0); 734227569Sphilip 735227569Sphilipfail3: 736227569Sphilip EFSYS_PROBE(fail3); 737227569Sphilipfail2: 738227569Sphilip EFSYS_PROBE(fail2); 739227569Sphilipfail1: 740227569Sphilip EFSYS_PROBE1(fail1, int, rc); 741227569Sphilip 742227569Sphilip return (0); 743227569Sphilip} 744227569Sphilip 745227569Sphilipstatic __checkReturn int 746227569Sphilipsiena_nic_logging( 747227569Sphilip __in efx_nic_t *enp) 748227569Sphilip{ 749227569Sphilip efx_mcdi_req_t req; 750227569Sphilip uint8_t payload[MC_CMD_LOG_CTRL_IN_LEN]; 751227569Sphilip int rc; 752227569Sphilip 753227569Sphilip req.emr_cmd = MC_CMD_LOG_CTRL; 754227569Sphilip req.emr_in_buf = payload; 755227569Sphilip req.emr_in_length = MC_CMD_LOG_CTRL_IN_LEN; 756227569Sphilip EFX_STATIC_ASSERT(MC_CMD_LOG_CTRL_OUT_LEN == 0); 757227569Sphilip req.emr_out_buf = NULL; 758227569Sphilip req.emr_out_length = 0; 759227569Sphilip 760227569Sphilip MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST, 761227569Sphilip MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ); 762227569Sphilip MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST_EVQ, 0); 763227569Sphilip 764227569Sphilip efx_mcdi_execute(enp, &req); 765227569Sphilip 766227569Sphilip if (req.emr_rc != 0) { 767227569Sphilip rc = req.emr_rc; 768227569Sphilip goto fail1; 769227569Sphilip } 770227569Sphilip 771227569Sphilip return (0); 772227569Sphilip 773227569Sphilipfail1: 774227569Sphilip EFSYS_PROBE1(fail1, int, rc); 775227569Sphilip 776227569Sphilip return (rc); 777227569Sphilip} 778227569Sphilip 779227569Sphilipstatic void 780227569Sphilipsiena_nic_rx_cfg( 781227569Sphilip __in efx_nic_t *enp) 782227569Sphilip{ 783227569Sphilip efx_oword_t oword; 784227569Sphilip 785227569Sphilip /* 786227569Sphilip * RX_INGR_EN is always enabled on Siena, because we rely on 787227569Sphilip * the RX parser to be resiliant to missing SOP/EOP. 788227569Sphilip */ 789227569Sphilip EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword); 790227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1); 791227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword); 792227569Sphilip 793227569Sphilip /* Disable parsing of additional 802.1Q in Q packets */ 794227569Sphilip EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); 795227569Sphilip EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0); 796227569Sphilip EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword); 797227569Sphilip} 798227569Sphilip 799227569Sphilipstatic void 800227569Sphilipsiena_nic_usrev_dis( 801227569Sphilip __in efx_nic_t *enp) 802227569Sphilip{ 803227569Sphilip efx_oword_t oword; 804227569Sphilip 805227569Sphilip EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1); 806227569Sphilip EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword); 807227569Sphilip} 808227569Sphilip 809227569Sphilip __checkReturn int 810227569Sphilipsiena_nic_init( 811227569Sphilip __in efx_nic_t *enp) 812227569Sphilip{ 813227569Sphilip int rc; 814227569Sphilip 815227569Sphilip EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 816227569Sphilip 817227569Sphilip if ((rc = siena_nic_logging(enp)) != 0) 818227569Sphilip goto fail1; 819227569Sphilip 820227569Sphilip siena_sram_init(enp); 821227569Sphilip 822227569Sphilip /* Configure Siena's RX block */ 823227569Sphilip siena_nic_rx_cfg(enp); 824227569Sphilip 825227569Sphilip /* Disable USR_EVents for now */ 826227569Sphilip siena_nic_usrev_dis(enp); 827227569Sphilip 828227569Sphilip /* bug17057: Ensure set_link is called */ 829227569Sphilip if ((rc = siena_phy_reconfigure(enp)) != 0) 830227569Sphilip goto fail2; 831227569Sphilip 832227569Sphilip return (0); 833227569Sphilip 834227569Sphilipfail2: 835227569Sphilip EFSYS_PROBE(fail2); 836227569Sphilipfail1: 837227569Sphilip EFSYS_PROBE1(fail1, int, rc); 838227569Sphilip 839227569Sphilip return (rc); 840227569Sphilip} 841227569Sphilip 842227569Sphilip void 843227569Sphilipsiena_nic_fini( 844227569Sphilip __in efx_nic_t *enp) 845227569Sphilip{ 846227569Sphilip _NOTE(ARGUNUSED(enp)) 847227569Sphilip} 848227569Sphilip 849227569Sphilip void 850227569Sphilipsiena_nic_unprobe( 851227569Sphilip __in efx_nic_t *enp) 852227569Sphilip{ 853227569Sphilip (void) siena_nic_attach(enp, B_FALSE); 854227569Sphilip} 855227569Sphilip 856227569Sphilip#if EFSYS_OPT_DIAG 857227569Sphilip 858227569Sphilipstatic efx_register_set_t __cs __siena_registers[] = { 859227569Sphilip { FR_AZ_ADR_REGION_REG_OFST, 0, 1 }, 860227569Sphilip { FR_CZ_USR_EV_CFG_OFST, 0, 1 }, 861227569Sphilip { FR_AZ_RX_CFG_REG_OFST, 0, 1 }, 862227569Sphilip { FR_AZ_TX_CFG_REG_OFST, 0, 1 }, 863227569Sphilip { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 }, 864227569Sphilip { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 }, 865227569Sphilip { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 }, 866227569Sphilip { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 }, 867227569Sphilip { FR_AZ_DP_CTRL_REG_OFST, 0, 1 }, 868227569Sphilip { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1}, 869227569Sphilip { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1}, 870227569Sphilip { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1}, 871227569Sphilip { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1} 872227569Sphilip}; 873227569Sphilip 874227569Sphilipstatic const uint32_t __cs __siena_register_masks[] = { 875227569Sphilip 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 876227569Sphilip 0x000103FF, 0x00000000, 0x00000000, 0x00000000, 877227569Sphilip 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000, 878227569Sphilip 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF, 879227569Sphilip 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF, 880227569Sphilip 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000, 881227569Sphilip 0x00000003, 0x00000000, 0x00000000, 0x00000000, 882227569Sphilip 0x000003FF, 0x00000000, 0x00000000, 0x00000000, 883227569Sphilip 0x00000FFF, 0x00000000, 0x00000000, 0x00000000, 884227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 885227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 886227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 887227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000 888227569Sphilip}; 889227569Sphilip 890227569Sphilipstatic efx_register_set_t __cs __siena_tables[] = { 891227569Sphilip { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP, 892227569Sphilip FR_AZ_RX_FILTER_TBL0_ROWS }, 893227569Sphilip { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP, 894227569Sphilip FR_CZ_RX_MAC_FILTER_TBL0_ROWS }, 895227569Sphilip { FR_AZ_RX_DESC_PTR_TBL_OFST, 896227569Sphilip FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS }, 897227569Sphilip { FR_AZ_TX_DESC_PTR_TBL_OFST, 898227569Sphilip FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS }, 899227569Sphilip { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS }, 900227569Sphilip { FR_CZ_TX_FILTER_TBL0_OFST, 901227569Sphilip FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS }, 902227569Sphilip { FR_CZ_TX_MAC_FILTER_TBL0_OFST, 903227569Sphilip FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS } 904227569Sphilip}; 905227569Sphilip 906227569Sphilipstatic const uint32_t __cs __siena_table_masks[] = { 907227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF, 908227569Sphilip 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000, 909279095Sarybchik 0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000, 910227569Sphilip 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000, 911227569Sphilip 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000, 912227569Sphilip 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF, 913227569Sphilip 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000, 914227569Sphilip}; 915227569Sphilip 916227569Sphilip __checkReturn int 917227569Sphilipsiena_nic_register_test( 918227569Sphilip __in efx_nic_t *enp) 919227569Sphilip{ 920227569Sphilip efx_register_set_t *rsp; 921227569Sphilip const uint32_t *dwordp; 922227569Sphilip unsigned int nitems; 923227569Sphilip unsigned int count; 924227569Sphilip int rc; 925227569Sphilip 926227569Sphilip /* Fill out the register mask entries */ 927227569Sphilip EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks) 928227569Sphilip == EFX_ARRAY_SIZE(__siena_registers) * 4); 929227569Sphilip 930227569Sphilip nitems = EFX_ARRAY_SIZE(__siena_registers); 931227569Sphilip dwordp = __siena_register_masks; 932227569Sphilip for (count = 0; count < nitems; ++count) { 933227569Sphilip rsp = __siena_registers + count; 934227569Sphilip rsp->mask.eo_u32[0] = *dwordp++; 935227569Sphilip rsp->mask.eo_u32[1] = *dwordp++; 936227569Sphilip rsp->mask.eo_u32[2] = *dwordp++; 937227569Sphilip rsp->mask.eo_u32[3] = *dwordp++; 938227569Sphilip } 939227569Sphilip 940227569Sphilip /* Fill out the register table entries */ 941227569Sphilip EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks) 942227569Sphilip == EFX_ARRAY_SIZE(__siena_tables) * 4); 943227569Sphilip 944227569Sphilip nitems = EFX_ARRAY_SIZE(__siena_tables); 945227569Sphilip dwordp = __siena_table_masks; 946227569Sphilip for (count = 0; count < nitems; ++count) { 947227569Sphilip rsp = __siena_tables + count; 948227569Sphilip rsp->mask.eo_u32[0] = *dwordp++; 949227569Sphilip rsp->mask.eo_u32[1] = *dwordp++; 950227569Sphilip rsp->mask.eo_u32[2] = *dwordp++; 951227569Sphilip rsp->mask.eo_u32[3] = *dwordp++; 952227569Sphilip } 953227569Sphilip 954227569Sphilip if ((rc = efx_nic_test_registers(enp, __siena_registers, 955227569Sphilip EFX_ARRAY_SIZE(__siena_registers))) != 0) 956227569Sphilip goto fail1; 957227569Sphilip 958227569Sphilip if ((rc = efx_nic_test_tables(enp, __siena_tables, 959227569Sphilip EFX_PATTERN_BYTE_ALTERNATE, 960227569Sphilip EFX_ARRAY_SIZE(__siena_tables))) != 0) 961227569Sphilip goto fail2; 962227569Sphilip 963227569Sphilip if ((rc = efx_nic_test_tables(enp, __siena_tables, 964227569Sphilip EFX_PATTERN_BYTE_CHANGING, 965227569Sphilip EFX_ARRAY_SIZE(__siena_tables))) != 0) 966227569Sphilip goto fail3; 967227569Sphilip 968227569Sphilip if ((rc = efx_nic_test_tables(enp, __siena_tables, 969227569Sphilip EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0) 970227569Sphilip goto fail4; 971227569Sphilip 972227569Sphilip return (0); 973227569Sphilip 974227569Sphilipfail4: 975227569Sphilip EFSYS_PROBE(fail4); 976227569Sphilipfail3: 977227569Sphilip EFSYS_PROBE(fail3); 978227569Sphilipfail2: 979227569Sphilip EFSYS_PROBE(fail2); 980227569Sphilipfail1: 981227569Sphilip EFSYS_PROBE1(fail1, int, rc); 982227569Sphilip 983227569Sphilip return (rc); 984227569Sphilip} 985227569Sphilip 986227569Sphilip#endif /* EFSYS_OPT_DIAG */ 987227569Sphilip 988227569Sphilip#endif /* EFSYS_OPT_SIENA */ 989