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