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_fw_assisted_tso_v2_n_contexts = 0;
156 encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
158 /* Siena supports two 10G ports, and 8 lanes of PCIe Gen2 */
159 encp->enc_required_pcie_bandwidth_mbps = 2 * 10000;
160 encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN2;
167 EFSYS_PROBE1(fail1, efx_rc_t, rc);
172 static __checkReturn efx_rc_t
176 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
179 /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
180 if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
183 #if EFSYS_OPT_PHY_STATS
184 /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
185 siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask,
186 NULL, &encp->enc_phy_stat_mask, NULL);
187 #endif /* EFSYS_OPT_PHY_STATS */
192 EFSYS_PROBE1(fail1, efx_rc_t, rc);
197 __checkReturn efx_rc_t
201 efx_port_t *epp = &(enp->en_port);
202 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
203 siena_link_state_t sls;
208 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
211 if ((rc = efx_nic_biu_test(enp)) != 0)
214 /* Clear the region register */
215 EFX_POPULATE_OWORD_4(oword,
216 FRF_AZ_ADR_REGION0, 0,
217 FRF_AZ_ADR_REGION1, (1 << 16),
218 FRF_AZ_ADR_REGION2, (2 << 16),
219 FRF_AZ_ADR_REGION3, (3 << 16));
220 EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
222 /* Read clear any assertion state */
223 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
226 /* Exit the assertion handler */
227 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
230 /* Wrestle control from the BMC */
231 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
234 if ((rc = siena_board_cfg(enp)) != 0)
237 if ((rc = siena_phy_cfg(enp)) != 0)
240 /* Obtain the default PHY advertised capabilities */
241 if ((rc = siena_nic_reset(enp)) != 0)
243 if ((rc = siena_phy_get_link(enp, &sls)) != 0)
245 epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
246 epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
248 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
249 if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
251 enp->en_u.siena.enu_partn_mask = mask;
254 #if EFSYS_OPT_MAC_STATS
255 /* Wipe the MAC statistics */
256 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
260 #if EFSYS_OPT_LOOPBACK
261 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
265 #if EFSYS_OPT_MON_STATS
266 if ((rc = mcdi_mon_cfg_build(enp)) != 0)
270 encp->enc_features = enp->en_features;
274 #if EFSYS_OPT_MON_STATS
278 #if EFSYS_OPT_LOOPBACK
282 #if EFSYS_OPT_MAC_STATS
286 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
305 EFSYS_PROBE1(fail1, efx_rc_t, rc);
310 __checkReturn efx_rc_t
317 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
319 /* siena_nic_reset() is called to recover from BADASSERT failures. */
320 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
322 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
326 * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied
327 * for backwards compatibility with PORT_RESET_IN_LEN.
329 EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0);
331 req.emr_cmd = MC_CMD_ENTITY_RESET;
332 req.emr_in_buf = NULL;
333 req.emr_in_length = 0;
334 req.emr_out_buf = NULL;
335 req.emr_out_length = 0;
337 efx_mcdi_execute(enp, &req);
339 if (req.emr_rc != 0) {
351 EFSYS_PROBE1(fail1, efx_rc_t, rc);
363 * RX_INGR_EN is always enabled on Siena, because we rely on
364 * the RX parser to be resiliant to missing SOP/EOP.
366 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
367 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
368 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
370 /* Disable parsing of additional 802.1Q in Q packets */
371 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
372 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
373 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
382 EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
383 EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
386 __checkReturn efx_rc_t
392 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
394 /* Enable reporting of some events (e.g. link change) */
395 if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
398 siena_sram_init(enp);
400 /* Configure Siena's RX block */
401 siena_nic_rx_cfg(enp);
403 /* Disable USR_EVents for now */
404 siena_nic_usrev_dis(enp);
406 /* bug17057: Ensure set_link is called */
407 if ((rc = siena_phy_reconfigure(enp)) != 0)
410 enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V1;
417 EFSYS_PROBE1(fail1, efx_rc_t, rc);
426 _NOTE(ARGUNUSED(enp))
433 #if EFSYS_OPT_MON_STATS
434 mcdi_mon_cfg_free(enp);
435 #endif /* EFSYS_OPT_MON_STATS */
436 (void) efx_mcdi_drv_attach(enp, B_FALSE);
441 static efx_register_set_t __siena_registers[] = {
442 { FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
443 { FR_CZ_USR_EV_CFG_OFST, 0, 1 },
444 { FR_AZ_RX_CFG_REG_OFST, 0, 1 },
445 { FR_AZ_TX_CFG_REG_OFST, 0, 1 },
446 { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
447 { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
448 { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
449 { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
450 { FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
451 { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
452 { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
453 { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
454 { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
457 static const uint32_t __siena_register_masks[] = {
458 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
459 0x000103FF, 0x00000000, 0x00000000, 0x00000000,
460 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
461 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
462 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
463 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
464 0x00000003, 0x00000000, 0x00000000, 0x00000000,
465 0x000003FF, 0x00000000, 0x00000000, 0x00000000,
466 0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
467 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
468 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
469 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
470 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
473 static efx_register_set_t __siena_tables[] = {
474 { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
475 FR_AZ_RX_FILTER_TBL0_ROWS },
476 { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
477 FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
478 { FR_AZ_RX_DESC_PTR_TBL_OFST,
479 FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
480 { FR_AZ_TX_DESC_PTR_TBL_OFST,
481 FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
482 { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
483 { FR_CZ_TX_FILTER_TBL0_OFST,
484 FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
485 { FR_CZ_TX_MAC_FILTER_TBL0_OFST,
486 FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
489 static const uint32_t __siena_table_masks[] = {
490 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
491 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
492 0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
493 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
494 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
495 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
496 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
499 __checkReturn efx_rc_t
500 siena_nic_register_test(
503 efx_register_set_t *rsp;
504 const uint32_t *dwordp;
509 /* Fill out the register mask entries */
510 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
511 == EFX_ARRAY_SIZE(__siena_registers) * 4);
513 nitems = EFX_ARRAY_SIZE(__siena_registers);
514 dwordp = __siena_register_masks;
515 for (count = 0; count < nitems; ++count) {
516 rsp = __siena_registers + count;
517 rsp->mask.eo_u32[0] = *dwordp++;
518 rsp->mask.eo_u32[1] = *dwordp++;
519 rsp->mask.eo_u32[2] = *dwordp++;
520 rsp->mask.eo_u32[3] = *dwordp++;
523 /* Fill out the register table entries */
524 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
525 == EFX_ARRAY_SIZE(__siena_tables) * 4);
527 nitems = EFX_ARRAY_SIZE(__siena_tables);
528 dwordp = __siena_table_masks;
529 for (count = 0; count < nitems; ++count) {
530 rsp = __siena_tables + count;
531 rsp->mask.eo_u32[0] = *dwordp++;
532 rsp->mask.eo_u32[1] = *dwordp++;
533 rsp->mask.eo_u32[2] = *dwordp++;
534 rsp->mask.eo_u32[3] = *dwordp++;
537 if ((rc = efx_nic_test_registers(enp, __siena_registers,
538 EFX_ARRAY_SIZE(__siena_registers))) != 0)
541 if ((rc = efx_nic_test_tables(enp, __siena_tables,
542 EFX_PATTERN_BYTE_ALTERNATE,
543 EFX_ARRAY_SIZE(__siena_tables))) != 0)
546 if ((rc = efx_nic_test_tables(enp, __siena_tables,
547 EFX_PATTERN_BYTE_CHANGING,
548 EFX_ARRAY_SIZE(__siena_tables))) != 0)
551 if ((rc = efx_nic_test_tables(enp, __siena_tables,
552 EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
564 EFSYS_PROBE1(fail1, efx_rc_t, rc);
569 #endif /* EFSYS_OPT_DIAG */
571 #endif /* EFSYS_OPT_SIENA */