2 * Copyright (c) 2009-2015 Solarflare Communications Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
40 static __checkReturn efx_rc_t
41 siena_nic_get_partn_mask(
43 __out unsigned int *maskp)
46 uint8_t payload[MAX(MC_CMD_NVRAM_TYPES_IN_LEN,
47 MC_CMD_NVRAM_TYPES_OUT_LEN)];
50 (void) memset(payload, 0, sizeof (payload));
51 req.emr_cmd = MC_CMD_NVRAM_TYPES;
52 req.emr_in_buf = payload;
53 req.emr_in_length = MC_CMD_NVRAM_TYPES_IN_LEN;
54 req.emr_out_buf = payload;
55 req.emr_out_length = MC_CMD_NVRAM_TYPES_OUT_LEN;
57 efx_mcdi_execute(enp, &req);
59 if (req.emr_rc != 0) {
64 if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
69 *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
76 EFSYS_PROBE1(fail1, efx_rc_t, rc);
81 #if EFSYS_OPT_PCIE_TUNE
83 __checkReturn efx_rc_t
84 siena_nic_pcie_extended_sync(
89 if ((rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG17230,
96 EFSYS_PROBE1(fail1, efx_rc_t, rc);
101 #endif /* EFSYS_OPT_PCIE_TUNE */
103 static __checkReturn efx_rc_t
107 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
109 efx_dword_t capabilities;
111 uint32_t nevq, nrxq, ntxq;
114 /* External port identifier using one-based port numbering */
115 encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port;
117 /* Board configuration */
118 if ((rc = efx_mcdi_get_board_cfg(enp, &board_type,
119 &capabilities, mac_addr)) != 0)
122 EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
124 encp->enc_board_type = board_type;
126 /* Additional capabilities */
127 encp->enc_clk_mult = 1;
128 if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) {
129 enp->en_features |= EFX_FEATURE_TURBO;
131 if (EFX_DWORD_FIELD(capabilities,
132 MC_CMD_CAPABILITIES_TURBO_ACTIVE)) {
133 encp->enc_clk_mult = 2;
137 encp->enc_evq_timer_quantum_ns =
138 EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
139 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
140 FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
142 /* When hash header insertion is enabled, Siena inserts 16 bytes */
143 encp->enc_rx_prefix_size = 16;
145 /* Alignment for receive packet DMA buffers */
146 encp->enc_rx_buf_align_start = 1;
147 encp->enc_rx_buf_align_end = 1;
149 /* Alignment for WPTR updates */
150 encp->enc_rx_push_align = 1;
152 /* Resource limits */
153 rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq);
159 nrxq = EFX_RXQ_LIMIT_TARGET;
160 ntxq = EFX_TXQ_LIMIT_TARGET;
162 encp->enc_evq_limit = nevq;
163 encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq);
164 encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq);
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));
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_allow_set_mac_with_installed_filters = B_TRUE;
180 EFSYS_PROBE1(fail1, efx_rc_t, rc);
185 static __checkReturn efx_rc_t
189 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
192 /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
193 if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
196 #if EFSYS_OPT_PHY_STATS
197 /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
198 siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask,
199 NULL, &encp->enc_phy_stat_mask, NULL);
200 #endif /* EFSYS_OPT_PHY_STATS */
205 EFSYS_PROBE1(fail1, efx_rc_t, rc);
210 __checkReturn efx_rc_t
214 efx_port_t *epp = &(enp->en_port);
215 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
216 siena_link_state_t sls;
221 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
224 if ((rc = efx_nic_biu_test(enp)) != 0)
227 /* Clear the region register */
228 EFX_POPULATE_OWORD_4(oword,
229 FRF_AZ_ADR_REGION0, 0,
230 FRF_AZ_ADR_REGION1, (1 << 16),
231 FRF_AZ_ADR_REGION2, (2 << 16),
232 FRF_AZ_ADR_REGION3, (3 << 16));
233 EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
235 /* Read clear any assertion state */
236 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
239 /* Exit the assertion handler */
240 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
243 /* Wrestle control from the BMC */
244 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
247 if ((rc = siena_board_cfg(enp)) != 0)
250 if ((rc = siena_phy_cfg(enp)) != 0)
253 /* Obtain the default PHY advertised capabilities */
254 if ((rc = siena_nic_reset(enp)) != 0)
256 if ((rc = siena_phy_get_link(enp, &sls)) != 0)
258 epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
259 epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
261 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
262 if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
264 enp->en_u.siena.enu_partn_mask = mask;
267 #if EFSYS_OPT_MAC_STATS
268 /* Wipe the MAC statistics */
269 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
273 #if EFSYS_OPT_LOOPBACK
274 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
278 #if EFSYS_OPT_MON_STATS
279 if ((rc = mcdi_mon_cfg_build(enp)) != 0)
283 encp->enc_features = enp->en_features;
287 #if EFSYS_OPT_MON_STATS
291 #if EFSYS_OPT_LOOPBACK
295 #if EFSYS_OPT_MAC_STATS
299 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
318 EFSYS_PROBE1(fail1, efx_rc_t, rc);
323 __checkReturn efx_rc_t
330 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
332 /* siena_nic_reset() is called to recover from BADASSERT failures. */
333 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
335 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
339 * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied
340 * for backwards compatibility with PORT_RESET_IN_LEN.
342 EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0);
344 req.emr_cmd = MC_CMD_ENTITY_RESET;
345 req.emr_in_buf = NULL;
346 req.emr_in_length = 0;
347 req.emr_out_buf = NULL;
348 req.emr_out_length = 0;
350 efx_mcdi_execute(enp, &req);
352 if (req.emr_rc != 0) {
364 EFSYS_PROBE1(fail1, efx_rc_t, rc);
376 * RX_INGR_EN is always enabled on Siena, because we rely on
377 * the RX parser to be resiliant to missing SOP/EOP.
379 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
380 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
381 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
383 /* Disable parsing of additional 802.1Q in Q packets */
384 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
385 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
386 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
395 EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
396 EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
399 __checkReturn efx_rc_t
405 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
407 /* Enable reporting of some events (e.g. link change) */
408 if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
411 siena_sram_init(enp);
413 /* Configure Siena's RX block */
414 siena_nic_rx_cfg(enp);
416 /* Disable USR_EVents for now */
417 siena_nic_usrev_dis(enp);
419 /* bug17057: Ensure set_link is called */
420 if ((rc = siena_phy_reconfigure(enp)) != 0)
423 enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V1;
430 EFSYS_PROBE1(fail1, efx_rc_t, rc);
439 _NOTE(ARGUNUSED(enp))
446 #if EFSYS_OPT_MON_STATS
447 mcdi_mon_cfg_free(enp);
448 #endif /* EFSYS_OPT_MON_STATS */
449 (void) efx_mcdi_drv_attach(enp, B_FALSE);
454 static efx_register_set_t __siena_registers[] = {
455 { FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
456 { FR_CZ_USR_EV_CFG_OFST, 0, 1 },
457 { FR_AZ_RX_CFG_REG_OFST, 0, 1 },
458 { FR_AZ_TX_CFG_REG_OFST, 0, 1 },
459 { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
460 { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
461 { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
462 { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
463 { FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
464 { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
465 { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
466 { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
467 { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
470 static const uint32_t __siena_register_masks[] = {
471 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
472 0x000103FF, 0x00000000, 0x00000000, 0x00000000,
473 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
474 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
475 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
476 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
477 0x00000003, 0x00000000, 0x00000000, 0x00000000,
478 0x000003FF, 0x00000000, 0x00000000, 0x00000000,
479 0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
480 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
481 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
482 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
483 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
486 static efx_register_set_t __siena_tables[] = {
487 { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
488 FR_AZ_RX_FILTER_TBL0_ROWS },
489 { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
490 FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
491 { FR_AZ_RX_DESC_PTR_TBL_OFST,
492 FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
493 { FR_AZ_TX_DESC_PTR_TBL_OFST,
494 FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
495 { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
496 { FR_CZ_TX_FILTER_TBL0_OFST,
497 FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
498 { FR_CZ_TX_MAC_FILTER_TBL0_OFST,
499 FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
502 static const uint32_t __siena_table_masks[] = {
503 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
504 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
505 0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
506 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
507 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
508 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
509 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
512 __checkReturn efx_rc_t
513 siena_nic_register_test(
516 efx_register_set_t *rsp;
517 const uint32_t *dwordp;
522 /* Fill out the register mask entries */
523 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
524 == EFX_ARRAY_SIZE(__siena_registers) * 4);
526 nitems = EFX_ARRAY_SIZE(__siena_registers);
527 dwordp = __siena_register_masks;
528 for (count = 0; count < nitems; ++count) {
529 rsp = __siena_registers + count;
530 rsp->mask.eo_u32[0] = *dwordp++;
531 rsp->mask.eo_u32[1] = *dwordp++;
532 rsp->mask.eo_u32[2] = *dwordp++;
533 rsp->mask.eo_u32[3] = *dwordp++;
536 /* Fill out the register table entries */
537 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
538 == EFX_ARRAY_SIZE(__siena_tables) * 4);
540 nitems = EFX_ARRAY_SIZE(__siena_tables);
541 dwordp = __siena_table_masks;
542 for (count = 0; count < nitems; ++count) {
543 rsp = __siena_tables + count;
544 rsp->mask.eo_u32[0] = *dwordp++;
545 rsp->mask.eo_u32[1] = *dwordp++;
546 rsp->mask.eo_u32[2] = *dwordp++;
547 rsp->mask.eo_u32[3] = *dwordp++;
550 if ((rc = efx_nic_test_registers(enp, __siena_registers,
551 EFX_ARRAY_SIZE(__siena_registers))) != 0)
554 if ((rc = efx_nic_test_tables(enp, __siena_tables,
555 EFX_PATTERN_BYTE_ALTERNATE,
556 EFX_ARRAY_SIZE(__siena_tables))) != 0)
559 if ((rc = efx_nic_test_tables(enp, __siena_tables,
560 EFX_PATTERN_BYTE_CHANGING,
561 EFX_ARRAY_SIZE(__siena_tables))) != 0)
564 if ((rc = efx_nic_test_tables(enp, __siena_tables,
565 EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
577 EFSYS_PROBE1(fail1, efx_rc_t, rc);
582 #endif /* EFSYS_OPT_DIAG */
584 #endif /* EFSYS_OPT_SIENA */