1*49ef7e06SGarrett D'Amore /*
2*49ef7e06SGarrett D'Amore  * Copyright (c) 2009-2015 Solarflare Communications Inc.
3*49ef7e06SGarrett D'Amore  * All rights reserved.
4*49ef7e06SGarrett D'Amore  *
5*49ef7e06SGarrett D'Amore  * Redistribution and use in source and binary forms, with or without
6*49ef7e06SGarrett D'Amore  * modification, are permitted provided that the following conditions are met:
7*49ef7e06SGarrett D'Amore  *
8*49ef7e06SGarrett D'Amore  * 1. Redistributions of source code must retain the above copyright notice,
9*49ef7e06SGarrett D'Amore  *    this list of conditions and the following disclaimer.
10*49ef7e06SGarrett D'Amore  * 2. Redistributions in binary form must reproduce the above copyright notice,
11*49ef7e06SGarrett D'Amore  *    this list of conditions and the following disclaimer in the documentation
12*49ef7e06SGarrett D'Amore  *    and/or other materials provided with the distribution.
13*49ef7e06SGarrett D'Amore  *
14*49ef7e06SGarrett D'Amore  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15*49ef7e06SGarrett D'Amore  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16*49ef7e06SGarrett D'Amore  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17*49ef7e06SGarrett D'Amore  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18*49ef7e06SGarrett D'Amore  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19*49ef7e06SGarrett D'Amore  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20*49ef7e06SGarrett D'Amore  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21*49ef7e06SGarrett D'Amore  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22*49ef7e06SGarrett D'Amore  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23*49ef7e06SGarrett D'Amore  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24*49ef7e06SGarrett D'Amore  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*49ef7e06SGarrett D'Amore  *
26*49ef7e06SGarrett D'Amore  * The views and conclusions contained in the software and documentation are
27*49ef7e06SGarrett D'Amore  * those of the authors and should not be interpreted as representing official
28*49ef7e06SGarrett D'Amore  * policies, either expressed or implied, of the FreeBSD Project.
29*49ef7e06SGarrett D'Amore  */
30*49ef7e06SGarrett D'Amore 
31*49ef7e06SGarrett D'Amore #include "efx.h"
32*49ef7e06SGarrett D'Amore #include "efx_impl.h"
33*49ef7e06SGarrett D'Amore #include "mcdi_mon.h"
34*49ef7e06SGarrett D'Amore 
35*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA
36*49ef7e06SGarrett D'Amore 
37*49ef7e06SGarrett D'Amore static	__checkReturn		efx_rc_t
siena_nic_get_partn_mask(__in efx_nic_t * enp,__out unsigned int * maskp)38*49ef7e06SGarrett D'Amore siena_nic_get_partn_mask(
39*49ef7e06SGarrett D'Amore 	__in			efx_nic_t *enp,
40*49ef7e06SGarrett D'Amore 	__out			unsigned int *maskp)
41*49ef7e06SGarrett D'Amore {
42*49ef7e06SGarrett D'Amore 	efx_mcdi_req_t req;
43*49ef7e06SGarrett D'Amore 	uint8_t payload[MAX(MC_CMD_NVRAM_TYPES_IN_LEN,
44*49ef7e06SGarrett D'Amore 			    MC_CMD_NVRAM_TYPES_OUT_LEN)];
45*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
46*49ef7e06SGarrett D'Amore 
47*49ef7e06SGarrett D'Amore 	(void) memset(payload, 0, sizeof (payload));
48*49ef7e06SGarrett D'Amore 	req.emr_cmd = MC_CMD_NVRAM_TYPES;
49*49ef7e06SGarrett D'Amore 	req.emr_in_buf = payload;
50*49ef7e06SGarrett D'Amore 	req.emr_in_length = MC_CMD_NVRAM_TYPES_IN_LEN;
51*49ef7e06SGarrett D'Amore 	req.emr_out_buf = payload;
52*49ef7e06SGarrett D'Amore 	req.emr_out_length = MC_CMD_NVRAM_TYPES_OUT_LEN;
53*49ef7e06SGarrett D'Amore 
54*49ef7e06SGarrett D'Amore 	efx_mcdi_execute(enp, &req);
55*49ef7e06SGarrett D'Amore 
56*49ef7e06SGarrett D'Amore 	if (req.emr_rc != 0) {
57*49ef7e06SGarrett D'Amore 		rc = req.emr_rc;
58*49ef7e06SGarrett D'Amore 		goto fail1;
59*49ef7e06SGarrett D'Amore 	}
60*49ef7e06SGarrett D'Amore 
61*49ef7e06SGarrett D'Amore 	if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
62*49ef7e06SGarrett D'Amore 		rc = EMSGSIZE;
63*49ef7e06SGarrett D'Amore 		goto fail2;
64*49ef7e06SGarrett D'Amore 	}
65*49ef7e06SGarrett D'Amore 
66*49ef7e06SGarrett D'Amore 	*maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
67*49ef7e06SGarrett D'Amore 
68*49ef7e06SGarrett D'Amore 	return (0);
69*49ef7e06SGarrett D'Amore 
70*49ef7e06SGarrett D'Amore fail2:
71*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
72*49ef7e06SGarrett D'Amore fail1:
73*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
74*49ef7e06SGarrett D'Amore 
75*49ef7e06SGarrett D'Amore 	return (rc);
76*49ef7e06SGarrett D'Amore }
77*49ef7e06SGarrett D'Amore 
78*49ef7e06SGarrett D'Amore static	__checkReturn	efx_rc_t
siena_board_cfg(__in efx_nic_t * enp)79*49ef7e06SGarrett D'Amore siena_board_cfg(
80*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp)
81*49ef7e06SGarrett D'Amore {
82*49ef7e06SGarrett D'Amore 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
83*49ef7e06SGarrett D'Amore 	uint8_t mac_addr[6];
84*49ef7e06SGarrett D'Amore 	efx_dword_t capabilities;
85*49ef7e06SGarrett D'Amore 	uint32_t board_type;
86*49ef7e06SGarrett D'Amore 	uint32_t nevq, nrxq, ntxq;
87*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
88*49ef7e06SGarrett D'Amore 
89*49ef7e06SGarrett D'Amore 	/* External port identifier using one-based port numbering */
90*49ef7e06SGarrett D'Amore 	encp->enc_external_port = (uint8_t)enp->en_mcdi.em_emip.emi_port;
91*49ef7e06SGarrett D'Amore 
92*49ef7e06SGarrett D'Amore 	/* Board configuration */
93*49ef7e06SGarrett D'Amore 	if ((rc = efx_mcdi_get_board_cfg(enp, &board_type,
94*49ef7e06SGarrett D'Amore 		    &capabilities, mac_addr)) != 0)
95*49ef7e06SGarrett D'Amore 		goto fail1;
96*49ef7e06SGarrett D'Amore 
97*49ef7e06SGarrett D'Amore 	EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
98*49ef7e06SGarrett D'Amore 
99*49ef7e06SGarrett D'Amore 	encp->enc_board_type = board_type;
100*49ef7e06SGarrett D'Amore 
101*49ef7e06SGarrett D'Amore 	/* Additional capabilities */
102*49ef7e06SGarrett D'Amore 	encp->enc_clk_mult = 1;
103*49ef7e06SGarrett D'Amore 	if (EFX_DWORD_FIELD(capabilities, MC_CMD_CAPABILITIES_TURBO)) {
104*49ef7e06SGarrett D'Amore 		enp->en_features |= EFX_FEATURE_TURBO;
105*49ef7e06SGarrett D'Amore 
106*49ef7e06SGarrett D'Amore 		if (EFX_DWORD_FIELD(capabilities,
107*49ef7e06SGarrett D'Amore 			MC_CMD_CAPABILITIES_TURBO_ACTIVE)) {
108*49ef7e06SGarrett D'Amore 			encp->enc_clk_mult = 2;
109*49ef7e06SGarrett D'Amore 		}
110*49ef7e06SGarrett D'Amore 	}
111*49ef7e06SGarrett D'Amore 
112*49ef7e06SGarrett D'Amore 	encp->enc_evq_timer_quantum_ns =
113*49ef7e06SGarrett D'Amore 		EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
114*49ef7e06SGarrett D'Amore 	encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
115*49ef7e06SGarrett D'Amore 		FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
116*49ef7e06SGarrett D'Amore 
117*49ef7e06SGarrett D'Amore 	/* When hash header insertion is enabled, Siena inserts 16 bytes */
118*49ef7e06SGarrett D'Amore 	encp->enc_rx_prefix_size = 16;
119*49ef7e06SGarrett D'Amore 
120*49ef7e06SGarrett D'Amore 	/* Alignment for receive packet DMA buffers */
121*49ef7e06SGarrett D'Amore 	encp->enc_rx_buf_align_start = 1;
122*49ef7e06SGarrett D'Amore 	encp->enc_rx_buf_align_end = 1;
123*49ef7e06SGarrett D'Amore 
124*49ef7e06SGarrett D'Amore 	/* Alignment for WPTR updates */
125*49ef7e06SGarrett D'Amore 	encp->enc_rx_push_align = 1;
126*49ef7e06SGarrett D'Amore 
127*49ef7e06SGarrett D'Amore 	/* Resource limits */
128*49ef7e06SGarrett D'Amore 	rc = efx_mcdi_get_resource_limits(enp, &nevq, &nrxq, &ntxq);
129*49ef7e06SGarrett D'Amore 	if (rc != 0) {
130*49ef7e06SGarrett D'Amore 		if (rc != ENOTSUP)
131*49ef7e06SGarrett D'Amore 			goto fail2;
132*49ef7e06SGarrett D'Amore 
133*49ef7e06SGarrett D'Amore 		nevq = 1024;
134*49ef7e06SGarrett D'Amore 		nrxq = EFX_RXQ_LIMIT_TARGET;
135*49ef7e06SGarrett D'Amore 		ntxq = EFX_TXQ_LIMIT_TARGET;
136*49ef7e06SGarrett D'Amore 	}
137*49ef7e06SGarrett D'Amore 	encp->enc_evq_limit = nevq;
138*49ef7e06SGarrett D'Amore 	encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET, nrxq);
139*49ef7e06SGarrett D'Amore 	encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET, ntxq);
140*49ef7e06SGarrett D'Amore 
141*49ef7e06SGarrett D'Amore 	encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
142*49ef7e06SGarrett D'Amore 	    (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) -
143*49ef7e06SGarrett D'Amore 	    (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
144*49ef7e06SGarrett D'Amore 
145*49ef7e06SGarrett D'Amore 	encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
146*49ef7e06SGarrett D'Amore 	encp->enc_fw_assisted_tso_enabled = B_FALSE;
147*49ef7e06SGarrett D'Amore 	encp->enc_fw_assisted_tso_v2_enabled = B_FALSE;
148*49ef7e06SGarrett D'Amore 	encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
149*49ef7e06SGarrett D'Amore 
150*49ef7e06SGarrett D'Amore 	return (0);
151*49ef7e06SGarrett D'Amore 
152*49ef7e06SGarrett D'Amore fail2:
153*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
154*49ef7e06SGarrett D'Amore fail1:
155*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
156*49ef7e06SGarrett D'Amore 
157*49ef7e06SGarrett D'Amore 	return (rc);
158*49ef7e06SGarrett D'Amore }
159*49ef7e06SGarrett D'Amore 
160*49ef7e06SGarrett D'Amore static	__checkReturn	efx_rc_t
siena_phy_cfg(__in efx_nic_t * enp)161*49ef7e06SGarrett D'Amore siena_phy_cfg(
162*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp)
163*49ef7e06SGarrett D'Amore {
164*49ef7e06SGarrett D'Amore 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
165*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
166*49ef7e06SGarrett D'Amore 
167*49ef7e06SGarrett D'Amore 	/* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
168*49ef7e06SGarrett D'Amore 	if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
169*49ef7e06SGarrett D'Amore 		goto fail1;
170*49ef7e06SGarrett D'Amore 
171*49ef7e06SGarrett D'Amore #if EFSYS_OPT_PHY_STATS
172*49ef7e06SGarrett D'Amore 	/* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
173*49ef7e06SGarrett D'Amore 	siena_phy_decode_stats(enp, encp->enc_mcdi_phy_stat_mask,
174*49ef7e06SGarrett D'Amore 			    NULL, &encp->enc_phy_stat_mask, NULL);
175*49ef7e06SGarrett D'Amore #endif	/* EFSYS_OPT_PHY_STATS */
176*49ef7e06SGarrett D'Amore 
177*49ef7e06SGarrett D'Amore 	return (0);
178*49ef7e06SGarrett D'Amore 
179*49ef7e06SGarrett D'Amore fail1:
180*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
181*49ef7e06SGarrett D'Amore 
182*49ef7e06SGarrett D'Amore 	return (rc);
183*49ef7e06SGarrett D'Amore }
184*49ef7e06SGarrett D'Amore 
185*49ef7e06SGarrett D'Amore 	__checkReturn	efx_rc_t
siena_nic_probe(__in efx_nic_t * enp)186*49ef7e06SGarrett D'Amore siena_nic_probe(
187*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp)
188*49ef7e06SGarrett D'Amore {
189*49ef7e06SGarrett D'Amore 	efx_port_t *epp = &(enp->en_port);
190*49ef7e06SGarrett D'Amore 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
191*49ef7e06SGarrett D'Amore 	siena_link_state_t sls;
192*49ef7e06SGarrett D'Amore 	unsigned int mask;
193*49ef7e06SGarrett D'Amore 	efx_oword_t oword;
194*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
195*49ef7e06SGarrett D'Amore 
196*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
197*49ef7e06SGarrett D'Amore 
198*49ef7e06SGarrett D'Amore 	/* Test BIU */
199*49ef7e06SGarrett D'Amore 	if ((rc = efx_nic_biu_test(enp)) != 0)
200*49ef7e06SGarrett D'Amore 		goto fail1;
201*49ef7e06SGarrett D'Amore 
202*49ef7e06SGarrett D'Amore 	/* Clear the region register */
203*49ef7e06SGarrett D'Amore 	EFX_POPULATE_OWORD_4(oword,
204*49ef7e06SGarrett D'Amore 	    FRF_AZ_ADR_REGION0, 0,
205*49ef7e06SGarrett D'Amore 	    FRF_AZ_ADR_REGION1, (1 << 16),
206*49ef7e06SGarrett D'Amore 	    FRF_AZ_ADR_REGION2, (2 << 16),
207*49ef7e06SGarrett D'Amore 	    FRF_AZ_ADR_REGION3, (3 << 16));
208*49ef7e06SGarrett D'Amore 	EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
209*49ef7e06SGarrett D'Amore 
210*49ef7e06SGarrett D'Amore 	/* Read clear any assertion state */
211*49ef7e06SGarrett D'Amore 	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
212*49ef7e06SGarrett D'Amore 		goto fail2;
213*49ef7e06SGarrett D'Amore 
214*49ef7e06SGarrett D'Amore 	/* Exit the assertion handler */
215*49ef7e06SGarrett D'Amore 	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
216*49ef7e06SGarrett D'Amore 		goto fail3;
217*49ef7e06SGarrett D'Amore 
218*49ef7e06SGarrett D'Amore 	/* Wrestle control from the BMC */
219*49ef7e06SGarrett D'Amore 	if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
220*49ef7e06SGarrett D'Amore 		goto fail4;
221*49ef7e06SGarrett D'Amore 
222*49ef7e06SGarrett D'Amore 	if ((rc = siena_board_cfg(enp)) != 0)
223*49ef7e06SGarrett D'Amore 		goto fail5;
224*49ef7e06SGarrett D'Amore 
225*49ef7e06SGarrett D'Amore 	if ((rc = siena_phy_cfg(enp)) != 0)
226*49ef7e06SGarrett D'Amore 		goto fail6;
227*49ef7e06SGarrett D'Amore 
228*49ef7e06SGarrett D'Amore 	/* Obtain the default PHY advertised capabilities */
229*49ef7e06SGarrett D'Amore 	if ((rc = siena_nic_reset(enp)) != 0)
230*49ef7e06SGarrett D'Amore 		goto fail7;
231*49ef7e06SGarrett D'Amore 	if ((rc = siena_phy_get_link(enp, &sls)) != 0)
232*49ef7e06SGarrett D'Amore 		goto fail8;
233*49ef7e06SGarrett D'Amore 	epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
234*49ef7e06SGarrett D'Amore 	epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
235*49ef7e06SGarrett D'Amore 
236*49ef7e06SGarrett D'Amore #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
237*49ef7e06SGarrett D'Amore 	if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
238*49ef7e06SGarrett D'Amore 		goto fail9;
239*49ef7e06SGarrett D'Amore 	enp->en_u.siena.enu_partn_mask = mask;
240*49ef7e06SGarrett D'Amore #endif
241*49ef7e06SGarrett D'Amore 
242*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MAC_STATS
243*49ef7e06SGarrett D'Amore 	/* Wipe the MAC statistics */
244*49ef7e06SGarrett D'Amore 	if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
245*49ef7e06SGarrett D'Amore 		goto fail10;
246*49ef7e06SGarrett D'Amore #endif
247*49ef7e06SGarrett D'Amore 
248*49ef7e06SGarrett D'Amore #if EFSYS_OPT_LOOPBACK
249*49ef7e06SGarrett D'Amore 	if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
250*49ef7e06SGarrett D'Amore 		goto fail11;
251*49ef7e06SGarrett D'Amore #endif
252*49ef7e06SGarrett D'Amore 
253*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MON_STATS
254*49ef7e06SGarrett D'Amore 	if ((rc = mcdi_mon_cfg_build(enp)) != 0)
255*49ef7e06SGarrett D'Amore 		goto fail12;
256*49ef7e06SGarrett D'Amore #endif
257*49ef7e06SGarrett D'Amore 
258*49ef7e06SGarrett D'Amore 	encp->enc_features = enp->en_features;
259*49ef7e06SGarrett D'Amore 
260*49ef7e06SGarrett D'Amore 	return (0);
261*49ef7e06SGarrett D'Amore 
262*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MON_STATS
263*49ef7e06SGarrett D'Amore fail12:
264*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail12);
265*49ef7e06SGarrett D'Amore #endif
266*49ef7e06SGarrett D'Amore #if EFSYS_OPT_LOOPBACK
267*49ef7e06SGarrett D'Amore fail11:
268*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail11);
269*49ef7e06SGarrett D'Amore #endif
270*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MAC_STATS
271*49ef7e06SGarrett D'Amore fail10:
272*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail10);
273*49ef7e06SGarrett D'Amore #endif
274*49ef7e06SGarrett D'Amore #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
275*49ef7e06SGarrett D'Amore fail9:
276*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail9);
277*49ef7e06SGarrett D'Amore #endif
278*49ef7e06SGarrett D'Amore fail8:
279*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail8);
280*49ef7e06SGarrett D'Amore fail7:
281*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail7);
282*49ef7e06SGarrett D'Amore fail6:
283*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail6);
284*49ef7e06SGarrett D'Amore fail5:
285*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail5);
286*49ef7e06SGarrett D'Amore fail4:
287*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail4);
288*49ef7e06SGarrett D'Amore fail3:
289*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail3);
290*49ef7e06SGarrett D'Amore fail2:
291*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
292*49ef7e06SGarrett D'Amore fail1:
293*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
294*49ef7e06SGarrett D'Amore 
295*49ef7e06SGarrett D'Amore 	return (rc);
296*49ef7e06SGarrett D'Amore }
297*49ef7e06SGarrett D'Amore 
298*49ef7e06SGarrett D'Amore 	__checkReturn	efx_rc_t
siena_nic_reset(__in efx_nic_t * enp)299*49ef7e06SGarrett D'Amore siena_nic_reset(
300*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp)
301*49ef7e06SGarrett D'Amore {
302*49ef7e06SGarrett D'Amore 	efx_mcdi_req_t req;
303*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
304*49ef7e06SGarrett D'Amore 
305*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
306*49ef7e06SGarrett D'Amore 
307*49ef7e06SGarrett D'Amore 	/* siena_nic_reset() is called to recover from BADASSERT failures. */
308*49ef7e06SGarrett D'Amore 	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
309*49ef7e06SGarrett D'Amore 		goto fail1;
310*49ef7e06SGarrett D'Amore 	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
311*49ef7e06SGarrett D'Amore 		goto fail2;
312*49ef7e06SGarrett D'Amore 
313*49ef7e06SGarrett D'Amore 	/*
314*49ef7e06SGarrett D'Amore 	 * Bug24908: ENTITY_RESET_IN_LEN is non zero but zero may be supplied
315*49ef7e06SGarrett D'Amore 	 * for backwards compatibility with PORT_RESET_IN_LEN.
316*49ef7e06SGarrett D'Amore 	 */
317*49ef7e06SGarrett D'Amore 	EFX_STATIC_ASSERT(MC_CMD_ENTITY_RESET_OUT_LEN == 0);
318*49ef7e06SGarrett D'Amore 
319*49ef7e06SGarrett D'Amore 	req.emr_cmd = MC_CMD_ENTITY_RESET;
320*49ef7e06SGarrett D'Amore 	req.emr_in_buf = NULL;
321*49ef7e06SGarrett D'Amore 	req.emr_in_length = 0;
322*49ef7e06SGarrett D'Amore 	req.emr_out_buf = NULL;
323*49ef7e06SGarrett D'Amore 	req.emr_out_length = 0;
324*49ef7e06SGarrett D'Amore 
325*49ef7e06SGarrett D'Amore 	efx_mcdi_execute(enp, &req);
326*49ef7e06SGarrett D'Amore 
327*49ef7e06SGarrett D'Amore 	if (req.emr_rc != 0) {
328*49ef7e06SGarrett D'Amore 		rc = req.emr_rc;
329*49ef7e06SGarrett D'Amore 		goto fail3;
330*49ef7e06SGarrett D'Amore 	}
331*49ef7e06SGarrett D'Amore 
332*49ef7e06SGarrett D'Amore 	return (0);
333*49ef7e06SGarrett D'Amore 
334*49ef7e06SGarrett D'Amore fail3:
335*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail3);
336*49ef7e06SGarrett D'Amore fail2:
337*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
338*49ef7e06SGarrett D'Amore fail1:
339*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
340*49ef7e06SGarrett D'Amore 
341*49ef7e06SGarrett D'Amore 	return (0);
342*49ef7e06SGarrett D'Amore }
343*49ef7e06SGarrett D'Amore 
344*49ef7e06SGarrett D'Amore static			void
siena_nic_rx_cfg(__in efx_nic_t * enp)345*49ef7e06SGarrett D'Amore siena_nic_rx_cfg(
346*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp)
347*49ef7e06SGarrett D'Amore {
348*49ef7e06SGarrett D'Amore 	efx_oword_t oword;
349*49ef7e06SGarrett D'Amore 
350*49ef7e06SGarrett D'Amore 	/*
351*49ef7e06SGarrett D'Amore 	 * RX_INGR_EN is always enabled on Siena, because we rely on
352*49ef7e06SGarrett D'Amore 	 * the RX parser to be resiliant to missing SOP/EOP.
353*49ef7e06SGarrett D'Amore 	 */
354*49ef7e06SGarrett D'Amore 	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
355*49ef7e06SGarrett D'Amore 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
356*49ef7e06SGarrett D'Amore 	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
357*49ef7e06SGarrett D'Amore 
358*49ef7e06SGarrett D'Amore 	/* Disable parsing of additional 802.1Q in Q packets */
359*49ef7e06SGarrett D'Amore 	EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
360*49ef7e06SGarrett D'Amore 	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
361*49ef7e06SGarrett D'Amore 	EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
362*49ef7e06SGarrett D'Amore }
363*49ef7e06SGarrett D'Amore 
364*49ef7e06SGarrett D'Amore static			void
siena_nic_usrev_dis(__in efx_nic_t * enp)365*49ef7e06SGarrett D'Amore siena_nic_usrev_dis(
366*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp)
367*49ef7e06SGarrett D'Amore {
368*49ef7e06SGarrett D'Amore 	efx_oword_t	oword;
369*49ef7e06SGarrett D'Amore 
370*49ef7e06SGarrett D'Amore 	EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
371*49ef7e06SGarrett D'Amore 	EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
372*49ef7e06SGarrett D'Amore }
373*49ef7e06SGarrett D'Amore 
374*49ef7e06SGarrett D'Amore 	__checkReturn	efx_rc_t
siena_nic_init(__in efx_nic_t * enp)375*49ef7e06SGarrett D'Amore siena_nic_init(
376*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp)
377*49ef7e06SGarrett D'Amore {
378*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
379*49ef7e06SGarrett D'Amore 
380*49ef7e06SGarrett D'Amore 	EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
381*49ef7e06SGarrett D'Amore 
382*49ef7e06SGarrett D'Amore 	/* Enable reporting of some events (e.g. link change) */
383*49ef7e06SGarrett D'Amore 	if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
384*49ef7e06SGarrett D'Amore 		goto fail1;
385*49ef7e06SGarrett D'Amore 
386*49ef7e06SGarrett D'Amore 	siena_sram_init(enp);
387*49ef7e06SGarrett D'Amore 
388*49ef7e06SGarrett D'Amore 	/* Configure Siena's RX block */
389*49ef7e06SGarrett D'Amore 	siena_nic_rx_cfg(enp);
390*49ef7e06SGarrett D'Amore 
391*49ef7e06SGarrett D'Amore 	/* Disable USR_EVents for now */
392*49ef7e06SGarrett D'Amore 	siena_nic_usrev_dis(enp);
393*49ef7e06SGarrett D'Amore 
394*49ef7e06SGarrett D'Amore 	/* bug17057: Ensure set_link is called */
395*49ef7e06SGarrett D'Amore 	if ((rc = siena_phy_reconfigure(enp)) != 0)
396*49ef7e06SGarrett D'Amore 		goto fail2;
397*49ef7e06SGarrett D'Amore 
398*49ef7e06SGarrett D'Amore 	enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V1;
399*49ef7e06SGarrett D'Amore 
400*49ef7e06SGarrett D'Amore 	return (0);
401*49ef7e06SGarrett D'Amore 
402*49ef7e06SGarrett D'Amore fail2:
403*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
404*49ef7e06SGarrett D'Amore fail1:
405*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
406*49ef7e06SGarrett D'Amore 
407*49ef7e06SGarrett D'Amore 	return (rc);
408*49ef7e06SGarrett D'Amore }
409*49ef7e06SGarrett D'Amore 
410*49ef7e06SGarrett D'Amore 			void
siena_nic_fini(__in efx_nic_t * enp)411*49ef7e06SGarrett D'Amore siena_nic_fini(
412*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp)
413*49ef7e06SGarrett D'Amore {
414*49ef7e06SGarrett D'Amore 	_NOTE(ARGUNUSED(enp))
415*49ef7e06SGarrett D'Amore }
416*49ef7e06SGarrett D'Amore 
417*49ef7e06SGarrett D'Amore 			void
siena_nic_unprobe(__in efx_nic_t * enp)418*49ef7e06SGarrett D'Amore siena_nic_unprobe(
419*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp)
420*49ef7e06SGarrett D'Amore {
421*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MON_STATS
422*49ef7e06SGarrett D'Amore 	mcdi_mon_cfg_free(enp);
423*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_MON_STATS */
424*49ef7e06SGarrett D'Amore 	(void) efx_mcdi_drv_attach(enp, B_FALSE);
425*49ef7e06SGarrett D'Amore }
426*49ef7e06SGarrett D'Amore 
427*49ef7e06SGarrett D'Amore #if EFSYS_OPT_DIAG
428*49ef7e06SGarrett D'Amore 
429*49ef7e06SGarrett D'Amore static efx_register_set_t __siena_registers[] = {
430*49ef7e06SGarrett D'Amore 	{ FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
431*49ef7e06SGarrett D'Amore 	{ FR_CZ_USR_EV_CFG_OFST, 0, 1 },
432*49ef7e06SGarrett D'Amore 	{ FR_AZ_RX_CFG_REG_OFST, 0, 1 },
433*49ef7e06SGarrett D'Amore 	{ FR_AZ_TX_CFG_REG_OFST, 0, 1 },
434*49ef7e06SGarrett D'Amore 	{ FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
435*49ef7e06SGarrett D'Amore 	{ FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
436*49ef7e06SGarrett D'Amore 	{ FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
437*49ef7e06SGarrett D'Amore 	{ FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
438*49ef7e06SGarrett D'Amore 	{ FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
439*49ef7e06SGarrett D'Amore 	{ FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
440*49ef7e06SGarrett D'Amore 	{ FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
441*49ef7e06SGarrett D'Amore 	{ FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
442*49ef7e06SGarrett D'Amore 	{ FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
443*49ef7e06SGarrett D'Amore };
444*49ef7e06SGarrett D'Amore 
445*49ef7e06SGarrett D'Amore static const uint32_t __siena_register_masks[] = {
446*49ef7e06SGarrett D'Amore 	0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
447*49ef7e06SGarrett D'Amore 	0x000103FF, 0x00000000, 0x00000000, 0x00000000,
448*49ef7e06SGarrett D'Amore 	0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
449*49ef7e06SGarrett D'Amore 	0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
450*49ef7e06SGarrett D'Amore 	0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
451*49ef7e06SGarrett D'Amore 	0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
452*49ef7e06SGarrett D'Amore 	0x00000003, 0x00000000, 0x00000000, 0x00000000,
453*49ef7e06SGarrett D'Amore 	0x000003FF, 0x00000000, 0x00000000, 0x00000000,
454*49ef7e06SGarrett D'Amore 	0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
455*49ef7e06SGarrett D'Amore 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
456*49ef7e06SGarrett D'Amore 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
457*49ef7e06SGarrett D'Amore 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
458*49ef7e06SGarrett D'Amore 	0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
459*49ef7e06SGarrett D'Amore };
460*49ef7e06SGarrett D'Amore 
461*49ef7e06SGarrett D'Amore static efx_register_set_t __siena_tables[] = {
462*49ef7e06SGarrett D'Amore 	{ FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
463*49ef7e06SGarrett D'Amore 	    FR_AZ_RX_FILTER_TBL0_ROWS },
464*49ef7e06SGarrett D'Amore 	{ FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
465*49ef7e06SGarrett D'Amore 	    FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
466*49ef7e06SGarrett D'Amore 	{ FR_AZ_RX_DESC_PTR_TBL_OFST,
467*49ef7e06SGarrett D'Amore 	    FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
468*49ef7e06SGarrett D'Amore 	{ FR_AZ_TX_DESC_PTR_TBL_OFST,
469*49ef7e06SGarrett D'Amore 	    FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
470*49ef7e06SGarrett D'Amore 	{ FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
471*49ef7e06SGarrett D'Amore 	{ FR_CZ_TX_FILTER_TBL0_OFST,
472*49ef7e06SGarrett D'Amore 	    FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
473*49ef7e06SGarrett D'Amore 	{ FR_CZ_TX_MAC_FILTER_TBL0_OFST,
474*49ef7e06SGarrett D'Amore 	    FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
475*49ef7e06SGarrett D'Amore };
476*49ef7e06SGarrett D'Amore 
477*49ef7e06SGarrett D'Amore static const uint32_t __siena_table_masks[] = {
478*49ef7e06SGarrett D'Amore 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
479*49ef7e06SGarrett D'Amore 	0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
480*49ef7e06SGarrett D'Amore 	0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
481*49ef7e06SGarrett D'Amore 	0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
482*49ef7e06SGarrett D'Amore 	0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
483*49ef7e06SGarrett D'Amore 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
484*49ef7e06SGarrett D'Amore 	0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
485*49ef7e06SGarrett D'Amore };
486*49ef7e06SGarrett D'Amore 
487*49ef7e06SGarrett D'Amore 	__checkReturn	efx_rc_t
siena_nic_register_test(__in efx_nic_t * enp)488*49ef7e06SGarrett D'Amore siena_nic_register_test(
489*49ef7e06SGarrett D'Amore 	__in		efx_nic_t *enp)
490*49ef7e06SGarrett D'Amore {
491*49ef7e06SGarrett D'Amore 	efx_register_set_t *rsp;
492*49ef7e06SGarrett D'Amore 	const uint32_t *dwordp;
493*49ef7e06SGarrett D'Amore 	unsigned int nitems;
494*49ef7e06SGarrett D'Amore 	unsigned int count;
495*49ef7e06SGarrett D'Amore 	efx_rc_t rc;
496*49ef7e06SGarrett D'Amore 
497*49ef7e06SGarrett D'Amore 	/* Fill out the register mask entries */
498*49ef7e06SGarrett D'Amore 	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
499*49ef7e06SGarrett D'Amore 		    == EFX_ARRAY_SIZE(__siena_registers) * 4);
500*49ef7e06SGarrett D'Amore 
501*49ef7e06SGarrett D'Amore 	nitems = EFX_ARRAY_SIZE(__siena_registers);
502*49ef7e06SGarrett D'Amore 	dwordp = __siena_register_masks;
503*49ef7e06SGarrett D'Amore 	for (count = 0; count < nitems; ++count) {
504*49ef7e06SGarrett D'Amore 		rsp = __siena_registers + count;
505*49ef7e06SGarrett D'Amore 		rsp->mask.eo_u32[0] = *dwordp++;
506*49ef7e06SGarrett D'Amore 		rsp->mask.eo_u32[1] = *dwordp++;
507*49ef7e06SGarrett D'Amore 		rsp->mask.eo_u32[2] = *dwordp++;
508*49ef7e06SGarrett D'Amore 		rsp->mask.eo_u32[3] = *dwordp++;
509*49ef7e06SGarrett D'Amore 	}
510*49ef7e06SGarrett D'Amore 
511*49ef7e06SGarrett D'Amore 	/* Fill out the register table entries */
512*49ef7e06SGarrett D'Amore 	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
513*49ef7e06SGarrett D'Amore 		    == EFX_ARRAY_SIZE(__siena_tables) * 4);
514*49ef7e06SGarrett D'Amore 
515*49ef7e06SGarrett D'Amore 	nitems = EFX_ARRAY_SIZE(__siena_tables);
516*49ef7e06SGarrett D'Amore 	dwordp = __siena_table_masks;
517*49ef7e06SGarrett D'Amore 	for (count = 0; count < nitems; ++count) {
518*49ef7e06SGarrett D'Amore 		rsp = __siena_tables + count;
519*49ef7e06SGarrett D'Amore 		rsp->mask.eo_u32[0] = *dwordp++;
520*49ef7e06SGarrett D'Amore 		rsp->mask.eo_u32[1] = *dwordp++;
521*49ef7e06SGarrett D'Amore 		rsp->mask.eo_u32[2] = *dwordp++;
522*49ef7e06SGarrett D'Amore 		rsp->mask.eo_u32[3] = *dwordp++;
523*49ef7e06SGarrett D'Amore 	}
524*49ef7e06SGarrett D'Amore 
525*49ef7e06SGarrett D'Amore 	if ((rc = efx_nic_test_registers(enp, __siena_registers,
526*49ef7e06SGarrett D'Amore 	    EFX_ARRAY_SIZE(__siena_registers))) != 0)
527*49ef7e06SGarrett D'Amore 		goto fail1;
528*49ef7e06SGarrett D'Amore 
529*49ef7e06SGarrett D'Amore 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
530*49ef7e06SGarrett D'Amore 	    EFX_PATTERN_BYTE_ALTERNATE,
531*49ef7e06SGarrett D'Amore 	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
532*49ef7e06SGarrett D'Amore 		goto fail2;
533*49ef7e06SGarrett D'Amore 
534*49ef7e06SGarrett D'Amore 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
535*49ef7e06SGarrett D'Amore 	    EFX_PATTERN_BYTE_CHANGING,
536*49ef7e06SGarrett D'Amore 	    EFX_ARRAY_SIZE(__siena_tables))) != 0)
537*49ef7e06SGarrett D'Amore 		goto fail3;
538*49ef7e06SGarrett D'Amore 
539*49ef7e06SGarrett D'Amore 	if ((rc = efx_nic_test_tables(enp, __siena_tables,
540*49ef7e06SGarrett D'Amore 	    EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
541*49ef7e06SGarrett D'Amore 		goto fail4;
542*49ef7e06SGarrett D'Amore 
543*49ef7e06SGarrett D'Amore 	return (0);
544*49ef7e06SGarrett D'Amore 
545*49ef7e06SGarrett D'Amore fail4:
546*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail4);
547*49ef7e06SGarrett D'Amore fail3:
548*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail3);
549*49ef7e06SGarrett D'Amore fail2:
550*49ef7e06SGarrett D'Amore 	EFSYS_PROBE(fail2);
551*49ef7e06SGarrett D'Amore fail1:
552*49ef7e06SGarrett D'Amore 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
553*49ef7e06SGarrett D'Amore 
554*49ef7e06SGarrett D'Amore 	return (rc);
555*49ef7e06SGarrett D'Amore }
556*49ef7e06SGarrett D'Amore 
557*49ef7e06SGarrett D'Amore #endif	/* EFSYS_OPT_DIAG */
558*49ef7e06SGarrett D'Amore 
559*49ef7e06SGarrett D'Amore #endif	/* EFSYS_OPT_SIENA */
560