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$");
41 static __checkReturn int
42 siena_nic_get_partn_mask(
44 __out unsigned int *maskp)
47 uint8_t payload[MAX(MC_CMD_NVRAM_TYPES_IN_LEN,
48 MC_CMD_NVRAM_TYPES_OUT_LEN)];
51 (void) memset(payload, 0, sizeof (payload));
52 req.emr_cmd = MC_CMD_NVRAM_TYPES;
53 req.emr_in_buf = payload;
54 req.emr_in_length = MC_CMD_NVRAM_TYPES_IN_LEN;
55 req.emr_out_buf = payload;
56 req.emr_out_length = MC_CMD_NVRAM_TYPES_OUT_LEN;
58 efx_mcdi_execute(enp, &req);
60 if (req.emr_rc != 0) {
65 if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
70 *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
77 EFSYS_PROBE1(fail1, int, rc);
82 #if EFSYS_OPT_PCIE_TUNE
85 siena_nic_pcie_extended_sync(
90 if ((rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG17230,
97 EFSYS_PROBE1(fail1, int, rc);
102 #endif /* EFSYS_OPT_PCIE_TUNE */
104 static __checkReturn int
108 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
110 efx_dword_t capabilities;
112 uint32_t nevq, nrxq, ntxq;
115 /* External port identifier using one-based port numbering */
116 encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port;
118 /* Board configuration */
119 if ((rc = efx_mcdi_get_board_cfg(enp, &board_type,
120 &capabilities, mac_addr)) != 0)
123 EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
125 encp->enc_board_type = board_type;
127 /* Additional capabilities */
128 encp->enc_clk_mult = 1;
129 if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) {
130 enp->en_features |= EFX_FEATURE_TURBO;
132 if (EFX_DWORD_FIELD(capabilities,
133 MC_CMD_CAPABILITIES_TURBO_ACTIVE)) {
134 encp->enc_clk_mult = 2;
138 encp->enc_evq_timer_quantum_ns =
139 EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
140 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
141 FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
143 /* When hash header insertion is enabled, Siena inserts 16 bytes */
144 encp->enc_rx_prefix_size = 16;
146 /* Alignment for receive packet DMA buffers */
147 encp->enc_rx_buf_align_start = 1;
148 encp->enc_rx_buf_align_end = 1;
150 /* Alignment for WPTR updates */
151 encp->enc_rx_push_align = 1;
153 /* Resource limits */
154 rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq);
160 nrxq = EFX_RXQ_LIMIT_TARGET;
161 ntxq = EFX_TXQ_LIMIT_TARGET;
163 encp->enc_evq_limit = nevq;
164 encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq);
165 encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq);
167 encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
168 (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) -
169 (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
171 encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
172 encp->enc_fw_assisted_tso_enabled = B_FALSE;
179 EFSYS_PROBE1(fail1, int, rc);
184 static __checkReturn int
188 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
191 /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
192 if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
195 #if EFSYS_OPT_PHY_STATS
196 /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
197 siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask,
198 NULL, &encp->enc_phy_stat_mask, NULL);
199 #endif /* EFSYS_OPT_PHY_STATS */
204 EFSYS_PROBE1(fail1, int, rc);
213 efx_port_t *epp = &(enp->en_port);
214 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
215 siena_link_state_t sls;
220 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
223 if ((rc = efx_nic_biu_test(enp)) != 0)
226 /* Clear the region register */
227 EFX_POPULATE_OWORD_4(oword,
228 FRF_AZ_ADR_REGION0, 0,
229 FRF_AZ_ADR_REGION1, (1 << 16),
230 FRF_AZ_ADR_REGION2, (2 << 16),
231 FRF_AZ_ADR_REGION3, (3 << 16));
232 EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
234 /* Read clear any assertion state */
235 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
238 /* Exit the assertion handler */
239 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
242 /* Wrestle control from the BMC */
243 if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
246 if ((rc = siena_board_cfg(enp)) != 0)
249 if ((rc = siena_phy_cfg(enp)) != 0)
252 /* Obtain the default PHY advertised capabilities */
253 if ((rc = siena_nic_reset(enp)) != 0)
255 if ((rc = siena_phy_get_link(enp, &sls)) != 0)
257 epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
258 epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
260 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
261 if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
263 enp->en_u.siena.enu_partn_mask = mask;
266 #if EFSYS_OPT_MAC_STATS
267 /* Wipe the MAC statistics */
268 if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
272 #if EFSYS_OPT_LOOPBACK
273 if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
277 #if EFSYS_OPT_MON_STATS
278 if ((rc = mcdi_mon_cfg_build(enp)) != 0)
282 encp->enc_features = enp->en_features;
286 #if EFSYS_OPT_MON_STATS
290 #if EFSYS_OPT_LOOPBACK
294 #if EFSYS_OPT_MAC_STATS
298 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
317 EFSYS_PROBE1(fail1, int, rc);
329 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
331 /* siena_nic_reset() is called to recover from BADASSERT failures. */
332 if ((rc = efx_mcdi_read_assertion(enp)) != 0)
334 if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
338 * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied
339 * for backwards compatibility with PORT_RESET_IN_LEN.
341 EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0);
343 req.emr_cmd = MC_CMD_ENTITY_RESET;
344 req.emr_in_buf = NULL;
345 req.emr_in_length = 0;
346 req.emr_out_buf = NULL;
347 req.emr_out_length = 0;
349 efx_mcdi_execute(enp, &req);
351 if (req.emr_rc != 0) {
363 EFSYS_PROBE1(fail1, int, rc);
375 * RX_INGR_EN is always enabled on Siena, because we rely on
376 * the RX parser to be resiliant to missing SOP/EOP.
378 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
379 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
380 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
382 /* Disable parsing of additional 802.1Q in Q packets */
383 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
384 EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
385 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
394 EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
395 EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
404 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
406 /* Enable reporting of some events (e.g. link change) */
407 if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
410 siena_sram_init(enp);
412 /* Configure Siena's RX block */
413 siena_nic_rx_cfg(enp);
415 /* Disable USR_EVents for now */
416 siena_nic_usrev_dis(enp);
418 /* bug17057: Ensure set_link is called */
419 if ((rc = siena_phy_reconfigure(enp)) != 0)
427 EFSYS_PROBE1(fail1, int, rc);
436 _NOTE(ARGUNUSED(enp))
443 #if EFSYS_OPT_MON_STATS
444 mcdi_mon_cfg_free(enp);
445 #endif /* EFSYS_OPT_MON_STATS */
446 (void) efx_mcdi_drv_attach(enp, B_FALSE);
451 static efx_register_set_t __siena_registers[] = {
452 { FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
453 { FR_CZ_USR_EV_CFG_OFST, 0, 1 },
454 { FR_AZ_RX_CFG_REG_OFST, 0, 1 },
455 { FR_AZ_TX_CFG_REG_OFST, 0, 1 },
456 { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
457 { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
458 { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
459 { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
460 { FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
461 { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
462 { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
463 { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
464 { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
467 static const uint32_t __siena_register_masks[] = {
468 0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
469 0x000103FF, 0x00000000, 0x00000000, 0x00000000,
470 0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
471 0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
472 0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
473 0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
474 0x00000003, 0x00000000, 0x00000000, 0x00000000,
475 0x000003FF, 0x00000000, 0x00000000, 0x00000000,
476 0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
477 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
478 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
479 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
480 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
483 static efx_register_set_t __siena_tables[] = {
484 { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
485 FR_AZ_RX_FILTER_TBL0_ROWS },
486 { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
487 FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
488 { FR_AZ_RX_DESC_PTR_TBL_OFST,
489 FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
490 { FR_AZ_TX_DESC_PTR_TBL_OFST,
491 FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
492 { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
493 { FR_CZ_TX_FILTER_TBL0_OFST,
494 FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
495 { FR_CZ_TX_MAC_FILTER_TBL0_OFST,
496 FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
499 static const uint32_t __siena_table_masks[] = {
500 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
501 0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
502 0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
503 0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
504 0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
505 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
506 0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
510 siena_nic_register_test(
513 efx_register_set_t *rsp;
514 const uint32_t *dwordp;
519 /* Fill out the register mask entries */
520 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
521 == EFX_ARRAY_SIZE(__siena_registers) * 4);
523 nitems = EFX_ARRAY_SIZE(__siena_registers);
524 dwordp = __siena_register_masks;
525 for (count = 0; count < nitems; ++count) {
526 rsp = __siena_registers + count;
527 rsp->mask.eo_u32[0] = *dwordp++;
528 rsp->mask.eo_u32[1] = *dwordp++;
529 rsp->mask.eo_u32[2] = *dwordp++;
530 rsp->mask.eo_u32[3] = *dwordp++;
533 /* Fill out the register table entries */
534 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
535 == EFX_ARRAY_SIZE(__siena_tables) * 4);
537 nitems = EFX_ARRAY_SIZE(__siena_tables);
538 dwordp = __siena_table_masks;
539 for (count = 0; count < nitems; ++count) {
540 rsp = __siena_tables + count;
541 rsp->mask.eo_u32[0] = *dwordp++;
542 rsp->mask.eo_u32[1] = *dwordp++;
543 rsp->mask.eo_u32[2] = *dwordp++;
544 rsp->mask.eo_u32[3] = *dwordp++;
547 if ((rc = efx_nic_test_registers(enp, __siena_registers,
548 EFX_ARRAY_SIZE(__siena_registers))) != 0)
551 if ((rc = efx_nic_test_tables(enp, __siena_tables,
552 EFX_PATTERN_BYTE_ALTERNATE,
553 EFX_ARRAY_SIZE(__siena_tables))) != 0)
556 if ((rc = efx_nic_test_tables(enp, __siena_tables,
557 EFX_PATTERN_BYTE_CHANGING,
558 EFX_ARRAY_SIZE(__siena_tables))) != 0)
561 if ((rc = efx_nic_test_tables(enp, __siena_tables,
562 EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
574 EFSYS_PROBE1(fail1, int, rc);
579 #endif /* EFSYS_OPT_DIAG */
581 #endif /* EFSYS_OPT_SIENA */