2 * Copyright (c) 2009-2016 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 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
42 static __checkReturn efx_rc_t
43 siena_nic_get_partn_mask(
45 __out unsigned int *maskp)
48 uint8_t payload[MAX(MC_CMD_NVRAM_TYPES_IN_LEN,
49 MC_CMD_NVRAM_TYPES_OUT_LEN)];
52 (void) memset(payload, 0, sizeof (payload));
53 req.emr_cmd = MC_CMD_NVRAM_TYPES;
54 req.emr_in_buf = payload;
55 req.emr_in_length = MC_CMD_NVRAM_TYPES_IN_LEN;
56 req.emr_out_buf = payload;
57 req.emr_out_length = MC_CMD_NVRAM_TYPES_OUT_LEN;
59 efx_mcdi_execute(enp, &req);
61 if (req.emr_rc != 0) {
66 if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
71 *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
78 EFSYS_PROBE1(fail1, efx_rc_t, rc);
83 #endif /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */
85 static __checkReturn efx_rc_t
89 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
91 efx_dword_t capabilities;
93 uint32_t nevq, nrxq, ntxq;
96 /* External port identifier using one-based port numbering */
97 encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port;
99 /* Board configuration */
100 if ((rc = efx_mcdi_get_board_cfg(enp, &board_type,
101 &capabilities, mac_addr)) != 0)
104 EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
106 encp->enc_board_type = board_type;
108 /* Additional capabilities */
109 encp->enc_clk_mult = 1;
110 if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) {
111 enp->en_features |= EFX_FEATURE_TURBO;
113 if (EFX_DWORD_FIELD(capabilities,
114 MC_CMD_CAPABILITIES_TURBO_ACTIVE)) {
115 encp->enc_clk_mult = 2;
119 encp->enc_evq_timer_quantum_ns =
120 EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
121 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
122 FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
124 /* When hash header insertion is enabled, Siena inserts 16 bytes */
125 encp->enc_rx_prefix_size = 16;
127 /* Alignment for receive packet DMA buffers */
128 encp->enc_rx_buf_align_start = 1;
129 encp->enc_rx_buf_align_end = 1;
131 /* Alignment for WPTR updates */
132 encp->enc_rx_push_align = 1;
134 /* Resource limits */
135 rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq);
141 nrxq = EFX_RXQ_LIMIT_TARGET;
142 ntxq = EFX_TXQ_LIMIT_TARGET;
144 encp->enc_evq_limit = nevq;
145 encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq);
146 encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq);
148 encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
149 (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) -
150 (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
152 encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
153 encp->enc_fw_assisted_tso_enabled = B_FALSE;
154 encp->enc_fw_assisted_tso_v2_enabled = B_FALSE;
155 encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
157 /* Siena supports two 10G ports, and 8 lanes of PCIe Gen2 */
158 encp->enc_required_pcie_bandwidth_mbps = 2 * 10000;
159 encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN2;
166 EFSYS_PROBE1(fail1, efx_rc_t, rc);
171 static __checkReturn efx_rc_t
175 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
178 /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
179 if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
182 #if EFSYS_OPT_PHY_STATS
183 /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
184 siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask,
185 NULL, &encp->enc_phy_stat_mask, NULL);
186 #endif /* EFSYS_OPT_PHY_STATS */
191 EFSYS_PROBE1(fail1, efx_rc_t, rc);
196 __checkReturn efx_rc_t
200 efx_port_t *epp = &(enp->en_port);
201 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
202 siena_link_state_t sls;
207 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
210 if ((rc = efx_nic_biu_test(enp)) != 0)
213 /* Clear the region register */
214 EFX_POPULATE_OWORD_4(oword,
215 FRF_AZ_ADR_REGION0, 0,
216 FRF_AZ_ADR_REGION1, (1 << 16),
217 FRF_AZ_ADR_REGION2, (2 << 16),
218 FRF_AZ_ADR_REGION3, (3 << 16));
219 EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
221 /* Read clear any assertion state */
222 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
225 /* Exit the assertion handler */
226 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
229 /* Wrestle control from the BMC */
230 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
233 if ((rc = siena_board_cfg(enp)) != 0)
236 if ((rc = siena_phy_cfg(enp)) != 0)
239 /* Obtain the default PHY advertised capabilities */
240 if ((rc = siena_nic_reset(enp)) != 0)
242 if ((rc = siena_phy_get_link(enp, &sls)) != 0)
244 epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
245 epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
247 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
248 if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
250 enp->en_u.siena.enu_partn_mask = mask;
253 #if EFSYS_OPT_MAC_STATS
254 /* Wipe the MAC statistics */
255 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
259 #if EFSYS_OPT_LOOPBACK
260 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
264 #if EFSYS_OPT_MON_STATS
265 if ((rc = mcdi_mon_cfg_build(enp)) != 0)
269 encp->enc_features = enp->en_features;
273 #if EFSYS_OPT_MON_STATS
277 #if EFSYS_OPT_LOOPBACK
281 #if EFSYS_OPT_MAC_STATS
285 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
304 EFSYS_PROBE1(fail1, efx_rc_t, rc);
309 __checkReturn efx_rc_t
316 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
318 /* siena_nic_reset() is called to recover from BADASSERT failures. */
319 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
321 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
325 * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied
326 * for backwards compatibility with PORT_RESET_IN_LEN.
328 EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0);
330 req.emr_cmd = MC_CMD_ENTITY_RESET;
331 req.emr_in_buf = NULL;
332 req.emr_in_length = 0;
333 req.emr_out_buf = NULL;
334 req.emr_out_length = 0;
336 efx_mcdi_execute(enp, &req);
338 if (req.emr_rc != 0) {
350 EFSYS_PROBE1(fail1, efx_rc_t, rc);
362 * RX_INGR_EN is always enabled on Siena, because we rely on
363 * the RX parser to be resiliant to missing SOP/EOP.
365 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
366 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
367 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
369 /* Disable parsing of additional 802.1Q in Q packets */
370 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
371 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
372 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
381 EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
382 EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
385 __checkReturn efx_rc_t
391 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
393 /* Enable reporting of some events (e.g. link change) */
394 if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
397 siena_sram_init(enp);
399 /* Configure Siena's RX block */
400 siena_nic_rx_cfg(enp);
402 /* Disable USR_EVents for now */
403 siena_nic_usrev_dis(enp);
405 /* bug17057: Ensure set_link is called */
406 if ((rc = siena_phy_reconfigure(enp)) != 0)
409 enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V1;
416 EFSYS_PROBE1(fail1, efx_rc_t, rc);
425 _NOTE(ARGUNUSED(enp))
432 #if EFSYS_OPT_MON_STATS
433 mcdi_mon_cfg_free(enp);
434 #endif /* EFSYS_OPT_MON_STATS */
435 (void) efx_mcdi_drv_attach(enp, B_FALSE);
440 static efx_register_set_t __siena_registers[] = {
441 { FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
442 { FR_CZ_USR_EV_CFG_OFST, 0, 1 },
443 { FR_AZ_RX_CFG_REG_OFST, 0, 1 },
444 { FR_AZ_TX_CFG_REG_OFST, 0, 1 },
445 { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
446 { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
447 { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
448 { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
449 { FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
450 { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
451 { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
452 { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
453 { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
456 static const uint32_t __siena_register_masks[] = {
457 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
458 0x000103FF, 0x00000000, 0x00000000, 0x00000000,
459 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
460 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
461 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
462 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
463 0x00000003, 0x00000000, 0x00000000, 0x00000000,
464 0x000003FF, 0x00000000, 0x00000000, 0x00000000,
465 0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
466 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
467 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
468 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
469 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
472 static efx_register_set_t __siena_tables[] = {
473 { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
474 FR_AZ_RX_FILTER_TBL0_ROWS },
475 { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
476 FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
477 { FR_AZ_RX_DESC_PTR_TBL_OFST,
478 FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
479 { FR_AZ_TX_DESC_PTR_TBL_OFST,
480 FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
481 { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
482 { FR_CZ_TX_FILTER_TBL0_OFST,
483 FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
484 { FR_CZ_TX_MAC_FILTER_TBL0_OFST,
485 FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
488 static const uint32_t __siena_table_masks[] = {
489 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
490 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
491 0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
492 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
493 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
494 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
495 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
498 __checkReturn efx_rc_t
499 siena_nic_register_test(
502 efx_register_set_t *rsp;
503 const uint32_t *dwordp;
508 /* Fill out the register mask entries */
509 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
510 == EFX_ARRAY_SIZE(__siena_registers) * 4);
512 nitems = EFX_ARRAY_SIZE(__siena_registers);
513 dwordp = __siena_register_masks;
514 for (count = 0; count < nitems; ++count) {
515 rsp = __siena_registers + count;
516 rsp->mask.eo_u32[0] = *dwordp++;
517 rsp->mask.eo_u32[1] = *dwordp++;
518 rsp->mask.eo_u32[2] = *dwordp++;
519 rsp->mask.eo_u32[3] = *dwordp++;
522 /* Fill out the register table entries */
523 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
524 == EFX_ARRAY_SIZE(__siena_tables) * 4);
526 nitems = EFX_ARRAY_SIZE(__siena_tables);
527 dwordp = __siena_table_masks;
528 for (count = 0; count < nitems; ++count) {
529 rsp = __siena_tables + 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 if ((rc = efx_nic_test_registers(enp, __siena_registers,
537 EFX_ARRAY_SIZE(__siena_registers))) != 0)
540 if ((rc = efx_nic_test_tables(enp, __siena_tables,
541 EFX_PATTERN_BYTE_ALTERNATE,
542 EFX_ARRAY_SIZE(__siena_tables))) != 0)
545 if ((rc = efx_nic_test_tables(enp, __siena_tables,
546 EFX_PATTERN_BYTE_CHANGING,
547 EFX_ARRAY_SIZE(__siena_tables))) != 0)
550 if ((rc = efx_nic_test_tables(enp, __siena_tables,
551 EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
563 EFSYS_PROBE1(fail1, efx_rc_t, rc);
568 #endif /* EFSYS_OPT_DIAG */
570 #endif /* EFSYS_OPT_SIENA */