1*49ef7e06SGarrett D'Amore /*
2*49ef7e06SGarrett D'Amore * Copyright (c) 2012-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 #if EFSYS_OPT_MON_MCDI
34*49ef7e06SGarrett D'Amore #include "mcdi_mon.h"
35*49ef7e06SGarrett D'Amore #endif
36*49ef7e06SGarrett D'Amore
37*49ef7e06SGarrett D'Amore #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
38*49ef7e06SGarrett D'Amore
39*49ef7e06SGarrett D'Amore #include "ef10_tlv_layout.h"
40*49ef7e06SGarrett D'Amore
41*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_mcdi_get_port_assignment(__in efx_nic_t * enp,__out uint32_t * portp)42*49ef7e06SGarrett D'Amore efx_mcdi_get_port_assignment(
43*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
44*49ef7e06SGarrett D'Amore __out uint32_t *portp)
45*49ef7e06SGarrett D'Amore {
46*49ef7e06SGarrett D'Amore efx_mcdi_req_t req;
47*49ef7e06SGarrett D'Amore uint8_t payload[MAX(MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN,
48*49ef7e06SGarrett D'Amore MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN)];
49*49ef7e06SGarrett D'Amore efx_rc_t rc;
50*49ef7e06SGarrett D'Amore
51*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
52*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
53*49ef7e06SGarrett D'Amore
54*49ef7e06SGarrett D'Amore (void) memset(payload, 0, sizeof (payload));
55*49ef7e06SGarrett D'Amore req.emr_cmd = MC_CMD_GET_PORT_ASSIGNMENT;
56*49ef7e06SGarrett D'Amore req.emr_in_buf = payload;
57*49ef7e06SGarrett D'Amore req.emr_in_length = MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN;
58*49ef7e06SGarrett D'Amore req.emr_out_buf = payload;
59*49ef7e06SGarrett D'Amore req.emr_out_length = MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN;
60*49ef7e06SGarrett D'Amore
61*49ef7e06SGarrett D'Amore efx_mcdi_execute(enp, &req);
62*49ef7e06SGarrett D'Amore
63*49ef7e06SGarrett D'Amore if (req.emr_rc != 0) {
64*49ef7e06SGarrett D'Amore rc = req.emr_rc;
65*49ef7e06SGarrett D'Amore goto fail1;
66*49ef7e06SGarrett D'Amore }
67*49ef7e06SGarrett D'Amore
68*49ef7e06SGarrett D'Amore if (req.emr_out_length_used < MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN) {
69*49ef7e06SGarrett D'Amore rc = EMSGSIZE;
70*49ef7e06SGarrett D'Amore goto fail2;
71*49ef7e06SGarrett D'Amore }
72*49ef7e06SGarrett D'Amore
73*49ef7e06SGarrett D'Amore *portp = MCDI_OUT_DWORD(req, GET_PORT_ASSIGNMENT_OUT_PORT);
74*49ef7e06SGarrett D'Amore
75*49ef7e06SGarrett D'Amore return (0);
76*49ef7e06SGarrett D'Amore
77*49ef7e06SGarrett D'Amore fail2:
78*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
79*49ef7e06SGarrett D'Amore fail1:
80*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
81*49ef7e06SGarrett D'Amore
82*49ef7e06SGarrett D'Amore return (rc);
83*49ef7e06SGarrett D'Amore }
84*49ef7e06SGarrett D'Amore
85*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_mcdi_get_port_modes(__in efx_nic_t * enp,__out uint32_t * modesp)86*49ef7e06SGarrett D'Amore efx_mcdi_get_port_modes(
87*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
88*49ef7e06SGarrett D'Amore __out uint32_t *modesp)
89*49ef7e06SGarrett D'Amore {
90*49ef7e06SGarrett D'Amore efx_mcdi_req_t req;
91*49ef7e06SGarrett D'Amore uint8_t payload[MAX(MC_CMD_GET_PORT_MODES_IN_LEN,
92*49ef7e06SGarrett D'Amore MC_CMD_GET_PORT_MODES_OUT_LEN)];
93*49ef7e06SGarrett D'Amore efx_rc_t rc;
94*49ef7e06SGarrett D'Amore
95*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
96*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
97*49ef7e06SGarrett D'Amore
98*49ef7e06SGarrett D'Amore (void) memset(payload, 0, sizeof (payload));
99*49ef7e06SGarrett D'Amore req.emr_cmd = MC_CMD_GET_PORT_MODES;
100*49ef7e06SGarrett D'Amore req.emr_in_buf = payload;
101*49ef7e06SGarrett D'Amore req.emr_in_length = MC_CMD_GET_PORT_MODES_IN_LEN;
102*49ef7e06SGarrett D'Amore req.emr_out_buf = payload;
103*49ef7e06SGarrett D'Amore req.emr_out_length = MC_CMD_GET_PORT_MODES_OUT_LEN;
104*49ef7e06SGarrett D'Amore
105*49ef7e06SGarrett D'Amore efx_mcdi_execute(enp, &req);
106*49ef7e06SGarrett D'Amore
107*49ef7e06SGarrett D'Amore if (req.emr_rc != 0) {
108*49ef7e06SGarrett D'Amore rc = req.emr_rc;
109*49ef7e06SGarrett D'Amore goto fail1;
110*49ef7e06SGarrett D'Amore }
111*49ef7e06SGarrett D'Amore
112*49ef7e06SGarrett D'Amore /*
113*49ef7e06SGarrett D'Amore * Require only Modes and DefaultMode fields.
114*49ef7e06SGarrett D'Amore * (CurrentMode field was added for Medford)
115*49ef7e06SGarrett D'Amore */
116*49ef7e06SGarrett D'Amore if (req.emr_out_length_used <
117*49ef7e06SGarrett D'Amore MC_CMD_GET_PORT_MODES_OUT_CURRENT_MODE_OFST) {
118*49ef7e06SGarrett D'Amore rc = EMSGSIZE;
119*49ef7e06SGarrett D'Amore goto fail2;
120*49ef7e06SGarrett D'Amore }
121*49ef7e06SGarrett D'Amore
122*49ef7e06SGarrett D'Amore *modesp = MCDI_OUT_DWORD(req, GET_PORT_MODES_OUT_MODES);
123*49ef7e06SGarrett D'Amore
124*49ef7e06SGarrett D'Amore return (0);
125*49ef7e06SGarrett D'Amore
126*49ef7e06SGarrett D'Amore fail2:
127*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
128*49ef7e06SGarrett D'Amore fail1:
129*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
130*49ef7e06SGarrett D'Amore
131*49ef7e06SGarrett D'Amore return (rc);
132*49ef7e06SGarrett D'Amore }
133*49ef7e06SGarrett D'Amore
134*49ef7e06SGarrett D'Amore
135*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
efx_mcdi_vadaptor_alloc(__in efx_nic_t * enp,__in uint32_t port_id)136*49ef7e06SGarrett D'Amore efx_mcdi_vadaptor_alloc(
137*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
138*49ef7e06SGarrett D'Amore __in uint32_t port_id)
139*49ef7e06SGarrett D'Amore {
140*49ef7e06SGarrett D'Amore efx_mcdi_req_t req;
141*49ef7e06SGarrett D'Amore uint8_t payload[MAX(MC_CMD_VADAPTOR_ALLOC_IN_LEN,
142*49ef7e06SGarrett D'Amore MC_CMD_VADAPTOR_ALLOC_OUT_LEN)];
143*49ef7e06SGarrett D'Amore efx_rc_t rc;
144*49ef7e06SGarrett D'Amore
145*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_vport_id, ==, EVB_PORT_ID_NULL);
146*49ef7e06SGarrett D'Amore
147*49ef7e06SGarrett D'Amore (void) memset(payload, 0, sizeof (payload));
148*49ef7e06SGarrett D'Amore req.emr_cmd = MC_CMD_VADAPTOR_ALLOC;
149*49ef7e06SGarrett D'Amore req.emr_in_buf = payload;
150*49ef7e06SGarrett D'Amore req.emr_in_length = MC_CMD_VADAPTOR_ALLOC_IN_LEN;
151*49ef7e06SGarrett D'Amore req.emr_out_buf = payload;
152*49ef7e06SGarrett D'Amore req.emr_out_length = MC_CMD_VADAPTOR_ALLOC_OUT_LEN;
153*49ef7e06SGarrett D'Amore
154*49ef7e06SGarrett D'Amore MCDI_IN_SET_DWORD(req, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
155*49ef7e06SGarrett D'Amore MCDI_IN_POPULATE_DWORD_1(req, VADAPTOR_ALLOC_IN_FLAGS,
156*49ef7e06SGarrett D'Amore VADAPTOR_ALLOC_IN_FLAG_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED,
157*49ef7e06SGarrett D'Amore enp->en_nic_cfg.enc_allow_set_mac_with_installed_filters ? 1 : 0);
158*49ef7e06SGarrett D'Amore
159*49ef7e06SGarrett D'Amore efx_mcdi_execute(enp, &req);
160*49ef7e06SGarrett D'Amore
161*49ef7e06SGarrett D'Amore if (req.emr_rc != 0) {
162*49ef7e06SGarrett D'Amore rc = req.emr_rc;
163*49ef7e06SGarrett D'Amore goto fail1;
164*49ef7e06SGarrett D'Amore }
165*49ef7e06SGarrett D'Amore
166*49ef7e06SGarrett D'Amore return (0);
167*49ef7e06SGarrett D'Amore
168*49ef7e06SGarrett D'Amore fail1:
169*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
170*49ef7e06SGarrett D'Amore
171*49ef7e06SGarrett D'Amore return (rc);
172*49ef7e06SGarrett D'Amore }
173*49ef7e06SGarrett D'Amore
174*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
efx_mcdi_vadaptor_free(__in efx_nic_t * enp,__in uint32_t port_id)175*49ef7e06SGarrett D'Amore efx_mcdi_vadaptor_free(
176*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
177*49ef7e06SGarrett D'Amore __in uint32_t port_id)
178*49ef7e06SGarrett D'Amore {
179*49ef7e06SGarrett D'Amore efx_mcdi_req_t req;
180*49ef7e06SGarrett D'Amore uint8_t payload[MAX(MC_CMD_VADAPTOR_FREE_IN_LEN,
181*49ef7e06SGarrett D'Amore MC_CMD_VADAPTOR_FREE_OUT_LEN)];
182*49ef7e06SGarrett D'Amore efx_rc_t rc;
183*49ef7e06SGarrett D'Amore
184*49ef7e06SGarrett D'Amore (void) memset(payload, 0, sizeof (payload));
185*49ef7e06SGarrett D'Amore req.emr_cmd = MC_CMD_VADAPTOR_FREE;
186*49ef7e06SGarrett D'Amore req.emr_in_buf = payload;
187*49ef7e06SGarrett D'Amore req.emr_in_length = MC_CMD_VADAPTOR_FREE_IN_LEN;
188*49ef7e06SGarrett D'Amore req.emr_out_buf = payload;
189*49ef7e06SGarrett D'Amore req.emr_out_length = MC_CMD_VADAPTOR_FREE_OUT_LEN;
190*49ef7e06SGarrett D'Amore
191*49ef7e06SGarrett D'Amore MCDI_IN_SET_DWORD(req, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id);
192*49ef7e06SGarrett D'Amore
193*49ef7e06SGarrett D'Amore efx_mcdi_execute(enp, &req);
194*49ef7e06SGarrett D'Amore
195*49ef7e06SGarrett D'Amore if (req.emr_rc != 0) {
196*49ef7e06SGarrett D'Amore rc = req.emr_rc;
197*49ef7e06SGarrett D'Amore goto fail1;
198*49ef7e06SGarrett D'Amore }
199*49ef7e06SGarrett D'Amore
200*49ef7e06SGarrett D'Amore return (0);
201*49ef7e06SGarrett D'Amore
202*49ef7e06SGarrett D'Amore fail1:
203*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
204*49ef7e06SGarrett D'Amore
205*49ef7e06SGarrett D'Amore return (rc);
206*49ef7e06SGarrett D'Amore }
207*49ef7e06SGarrett D'Amore
208*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
209*49ef7e06SGarrett D'Amore efx_mcdi_get_mac_address_pf(
210*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
211*49ef7e06SGarrett D'Amore __out_ecount_opt(6) uint8_t mac_addrp[6])
212*49ef7e06SGarrett D'Amore {
213*49ef7e06SGarrett D'Amore efx_mcdi_req_t req;
214*49ef7e06SGarrett D'Amore uint8_t payload[MAX(MC_CMD_GET_MAC_ADDRESSES_IN_LEN,
215*49ef7e06SGarrett D'Amore MC_CMD_GET_MAC_ADDRESSES_OUT_LEN)];
216*49ef7e06SGarrett D'Amore efx_rc_t rc;
217*49ef7e06SGarrett D'Amore
218*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
219*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
220*49ef7e06SGarrett D'Amore
221*49ef7e06SGarrett D'Amore (void) memset(payload, 0, sizeof (payload));
222*49ef7e06SGarrett D'Amore req.emr_cmd = MC_CMD_GET_MAC_ADDRESSES;
223*49ef7e06SGarrett D'Amore req.emr_in_buf = payload;
224*49ef7e06SGarrett D'Amore req.emr_in_length = MC_CMD_GET_MAC_ADDRESSES_IN_LEN;
225*49ef7e06SGarrett D'Amore req.emr_out_buf = payload;
226*49ef7e06SGarrett D'Amore req.emr_out_length = MC_CMD_GET_MAC_ADDRESSES_OUT_LEN;
227*49ef7e06SGarrett D'Amore
228*49ef7e06SGarrett D'Amore efx_mcdi_execute(enp, &req);
229*49ef7e06SGarrett D'Amore
230*49ef7e06SGarrett D'Amore if (req.emr_rc != 0) {
231*49ef7e06SGarrett D'Amore rc = req.emr_rc;
232*49ef7e06SGarrett D'Amore goto fail1;
233*49ef7e06SGarrett D'Amore }
234*49ef7e06SGarrett D'Amore
235*49ef7e06SGarrett D'Amore if (req.emr_out_length_used < MC_CMD_GET_MAC_ADDRESSES_OUT_LEN) {
236*49ef7e06SGarrett D'Amore rc = EMSGSIZE;
237*49ef7e06SGarrett D'Amore goto fail2;
238*49ef7e06SGarrett D'Amore }
239*49ef7e06SGarrett D'Amore
240*49ef7e06SGarrett D'Amore if (MCDI_OUT_DWORD(req, GET_MAC_ADDRESSES_OUT_MAC_COUNT) < 1) {
241*49ef7e06SGarrett D'Amore rc = ENOENT;
242*49ef7e06SGarrett D'Amore goto fail3;
243*49ef7e06SGarrett D'Amore }
244*49ef7e06SGarrett D'Amore
245*49ef7e06SGarrett D'Amore if (mac_addrp != NULL) {
246*49ef7e06SGarrett D'Amore uint8_t *addrp;
247*49ef7e06SGarrett D'Amore
248*49ef7e06SGarrett D'Amore addrp = MCDI_OUT2(req, uint8_t,
249*49ef7e06SGarrett D'Amore GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE);
250*49ef7e06SGarrett D'Amore
251*49ef7e06SGarrett D'Amore EFX_MAC_ADDR_COPY(mac_addrp, addrp);
252*49ef7e06SGarrett D'Amore }
253*49ef7e06SGarrett D'Amore
254*49ef7e06SGarrett D'Amore return (0);
255*49ef7e06SGarrett D'Amore
256*49ef7e06SGarrett D'Amore fail3:
257*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail3);
258*49ef7e06SGarrett D'Amore fail2:
259*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
260*49ef7e06SGarrett D'Amore fail1:
261*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
262*49ef7e06SGarrett D'Amore
263*49ef7e06SGarrett D'Amore return (rc);
264*49ef7e06SGarrett D'Amore }
265*49ef7e06SGarrett D'Amore
266*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
267*49ef7e06SGarrett D'Amore efx_mcdi_get_mac_address_vf(
268*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
269*49ef7e06SGarrett D'Amore __out_ecount_opt(6) uint8_t mac_addrp[6])
270*49ef7e06SGarrett D'Amore {
271*49ef7e06SGarrett D'Amore efx_mcdi_req_t req;
272*49ef7e06SGarrett D'Amore uint8_t payload[MAX(MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN,
273*49ef7e06SGarrett D'Amore MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX)];
274*49ef7e06SGarrett D'Amore efx_rc_t rc;
275*49ef7e06SGarrett D'Amore
276*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
277*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
278*49ef7e06SGarrett D'Amore
279*49ef7e06SGarrett D'Amore (void) memset(payload, 0, sizeof (payload));
280*49ef7e06SGarrett D'Amore req.emr_cmd = MC_CMD_VPORT_GET_MAC_ADDRESSES;
281*49ef7e06SGarrett D'Amore req.emr_in_buf = payload;
282*49ef7e06SGarrett D'Amore req.emr_in_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN;
283*49ef7e06SGarrett D'Amore req.emr_out_buf = payload;
284*49ef7e06SGarrett D'Amore req.emr_out_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX;
285*49ef7e06SGarrett D'Amore
286*49ef7e06SGarrett D'Amore MCDI_IN_SET_DWORD(req, VPORT_GET_MAC_ADDRESSES_IN_VPORT_ID,
287*49ef7e06SGarrett D'Amore EVB_PORT_ID_ASSIGNED);
288*49ef7e06SGarrett D'Amore
289*49ef7e06SGarrett D'Amore efx_mcdi_execute(enp, &req);
290*49ef7e06SGarrett D'Amore
291*49ef7e06SGarrett D'Amore if (req.emr_rc != 0) {
292*49ef7e06SGarrett D'Amore rc = req.emr_rc;
293*49ef7e06SGarrett D'Amore goto fail1;
294*49ef7e06SGarrett D'Amore }
295*49ef7e06SGarrett D'Amore
296*49ef7e06SGarrett D'Amore if (req.emr_out_length_used <
297*49ef7e06SGarrett D'Amore MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMIN) {
298*49ef7e06SGarrett D'Amore rc = EMSGSIZE;
299*49ef7e06SGarrett D'Amore goto fail2;
300*49ef7e06SGarrett D'Amore }
301*49ef7e06SGarrett D'Amore
302*49ef7e06SGarrett D'Amore if (MCDI_OUT_DWORD(req,
303*49ef7e06SGarrett D'Amore VPORT_GET_MAC_ADDRESSES_OUT_MACADDR_COUNT) < 1) {
304*49ef7e06SGarrett D'Amore rc = ENOENT;
305*49ef7e06SGarrett D'Amore goto fail3;
306*49ef7e06SGarrett D'Amore }
307*49ef7e06SGarrett D'Amore
308*49ef7e06SGarrett D'Amore if (mac_addrp != NULL) {
309*49ef7e06SGarrett D'Amore uint8_t *addrp;
310*49ef7e06SGarrett D'Amore
311*49ef7e06SGarrett D'Amore addrp = MCDI_OUT2(req, uint8_t,
312*49ef7e06SGarrett D'Amore VPORT_GET_MAC_ADDRESSES_OUT_MACADDR);
313*49ef7e06SGarrett D'Amore
314*49ef7e06SGarrett D'Amore EFX_MAC_ADDR_COPY(mac_addrp, addrp);
315*49ef7e06SGarrett D'Amore }
316*49ef7e06SGarrett D'Amore
317*49ef7e06SGarrett D'Amore return (0);
318*49ef7e06SGarrett D'Amore
319*49ef7e06SGarrett D'Amore fail3:
320*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail3);
321*49ef7e06SGarrett D'Amore fail2:
322*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
323*49ef7e06SGarrett D'Amore fail1:
324*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
325*49ef7e06SGarrett D'Amore
326*49ef7e06SGarrett D'Amore return (rc);
327*49ef7e06SGarrett D'Amore }
328*49ef7e06SGarrett D'Amore
329*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_mcdi_get_clock(__in efx_nic_t * enp,__out uint32_t * sys_freqp)330*49ef7e06SGarrett D'Amore efx_mcdi_get_clock(
331*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
332*49ef7e06SGarrett D'Amore __out uint32_t *sys_freqp)
333*49ef7e06SGarrett D'Amore {
334*49ef7e06SGarrett D'Amore efx_mcdi_req_t req;
335*49ef7e06SGarrett D'Amore uint8_t payload[MAX(MC_CMD_GET_CLOCK_IN_LEN,
336*49ef7e06SGarrett D'Amore MC_CMD_GET_CLOCK_OUT_LEN)];
337*49ef7e06SGarrett D'Amore efx_rc_t rc;
338*49ef7e06SGarrett D'Amore
339*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
340*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
341*49ef7e06SGarrett D'Amore
342*49ef7e06SGarrett D'Amore (void) memset(payload, 0, sizeof (payload));
343*49ef7e06SGarrett D'Amore req.emr_cmd = MC_CMD_GET_CLOCK;
344*49ef7e06SGarrett D'Amore req.emr_in_buf = payload;
345*49ef7e06SGarrett D'Amore req.emr_in_length = MC_CMD_GET_CLOCK_IN_LEN;
346*49ef7e06SGarrett D'Amore req.emr_out_buf = payload;
347*49ef7e06SGarrett D'Amore req.emr_out_length = MC_CMD_GET_CLOCK_OUT_LEN;
348*49ef7e06SGarrett D'Amore
349*49ef7e06SGarrett D'Amore efx_mcdi_execute(enp, &req);
350*49ef7e06SGarrett D'Amore
351*49ef7e06SGarrett D'Amore if (req.emr_rc != 0) {
352*49ef7e06SGarrett D'Amore rc = req.emr_rc;
353*49ef7e06SGarrett D'Amore goto fail1;
354*49ef7e06SGarrett D'Amore }
355*49ef7e06SGarrett D'Amore
356*49ef7e06SGarrett D'Amore if (req.emr_out_length_used < MC_CMD_GET_CLOCK_OUT_LEN) {
357*49ef7e06SGarrett D'Amore rc = EMSGSIZE;
358*49ef7e06SGarrett D'Amore goto fail2;
359*49ef7e06SGarrett D'Amore }
360*49ef7e06SGarrett D'Amore
361*49ef7e06SGarrett D'Amore *sys_freqp = MCDI_OUT_DWORD(req, GET_CLOCK_OUT_SYS_FREQ);
362*49ef7e06SGarrett D'Amore if (*sys_freqp == 0) {
363*49ef7e06SGarrett D'Amore rc = EINVAL;
364*49ef7e06SGarrett D'Amore goto fail3;
365*49ef7e06SGarrett D'Amore }
366*49ef7e06SGarrett D'Amore
367*49ef7e06SGarrett D'Amore return (0);
368*49ef7e06SGarrett D'Amore
369*49ef7e06SGarrett D'Amore fail3:
370*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail3);
371*49ef7e06SGarrett D'Amore fail2:
372*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
373*49ef7e06SGarrett D'Amore fail1:
374*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
375*49ef7e06SGarrett D'Amore
376*49ef7e06SGarrett D'Amore return (rc);
377*49ef7e06SGarrett D'Amore }
378*49ef7e06SGarrett D'Amore
379*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
efx_mcdi_get_vector_cfg(__in efx_nic_t * enp,__out_opt uint32_t * vec_basep,__out_opt uint32_t * pf_nvecp,__out_opt uint32_t * vf_nvecp)380*49ef7e06SGarrett D'Amore efx_mcdi_get_vector_cfg(
381*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
382*49ef7e06SGarrett D'Amore __out_opt uint32_t *vec_basep,
383*49ef7e06SGarrett D'Amore __out_opt uint32_t *pf_nvecp,
384*49ef7e06SGarrett D'Amore __out_opt uint32_t *vf_nvecp)
385*49ef7e06SGarrett D'Amore {
386*49ef7e06SGarrett D'Amore efx_mcdi_req_t req;
387*49ef7e06SGarrett D'Amore uint8_t payload[MAX(MC_CMD_GET_VECTOR_CFG_IN_LEN,
388*49ef7e06SGarrett D'Amore MC_CMD_GET_VECTOR_CFG_OUT_LEN)];
389*49ef7e06SGarrett D'Amore efx_rc_t rc;
390*49ef7e06SGarrett D'Amore
391*49ef7e06SGarrett D'Amore (void) memset(payload, 0, sizeof (payload));
392*49ef7e06SGarrett D'Amore req.emr_cmd = MC_CMD_GET_VECTOR_CFG;
393*49ef7e06SGarrett D'Amore req.emr_in_buf = payload;
394*49ef7e06SGarrett D'Amore req.emr_in_length = MC_CMD_GET_VECTOR_CFG_IN_LEN;
395*49ef7e06SGarrett D'Amore req.emr_out_buf = payload;
396*49ef7e06SGarrett D'Amore req.emr_out_length = MC_CMD_GET_VECTOR_CFG_OUT_LEN;
397*49ef7e06SGarrett D'Amore
398*49ef7e06SGarrett D'Amore efx_mcdi_execute(enp, &req);
399*49ef7e06SGarrett D'Amore
400*49ef7e06SGarrett D'Amore if (req.emr_rc != 0) {
401*49ef7e06SGarrett D'Amore rc = req.emr_rc;
402*49ef7e06SGarrett D'Amore goto fail1;
403*49ef7e06SGarrett D'Amore }
404*49ef7e06SGarrett D'Amore
405*49ef7e06SGarrett D'Amore if (req.emr_out_length_used < MC_CMD_GET_VECTOR_CFG_OUT_LEN) {
406*49ef7e06SGarrett D'Amore rc = EMSGSIZE;
407*49ef7e06SGarrett D'Amore goto fail2;
408*49ef7e06SGarrett D'Amore }
409*49ef7e06SGarrett D'Amore
410*49ef7e06SGarrett D'Amore if (vec_basep != NULL)
411*49ef7e06SGarrett D'Amore *vec_basep = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VEC_BASE);
412*49ef7e06SGarrett D'Amore if (pf_nvecp != NULL)
413*49ef7e06SGarrett D'Amore *pf_nvecp = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VECS_PER_PF);
414*49ef7e06SGarrett D'Amore if (vf_nvecp != NULL)
415*49ef7e06SGarrett D'Amore *vf_nvecp = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VECS_PER_VF);
416*49ef7e06SGarrett D'Amore
417*49ef7e06SGarrett D'Amore return (0);
418*49ef7e06SGarrett D'Amore
419*49ef7e06SGarrett D'Amore fail2:
420*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
421*49ef7e06SGarrett D'Amore fail1:
422*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
423*49ef7e06SGarrett D'Amore
424*49ef7e06SGarrett D'Amore return (rc);
425*49ef7e06SGarrett D'Amore }
426*49ef7e06SGarrett D'Amore
427*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
efx_mcdi_get_capabilities(__in efx_nic_t * enp,__out uint32_t * flagsp,__out uint32_t * flags2p)428*49ef7e06SGarrett D'Amore efx_mcdi_get_capabilities(
429*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
430*49ef7e06SGarrett D'Amore __out uint32_t *flagsp,
431*49ef7e06SGarrett D'Amore __out uint32_t *flags2p)
432*49ef7e06SGarrett D'Amore {
433*49ef7e06SGarrett D'Amore efx_mcdi_req_t req;
434*49ef7e06SGarrett D'Amore uint8_t payload[MAX(MC_CMD_GET_CAPABILITIES_IN_LEN,
435*49ef7e06SGarrett D'Amore MC_CMD_GET_CAPABILITIES_V2_OUT_LEN)];
436*49ef7e06SGarrett D'Amore efx_rc_t rc;
437*49ef7e06SGarrett D'Amore
438*49ef7e06SGarrett D'Amore (void) memset(payload, 0, sizeof (payload));
439*49ef7e06SGarrett D'Amore req.emr_cmd = MC_CMD_GET_CAPABILITIES;
440*49ef7e06SGarrett D'Amore req.emr_in_buf = payload;
441*49ef7e06SGarrett D'Amore req.emr_in_length = MC_CMD_GET_CAPABILITIES_IN_LEN;
442*49ef7e06SGarrett D'Amore req.emr_out_buf = payload;
443*49ef7e06SGarrett D'Amore req.emr_out_length = MC_CMD_GET_CAPABILITIES_V2_OUT_LEN;
444*49ef7e06SGarrett D'Amore
445*49ef7e06SGarrett D'Amore efx_mcdi_execute(enp, &req);
446*49ef7e06SGarrett D'Amore
447*49ef7e06SGarrett D'Amore if (req.emr_rc != 0) {
448*49ef7e06SGarrett D'Amore rc = req.emr_rc;
449*49ef7e06SGarrett D'Amore goto fail1;
450*49ef7e06SGarrett D'Amore }
451*49ef7e06SGarrett D'Amore
452*49ef7e06SGarrett D'Amore if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_OUT_LEN) {
453*49ef7e06SGarrett D'Amore rc = EMSGSIZE;
454*49ef7e06SGarrett D'Amore goto fail2;
455*49ef7e06SGarrett D'Amore }
456*49ef7e06SGarrett D'Amore
457*49ef7e06SGarrett D'Amore *flagsp = MCDI_OUT_DWORD(req, GET_CAPABILITIES_OUT_FLAGS1);
458*49ef7e06SGarrett D'Amore
459*49ef7e06SGarrett D'Amore if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_V2_OUT_LEN)
460*49ef7e06SGarrett D'Amore *flags2p = 0;
461*49ef7e06SGarrett D'Amore else
462*49ef7e06SGarrett D'Amore *flags2p = MCDI_OUT_DWORD(req, GET_CAPABILITIES_V2_OUT_FLAGS2);
463*49ef7e06SGarrett D'Amore
464*49ef7e06SGarrett D'Amore return (0);
465*49ef7e06SGarrett D'Amore
466*49ef7e06SGarrett D'Amore fail2:
467*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
468*49ef7e06SGarrett D'Amore fail1:
469*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
470*49ef7e06SGarrett D'Amore
471*49ef7e06SGarrett D'Amore return (rc);
472*49ef7e06SGarrett D'Amore }
473*49ef7e06SGarrett D'Amore
474*49ef7e06SGarrett D'Amore
475*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
efx_mcdi_alloc_vis(__in efx_nic_t * enp,__in uint32_t min_vi_count,__in uint32_t max_vi_count,__out uint32_t * vi_basep,__out uint32_t * vi_countp,__out uint32_t * vi_shiftp)476*49ef7e06SGarrett D'Amore efx_mcdi_alloc_vis(
477*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
478*49ef7e06SGarrett D'Amore __in uint32_t min_vi_count,
479*49ef7e06SGarrett D'Amore __in uint32_t max_vi_count,
480*49ef7e06SGarrett D'Amore __out uint32_t *vi_basep,
481*49ef7e06SGarrett D'Amore __out uint32_t *vi_countp,
482*49ef7e06SGarrett D'Amore __out uint32_t *vi_shiftp)
483*49ef7e06SGarrett D'Amore {
484*49ef7e06SGarrett D'Amore efx_mcdi_req_t req;
485*49ef7e06SGarrett D'Amore uint8_t payload[MAX(MC_CMD_ALLOC_VIS_IN_LEN,
486*49ef7e06SGarrett D'Amore MC_CMD_ALLOC_VIS_OUT_LEN)];
487*49ef7e06SGarrett D'Amore efx_rc_t rc;
488*49ef7e06SGarrett D'Amore
489*49ef7e06SGarrett D'Amore if (vi_countp == NULL) {
490*49ef7e06SGarrett D'Amore rc = EINVAL;
491*49ef7e06SGarrett D'Amore goto fail1;
492*49ef7e06SGarrett D'Amore }
493*49ef7e06SGarrett D'Amore
494*49ef7e06SGarrett D'Amore (void) memset(payload, 0, sizeof (payload));
495*49ef7e06SGarrett D'Amore req.emr_cmd = MC_CMD_ALLOC_VIS;
496*49ef7e06SGarrett D'Amore req.emr_in_buf = payload;
497*49ef7e06SGarrett D'Amore req.emr_in_length = MC_CMD_ALLOC_VIS_IN_LEN;
498*49ef7e06SGarrett D'Amore req.emr_out_buf = payload;
499*49ef7e06SGarrett D'Amore req.emr_out_length = MC_CMD_ALLOC_VIS_OUT_LEN;
500*49ef7e06SGarrett D'Amore
501*49ef7e06SGarrett D'Amore MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MIN_VI_COUNT, min_vi_count);
502*49ef7e06SGarrett D'Amore MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MAX_VI_COUNT, max_vi_count);
503*49ef7e06SGarrett D'Amore
504*49ef7e06SGarrett D'Amore efx_mcdi_execute(enp, &req);
505*49ef7e06SGarrett D'Amore
506*49ef7e06SGarrett D'Amore if (req.emr_rc != 0) {
507*49ef7e06SGarrett D'Amore rc = req.emr_rc;
508*49ef7e06SGarrett D'Amore goto fail2;
509*49ef7e06SGarrett D'Amore }
510*49ef7e06SGarrett D'Amore
511*49ef7e06SGarrett D'Amore if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_OUT_LEN) {
512*49ef7e06SGarrett D'Amore rc = EMSGSIZE;
513*49ef7e06SGarrett D'Amore goto fail3;
514*49ef7e06SGarrett D'Amore }
515*49ef7e06SGarrett D'Amore
516*49ef7e06SGarrett D'Amore *vi_basep = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_BASE);
517*49ef7e06SGarrett D'Amore *vi_countp = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_COUNT);
518*49ef7e06SGarrett D'Amore
519*49ef7e06SGarrett D'Amore /* Report VI_SHIFT if available (always zero for Huntington) */
520*49ef7e06SGarrett D'Amore if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_EXT_OUT_LEN)
521*49ef7e06SGarrett D'Amore *vi_shiftp = 0;
522*49ef7e06SGarrett D'Amore else
523*49ef7e06SGarrett D'Amore *vi_shiftp = MCDI_OUT_DWORD(req, ALLOC_VIS_EXT_OUT_VI_SHIFT);
524*49ef7e06SGarrett D'Amore
525*49ef7e06SGarrett D'Amore return (0);
526*49ef7e06SGarrett D'Amore
527*49ef7e06SGarrett D'Amore fail3:
528*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail3);
529*49ef7e06SGarrett D'Amore fail2:
530*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
531*49ef7e06SGarrett D'Amore fail1:
532*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
533*49ef7e06SGarrett D'Amore
534*49ef7e06SGarrett D'Amore return (rc);
535*49ef7e06SGarrett D'Amore }
536*49ef7e06SGarrett D'Amore
537*49ef7e06SGarrett D'Amore
538*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
efx_mcdi_free_vis(__in efx_nic_t * enp)539*49ef7e06SGarrett D'Amore efx_mcdi_free_vis(
540*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
541*49ef7e06SGarrett D'Amore {
542*49ef7e06SGarrett D'Amore efx_mcdi_req_t req;
543*49ef7e06SGarrett D'Amore efx_rc_t rc;
544*49ef7e06SGarrett D'Amore
545*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_IN_LEN == 0);
546*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_OUT_LEN == 0);
547*49ef7e06SGarrett D'Amore
548*49ef7e06SGarrett D'Amore req.emr_cmd = MC_CMD_FREE_VIS;
549*49ef7e06SGarrett D'Amore req.emr_in_buf = NULL;
550*49ef7e06SGarrett D'Amore req.emr_in_length = 0;
551*49ef7e06SGarrett D'Amore req.emr_out_buf = NULL;
552*49ef7e06SGarrett D'Amore req.emr_out_length = 0;
553*49ef7e06SGarrett D'Amore
554*49ef7e06SGarrett D'Amore efx_mcdi_execute_quiet(enp, &req);
555*49ef7e06SGarrett D'Amore
556*49ef7e06SGarrett D'Amore /* Ignore ELREADY (no allocated VIs, so nothing to free) */
557*49ef7e06SGarrett D'Amore if ((req.emr_rc != 0) && (req.emr_rc != EALREADY)) {
558*49ef7e06SGarrett D'Amore rc = req.emr_rc;
559*49ef7e06SGarrett D'Amore goto fail1;
560*49ef7e06SGarrett D'Amore }
561*49ef7e06SGarrett D'Amore
562*49ef7e06SGarrett D'Amore return (0);
563*49ef7e06SGarrett D'Amore
564*49ef7e06SGarrett D'Amore fail1:
565*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
566*49ef7e06SGarrett D'Amore
567*49ef7e06SGarrett D'Amore return (rc);
568*49ef7e06SGarrett D'Amore }
569*49ef7e06SGarrett D'Amore
570*49ef7e06SGarrett D'Amore
571*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
efx_mcdi_alloc_piobuf(__in efx_nic_t * enp,__out efx_piobuf_handle_t * handlep)572*49ef7e06SGarrett D'Amore efx_mcdi_alloc_piobuf(
573*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
574*49ef7e06SGarrett D'Amore __out efx_piobuf_handle_t *handlep)
575*49ef7e06SGarrett D'Amore {
576*49ef7e06SGarrett D'Amore efx_mcdi_req_t req;
577*49ef7e06SGarrett D'Amore uint8_t payload[MAX(MC_CMD_ALLOC_PIOBUF_IN_LEN,
578*49ef7e06SGarrett D'Amore MC_CMD_ALLOC_PIOBUF_OUT_LEN)];
579*49ef7e06SGarrett D'Amore efx_rc_t rc;
580*49ef7e06SGarrett D'Amore
581*49ef7e06SGarrett D'Amore if (handlep == NULL) {
582*49ef7e06SGarrett D'Amore rc = EINVAL;
583*49ef7e06SGarrett D'Amore goto fail1;
584*49ef7e06SGarrett D'Amore }
585*49ef7e06SGarrett D'Amore
586*49ef7e06SGarrett D'Amore (void) memset(payload, 0, sizeof (payload));
587*49ef7e06SGarrett D'Amore req.emr_cmd = MC_CMD_ALLOC_PIOBUF;
588*49ef7e06SGarrett D'Amore req.emr_in_buf = payload;
589*49ef7e06SGarrett D'Amore req.emr_in_length = MC_CMD_ALLOC_PIOBUF_IN_LEN;
590*49ef7e06SGarrett D'Amore req.emr_out_buf = payload;
591*49ef7e06SGarrett D'Amore req.emr_out_length = MC_CMD_ALLOC_PIOBUF_OUT_LEN;
592*49ef7e06SGarrett D'Amore
593*49ef7e06SGarrett D'Amore efx_mcdi_execute_quiet(enp, &req);
594*49ef7e06SGarrett D'Amore
595*49ef7e06SGarrett D'Amore if (req.emr_rc != 0) {
596*49ef7e06SGarrett D'Amore rc = req.emr_rc;
597*49ef7e06SGarrett D'Amore goto fail2;
598*49ef7e06SGarrett D'Amore }
599*49ef7e06SGarrett D'Amore
600*49ef7e06SGarrett D'Amore if (req.emr_out_length_used < MC_CMD_ALLOC_PIOBUF_OUT_LEN) {
601*49ef7e06SGarrett D'Amore rc = EMSGSIZE;
602*49ef7e06SGarrett D'Amore goto fail3;
603*49ef7e06SGarrett D'Amore }
604*49ef7e06SGarrett D'Amore
605*49ef7e06SGarrett D'Amore *handlep = MCDI_OUT_DWORD(req, ALLOC_PIOBUF_OUT_PIOBUF_HANDLE);
606*49ef7e06SGarrett D'Amore
607*49ef7e06SGarrett D'Amore return (0);
608*49ef7e06SGarrett D'Amore
609*49ef7e06SGarrett D'Amore fail3:
610*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail3);
611*49ef7e06SGarrett D'Amore fail2:
612*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
613*49ef7e06SGarrett D'Amore fail1:
614*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
615*49ef7e06SGarrett D'Amore
616*49ef7e06SGarrett D'Amore return (rc);
617*49ef7e06SGarrett D'Amore }
618*49ef7e06SGarrett D'Amore
619*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
efx_mcdi_free_piobuf(__in efx_nic_t * enp,__in efx_piobuf_handle_t handle)620*49ef7e06SGarrett D'Amore efx_mcdi_free_piobuf(
621*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
622*49ef7e06SGarrett D'Amore __in efx_piobuf_handle_t handle)
623*49ef7e06SGarrett D'Amore {
624*49ef7e06SGarrett D'Amore efx_mcdi_req_t req;
625*49ef7e06SGarrett D'Amore uint8_t payload[MAX(MC_CMD_FREE_PIOBUF_IN_LEN,
626*49ef7e06SGarrett D'Amore MC_CMD_FREE_PIOBUF_OUT_LEN)];
627*49ef7e06SGarrett D'Amore efx_rc_t rc;
628*49ef7e06SGarrett D'Amore
629*49ef7e06SGarrett D'Amore (void) memset(payload, 0, sizeof (payload));
630*49ef7e06SGarrett D'Amore req.emr_cmd = MC_CMD_FREE_PIOBUF;
631*49ef7e06SGarrett D'Amore req.emr_in_buf = payload;
632*49ef7e06SGarrett D'Amore req.emr_in_length = MC_CMD_FREE_PIOBUF_IN_LEN;
633*49ef7e06SGarrett D'Amore req.emr_out_buf = payload;
634*49ef7e06SGarrett D'Amore req.emr_out_length = MC_CMD_FREE_PIOBUF_OUT_LEN;
635*49ef7e06SGarrett D'Amore
636*49ef7e06SGarrett D'Amore MCDI_IN_SET_DWORD(req, FREE_PIOBUF_IN_PIOBUF_HANDLE, handle);
637*49ef7e06SGarrett D'Amore
638*49ef7e06SGarrett D'Amore efx_mcdi_execute_quiet(enp, &req);
639*49ef7e06SGarrett D'Amore
640*49ef7e06SGarrett D'Amore if (req.emr_rc != 0) {
641*49ef7e06SGarrett D'Amore rc = req.emr_rc;
642*49ef7e06SGarrett D'Amore goto fail1;
643*49ef7e06SGarrett D'Amore }
644*49ef7e06SGarrett D'Amore
645*49ef7e06SGarrett D'Amore return (0);
646*49ef7e06SGarrett D'Amore
647*49ef7e06SGarrett D'Amore fail1:
648*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
649*49ef7e06SGarrett D'Amore
650*49ef7e06SGarrett D'Amore return (rc);
651*49ef7e06SGarrett D'Amore }
652*49ef7e06SGarrett D'Amore
653*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
efx_mcdi_link_piobuf(__in efx_nic_t * enp,__in uint32_t vi_index,__in efx_piobuf_handle_t handle)654*49ef7e06SGarrett D'Amore efx_mcdi_link_piobuf(
655*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
656*49ef7e06SGarrett D'Amore __in uint32_t vi_index,
657*49ef7e06SGarrett D'Amore __in efx_piobuf_handle_t handle)
658*49ef7e06SGarrett D'Amore {
659*49ef7e06SGarrett D'Amore efx_mcdi_req_t req;
660*49ef7e06SGarrett D'Amore uint8_t payload[MAX(MC_CMD_LINK_PIOBUF_IN_LEN,
661*49ef7e06SGarrett D'Amore MC_CMD_LINK_PIOBUF_OUT_LEN)];
662*49ef7e06SGarrett D'Amore efx_rc_t rc;
663*49ef7e06SGarrett D'Amore
664*49ef7e06SGarrett D'Amore (void) memset(payload, 0, sizeof (payload));
665*49ef7e06SGarrett D'Amore req.emr_cmd = MC_CMD_LINK_PIOBUF;
666*49ef7e06SGarrett D'Amore req.emr_in_buf = payload;
667*49ef7e06SGarrett D'Amore req.emr_in_length = MC_CMD_LINK_PIOBUF_IN_LEN;
668*49ef7e06SGarrett D'Amore req.emr_out_buf = payload;
669*49ef7e06SGarrett D'Amore req.emr_out_length = MC_CMD_LINK_PIOBUF_OUT_LEN;
670*49ef7e06SGarrett D'Amore
671*49ef7e06SGarrett D'Amore MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_PIOBUF_HANDLE, handle);
672*49ef7e06SGarrett D'Amore MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_TXQ_INSTANCE, vi_index);
673*49ef7e06SGarrett D'Amore
674*49ef7e06SGarrett D'Amore efx_mcdi_execute(enp, &req);
675*49ef7e06SGarrett D'Amore
676*49ef7e06SGarrett D'Amore if (req.emr_rc != 0) {
677*49ef7e06SGarrett D'Amore rc = req.emr_rc;
678*49ef7e06SGarrett D'Amore goto fail1;
679*49ef7e06SGarrett D'Amore }
680*49ef7e06SGarrett D'Amore
681*49ef7e06SGarrett D'Amore return (0);
682*49ef7e06SGarrett D'Amore
683*49ef7e06SGarrett D'Amore fail1:
684*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
685*49ef7e06SGarrett D'Amore
686*49ef7e06SGarrett D'Amore return (rc);
687*49ef7e06SGarrett D'Amore }
688*49ef7e06SGarrett D'Amore
689*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t
efx_mcdi_unlink_piobuf(__in efx_nic_t * enp,__in uint32_t vi_index)690*49ef7e06SGarrett D'Amore efx_mcdi_unlink_piobuf(
691*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
692*49ef7e06SGarrett D'Amore __in uint32_t vi_index)
693*49ef7e06SGarrett D'Amore {
694*49ef7e06SGarrett D'Amore efx_mcdi_req_t req;
695*49ef7e06SGarrett D'Amore uint8_t payload[MAX(MC_CMD_UNLINK_PIOBUF_IN_LEN,
696*49ef7e06SGarrett D'Amore MC_CMD_UNLINK_PIOBUF_OUT_LEN)];
697*49ef7e06SGarrett D'Amore efx_rc_t rc;
698*49ef7e06SGarrett D'Amore
699*49ef7e06SGarrett D'Amore (void) memset(payload, 0, sizeof (payload));
700*49ef7e06SGarrett D'Amore req.emr_cmd = MC_CMD_UNLINK_PIOBUF;
701*49ef7e06SGarrett D'Amore req.emr_in_buf = payload;
702*49ef7e06SGarrett D'Amore req.emr_in_length = MC_CMD_UNLINK_PIOBUF_IN_LEN;
703*49ef7e06SGarrett D'Amore req.emr_out_buf = payload;
704*49ef7e06SGarrett D'Amore req.emr_out_length = MC_CMD_UNLINK_PIOBUF_OUT_LEN;
705*49ef7e06SGarrett D'Amore
706*49ef7e06SGarrett D'Amore MCDI_IN_SET_DWORD(req, UNLINK_PIOBUF_IN_TXQ_INSTANCE, vi_index);
707*49ef7e06SGarrett D'Amore
708*49ef7e06SGarrett D'Amore efx_mcdi_execute(enp, &req);
709*49ef7e06SGarrett D'Amore
710*49ef7e06SGarrett D'Amore if (req.emr_rc != 0) {
711*49ef7e06SGarrett D'Amore rc = req.emr_rc;
712*49ef7e06SGarrett D'Amore goto fail1;
713*49ef7e06SGarrett D'Amore }
714*49ef7e06SGarrett D'Amore
715*49ef7e06SGarrett D'Amore return (0);
716*49ef7e06SGarrett D'Amore
717*49ef7e06SGarrett D'Amore fail1:
718*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
719*49ef7e06SGarrett D'Amore
720*49ef7e06SGarrett D'Amore return (rc);
721*49ef7e06SGarrett D'Amore }
722*49ef7e06SGarrett D'Amore
723*49ef7e06SGarrett D'Amore static void
ef10_nic_alloc_piobufs(__in efx_nic_t * enp,__in uint32_t max_piobuf_count)724*49ef7e06SGarrett D'Amore ef10_nic_alloc_piobufs(
725*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
726*49ef7e06SGarrett D'Amore __in uint32_t max_piobuf_count)
727*49ef7e06SGarrett D'Amore {
728*49ef7e06SGarrett D'Amore efx_piobuf_handle_t *handlep;
729*49ef7e06SGarrett D'Amore unsigned int i;
730*49ef7e06SGarrett D'Amore
731*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(max_piobuf_count, <=,
732*49ef7e06SGarrett D'Amore EFX_ARRAY_SIZE(enp->en_arch.ef10.ena_piobuf_handle));
733*49ef7e06SGarrett D'Amore
734*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_piobuf_count = 0;
735*49ef7e06SGarrett D'Amore
736*49ef7e06SGarrett D'Amore for (i = 0; i < max_piobuf_count; i++) {
737*49ef7e06SGarrett D'Amore handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
738*49ef7e06SGarrett D'Amore
739*49ef7e06SGarrett D'Amore if (efx_mcdi_alloc_piobuf(enp, handlep) != 0)
740*49ef7e06SGarrett D'Amore goto fail1;
741*49ef7e06SGarrett D'Amore
742*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_pio_alloc_map[i] = 0;
743*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_piobuf_count++;
744*49ef7e06SGarrett D'Amore }
745*49ef7e06SGarrett D'Amore
746*49ef7e06SGarrett D'Amore return;
747*49ef7e06SGarrett D'Amore
748*49ef7e06SGarrett D'Amore fail1:
749*49ef7e06SGarrett D'Amore for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
750*49ef7e06SGarrett D'Amore handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
751*49ef7e06SGarrett D'Amore
752*49ef7e06SGarrett D'Amore (void) efx_mcdi_free_piobuf(enp, *handlep);
753*49ef7e06SGarrett D'Amore *handlep = EFX_PIOBUF_HANDLE_INVALID;
754*49ef7e06SGarrett D'Amore }
755*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_piobuf_count = 0;
756*49ef7e06SGarrett D'Amore }
757*49ef7e06SGarrett D'Amore
758*49ef7e06SGarrett D'Amore
759*49ef7e06SGarrett D'Amore static void
ef10_nic_free_piobufs(__in efx_nic_t * enp)760*49ef7e06SGarrett D'Amore ef10_nic_free_piobufs(
761*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
762*49ef7e06SGarrett D'Amore {
763*49ef7e06SGarrett D'Amore efx_piobuf_handle_t *handlep;
764*49ef7e06SGarrett D'Amore unsigned int i;
765*49ef7e06SGarrett D'Amore
766*49ef7e06SGarrett D'Amore for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
767*49ef7e06SGarrett D'Amore handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
768*49ef7e06SGarrett D'Amore
769*49ef7e06SGarrett D'Amore (void) efx_mcdi_free_piobuf(enp, *handlep);
770*49ef7e06SGarrett D'Amore *handlep = EFX_PIOBUF_HANDLE_INVALID;
771*49ef7e06SGarrett D'Amore }
772*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_piobuf_count = 0;
773*49ef7e06SGarrett D'Amore }
774*49ef7e06SGarrett D'Amore
775*49ef7e06SGarrett D'Amore /* Sub-allocate a block from a piobuf */
776*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_nic_pio_alloc(__inout efx_nic_t * enp,__out uint32_t * bufnump,__out efx_piobuf_handle_t * handlep,__out uint32_t * blknump,__out uint32_t * offsetp,__out size_t * sizep)777*49ef7e06SGarrett D'Amore ef10_nic_pio_alloc(
778*49ef7e06SGarrett D'Amore __inout efx_nic_t *enp,
779*49ef7e06SGarrett D'Amore __out uint32_t *bufnump,
780*49ef7e06SGarrett D'Amore __out efx_piobuf_handle_t *handlep,
781*49ef7e06SGarrett D'Amore __out uint32_t *blknump,
782*49ef7e06SGarrett D'Amore __out uint32_t *offsetp,
783*49ef7e06SGarrett D'Amore __out size_t *sizep)
784*49ef7e06SGarrett D'Amore {
785*49ef7e06SGarrett D'Amore efx_nic_cfg_t *encp = &enp->en_nic_cfg;
786*49ef7e06SGarrett D'Amore efx_drv_cfg_t *edcp = &enp->en_drv_cfg;
787*49ef7e06SGarrett D'Amore uint32_t blk_per_buf;
788*49ef7e06SGarrett D'Amore uint32_t buf, blk;
789*49ef7e06SGarrett D'Amore efx_rc_t rc;
790*49ef7e06SGarrett D'Amore
791*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
792*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
793*49ef7e06SGarrett D'Amore EFSYS_ASSERT(bufnump);
794*49ef7e06SGarrett D'Amore EFSYS_ASSERT(handlep);
795*49ef7e06SGarrett D'Amore EFSYS_ASSERT(blknump);
796*49ef7e06SGarrett D'Amore EFSYS_ASSERT(offsetp);
797*49ef7e06SGarrett D'Amore EFSYS_ASSERT(sizep);
798*49ef7e06SGarrett D'Amore
799*49ef7e06SGarrett D'Amore if ((edcp->edc_pio_alloc_size == 0) ||
800*49ef7e06SGarrett D'Amore (enp->en_arch.ef10.ena_piobuf_count == 0)) {
801*49ef7e06SGarrett D'Amore rc = ENOMEM;
802*49ef7e06SGarrett D'Amore goto fail1;
803*49ef7e06SGarrett D'Amore }
804*49ef7e06SGarrett D'Amore blk_per_buf = encp->enc_piobuf_size / edcp->edc_pio_alloc_size;
805*49ef7e06SGarrett D'Amore
806*49ef7e06SGarrett D'Amore for (buf = 0; buf < enp->en_arch.ef10.ena_piobuf_count; buf++) {
807*49ef7e06SGarrett D'Amore uint32_t *map = &enp->en_arch.ef10.ena_pio_alloc_map[buf];
808*49ef7e06SGarrett D'Amore
809*49ef7e06SGarrett D'Amore if (~(*map) == 0)
810*49ef7e06SGarrett D'Amore continue;
811*49ef7e06SGarrett D'Amore
812*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(blk_per_buf, <=, (8 * sizeof (*map)));
813*49ef7e06SGarrett D'Amore for (blk = 0; blk < blk_per_buf; blk++) {
814*49ef7e06SGarrett D'Amore if ((*map & (1u << blk)) == 0) {
815*49ef7e06SGarrett D'Amore *map |= (1u << blk);
816*49ef7e06SGarrett D'Amore goto done;
817*49ef7e06SGarrett D'Amore }
818*49ef7e06SGarrett D'Amore }
819*49ef7e06SGarrett D'Amore }
820*49ef7e06SGarrett D'Amore rc = ENOMEM;
821*49ef7e06SGarrett D'Amore goto fail2;
822*49ef7e06SGarrett D'Amore
823*49ef7e06SGarrett D'Amore done:
824*49ef7e06SGarrett D'Amore *handlep = enp->en_arch.ef10.ena_piobuf_handle[buf];
825*49ef7e06SGarrett D'Amore *bufnump = buf;
826*49ef7e06SGarrett D'Amore *blknump = blk;
827*49ef7e06SGarrett D'Amore *sizep = edcp->edc_pio_alloc_size;
828*49ef7e06SGarrett D'Amore *offsetp = blk * (*sizep);
829*49ef7e06SGarrett D'Amore
830*49ef7e06SGarrett D'Amore return (0);
831*49ef7e06SGarrett D'Amore
832*49ef7e06SGarrett D'Amore fail2:
833*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
834*49ef7e06SGarrett D'Amore fail1:
835*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
836*49ef7e06SGarrett D'Amore
837*49ef7e06SGarrett D'Amore return (rc);
838*49ef7e06SGarrett D'Amore }
839*49ef7e06SGarrett D'Amore
840*49ef7e06SGarrett D'Amore /* Free a piobuf sub-allocated block */
841*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_nic_pio_free(__inout efx_nic_t * enp,__in uint32_t bufnum,__in uint32_t blknum)842*49ef7e06SGarrett D'Amore ef10_nic_pio_free(
843*49ef7e06SGarrett D'Amore __inout efx_nic_t *enp,
844*49ef7e06SGarrett D'Amore __in uint32_t bufnum,
845*49ef7e06SGarrett D'Amore __in uint32_t blknum)
846*49ef7e06SGarrett D'Amore {
847*49ef7e06SGarrett D'Amore uint32_t *map;
848*49ef7e06SGarrett D'Amore efx_rc_t rc;
849*49ef7e06SGarrett D'Amore
850*49ef7e06SGarrett D'Amore if ((bufnum >= enp->en_arch.ef10.ena_piobuf_count) ||
851*49ef7e06SGarrett D'Amore (blknum >= (8 * sizeof (*map)))) {
852*49ef7e06SGarrett D'Amore rc = EINVAL;
853*49ef7e06SGarrett D'Amore goto fail1;
854*49ef7e06SGarrett D'Amore }
855*49ef7e06SGarrett D'Amore
856*49ef7e06SGarrett D'Amore map = &enp->en_arch.ef10.ena_pio_alloc_map[bufnum];
857*49ef7e06SGarrett D'Amore if ((*map & (1u << blknum)) == 0) {
858*49ef7e06SGarrett D'Amore rc = ENOENT;
859*49ef7e06SGarrett D'Amore goto fail2;
860*49ef7e06SGarrett D'Amore }
861*49ef7e06SGarrett D'Amore *map &= ~(1u << blknum);
862*49ef7e06SGarrett D'Amore
863*49ef7e06SGarrett D'Amore return (0);
864*49ef7e06SGarrett D'Amore
865*49ef7e06SGarrett D'Amore fail2:
866*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
867*49ef7e06SGarrett D'Amore fail1:
868*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
869*49ef7e06SGarrett D'Amore
870*49ef7e06SGarrett D'Amore return (rc);
871*49ef7e06SGarrett D'Amore }
872*49ef7e06SGarrett D'Amore
873*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_nic_pio_link(__inout efx_nic_t * enp,__in uint32_t vi_index,__in efx_piobuf_handle_t handle)874*49ef7e06SGarrett D'Amore ef10_nic_pio_link(
875*49ef7e06SGarrett D'Amore __inout efx_nic_t *enp,
876*49ef7e06SGarrett D'Amore __in uint32_t vi_index,
877*49ef7e06SGarrett D'Amore __in efx_piobuf_handle_t handle)
878*49ef7e06SGarrett D'Amore {
879*49ef7e06SGarrett D'Amore return (efx_mcdi_link_piobuf(enp, vi_index, handle));
880*49ef7e06SGarrett D'Amore }
881*49ef7e06SGarrett D'Amore
882*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_nic_pio_unlink(__inout efx_nic_t * enp,__in uint32_t vi_index)883*49ef7e06SGarrett D'Amore ef10_nic_pio_unlink(
884*49ef7e06SGarrett D'Amore __inout efx_nic_t *enp,
885*49ef7e06SGarrett D'Amore __in uint32_t vi_index)
886*49ef7e06SGarrett D'Amore {
887*49ef7e06SGarrett D'Amore return (efx_mcdi_unlink_piobuf(enp, vi_index));
888*49ef7e06SGarrett D'Amore }
889*49ef7e06SGarrett D'Amore
890*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_get_datapath_caps(__in efx_nic_t * enp)891*49ef7e06SGarrett D'Amore ef10_get_datapath_caps(
892*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
893*49ef7e06SGarrett D'Amore {
894*49ef7e06SGarrett D'Amore efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
895*49ef7e06SGarrett D'Amore uint32_t flags;
896*49ef7e06SGarrett D'Amore uint32_t flags2;
897*49ef7e06SGarrett D'Amore efx_rc_t rc;
898*49ef7e06SGarrett D'Amore
899*49ef7e06SGarrett D'Amore if ((rc = efx_mcdi_get_capabilities(enp, &flags, &flags2)) != 0)
900*49ef7e06SGarrett D'Amore goto fail1;
901*49ef7e06SGarrett D'Amore
902*49ef7e06SGarrett D'Amore #define CAP_FLAG(flags1, field) \
903*49ef7e06SGarrett D'Amore ((flags1) & (1 << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## field ## _LBN)))
904*49ef7e06SGarrett D'Amore
905*49ef7e06SGarrett D'Amore #define CAP_FLAG2(flags2, field) \
906*49ef7e06SGarrett D'Amore ((flags2) & (1 << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## field ## _LBN)))
907*49ef7e06SGarrett D'Amore
908*49ef7e06SGarrett D'Amore /*
909*49ef7e06SGarrett D'Amore * Huntington RXDP firmware inserts a 0 or 14 byte prefix.
910*49ef7e06SGarrett D'Amore * We only support the 14 byte prefix here.
911*49ef7e06SGarrett D'Amore */
912*49ef7e06SGarrett D'Amore if (CAP_FLAG(flags, RX_PREFIX_LEN_14) == 0) {
913*49ef7e06SGarrett D'Amore rc = ENOTSUP;
914*49ef7e06SGarrett D'Amore goto fail2;
915*49ef7e06SGarrett D'Amore }
916*49ef7e06SGarrett D'Amore encp->enc_rx_prefix_size = 14;
917*49ef7e06SGarrett D'Amore
918*49ef7e06SGarrett D'Amore /* Check if the firmware supports TSO */
919*49ef7e06SGarrett D'Amore encp->enc_fw_assisted_tso_enabled =
920*49ef7e06SGarrett D'Amore CAP_FLAG(flags, TX_TSO) ? B_TRUE : B_FALSE;
921*49ef7e06SGarrett D'Amore
922*49ef7e06SGarrett D'Amore /* Check if the firmware supports FATSOv2 */
923*49ef7e06SGarrett D'Amore encp->enc_fw_assisted_tso_v2_enabled =
924*49ef7e06SGarrett D'Amore CAP_FLAG2(flags2, TX_TSO_V2) ? B_TRUE : B_FALSE;
925*49ef7e06SGarrett D'Amore
926*49ef7e06SGarrett D'Amore /* Check if the firmware has vadapter/vport/vswitch support */
927*49ef7e06SGarrett D'Amore encp->enc_datapath_cap_evb =
928*49ef7e06SGarrett D'Amore CAP_FLAG(flags, EVB) ? B_TRUE : B_FALSE;
929*49ef7e06SGarrett D'Amore
930*49ef7e06SGarrett D'Amore /* Check if the firmware supports VLAN insertion */
931*49ef7e06SGarrett D'Amore encp->enc_hw_tx_insert_vlan_enabled =
932*49ef7e06SGarrett D'Amore CAP_FLAG(flags, TX_VLAN_INSERTION) ? B_TRUE : B_FALSE;
933*49ef7e06SGarrett D'Amore
934*49ef7e06SGarrett D'Amore /* Check if the firmware supports RX event batching */
935*49ef7e06SGarrett D'Amore encp->enc_rx_batching_enabled =
936*49ef7e06SGarrett D'Amore CAP_FLAG(flags, RX_BATCHING) ? B_TRUE : B_FALSE;
937*49ef7e06SGarrett D'Amore
938*49ef7e06SGarrett D'Amore if (encp->enc_rx_batching_enabled)
939*49ef7e06SGarrett D'Amore encp->enc_rx_batch_max = 16;
940*49ef7e06SGarrett D'Amore
941*49ef7e06SGarrett D'Amore /* Check if the firmware supports disabling scatter on RXQs */
942*49ef7e06SGarrett D'Amore encp->enc_rx_disable_scatter_supported =
943*49ef7e06SGarrett D'Amore CAP_FLAG(flags, RX_DISABLE_SCATTER) ? B_TRUE : B_FALSE;
944*49ef7e06SGarrett D'Amore
945*49ef7e06SGarrett D'Amore /* Check if the firmware supports set mac with running filters */
946*49ef7e06SGarrett D'Amore encp->enc_allow_set_mac_with_installed_filters =
947*49ef7e06SGarrett D'Amore CAP_FLAG(flags, VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED) ?
948*49ef7e06SGarrett D'Amore B_TRUE : B_FALSE;
949*49ef7e06SGarrett D'Amore
950*49ef7e06SGarrett D'Amore /*
951*49ef7e06SGarrett D'Amore * Check if firmware supports the extended MC_CMD_SET_MAC, which allows
952*49ef7e06SGarrett D'Amore * specifying which parameters to configure.
953*49ef7e06SGarrett D'Amore */
954*49ef7e06SGarrett D'Amore encp->enc_enhanced_set_mac_supported =
955*49ef7e06SGarrett D'Amore CAP_FLAG(flags, SET_MAC_ENHANCED) ? B_TRUE : B_FALSE;
956*49ef7e06SGarrett D'Amore
957*49ef7e06SGarrett D'Amore #undef CAP_FLAG
958*49ef7e06SGarrett D'Amore #undef CAP_FLAG2
959*49ef7e06SGarrett D'Amore
960*49ef7e06SGarrett D'Amore return (0);
961*49ef7e06SGarrett D'Amore
962*49ef7e06SGarrett D'Amore fail2:
963*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
964*49ef7e06SGarrett D'Amore fail1:
965*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
966*49ef7e06SGarrett D'Amore
967*49ef7e06SGarrett D'Amore return (rc);
968*49ef7e06SGarrett D'Amore }
969*49ef7e06SGarrett D'Amore
970*49ef7e06SGarrett D'Amore
971*49ef7e06SGarrett D'Amore #define EF10_LEGACY_PF_PRIVILEGE_MASK \
972*49ef7e06SGarrett D'Amore (MC_CMD_PRIVILEGE_MASK_IN_GRP_ADMIN | \
973*49ef7e06SGarrett D'Amore MC_CMD_PRIVILEGE_MASK_IN_GRP_LINK | \
974*49ef7e06SGarrett D'Amore MC_CMD_PRIVILEGE_MASK_IN_GRP_ONLOAD | \
975*49ef7e06SGarrett D'Amore MC_CMD_PRIVILEGE_MASK_IN_GRP_PTP | \
976*49ef7e06SGarrett D'Amore MC_CMD_PRIVILEGE_MASK_IN_GRP_INSECURE_FILTERS | \
977*49ef7e06SGarrett D'Amore MC_CMD_PRIVILEGE_MASK_IN_GRP_MAC_SPOOFING | \
978*49ef7e06SGarrett D'Amore MC_CMD_PRIVILEGE_MASK_IN_GRP_UNICAST | \
979*49ef7e06SGarrett D'Amore MC_CMD_PRIVILEGE_MASK_IN_GRP_MULTICAST | \
980*49ef7e06SGarrett D'Amore MC_CMD_PRIVILEGE_MASK_IN_GRP_BROADCAST | \
981*49ef7e06SGarrett D'Amore MC_CMD_PRIVILEGE_MASK_IN_GRP_ALL_MULTICAST | \
982*49ef7e06SGarrett D'Amore MC_CMD_PRIVILEGE_MASK_IN_GRP_PROMISCUOUS)
983*49ef7e06SGarrett D'Amore
984*49ef7e06SGarrett D'Amore #define EF10_LEGACY_VF_PRIVILEGE_MASK 0
985*49ef7e06SGarrett D'Amore
986*49ef7e06SGarrett D'Amore
987*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_get_privilege_mask(__in efx_nic_t * enp,__out uint32_t * maskp)988*49ef7e06SGarrett D'Amore ef10_get_privilege_mask(
989*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
990*49ef7e06SGarrett D'Amore __out uint32_t *maskp)
991*49ef7e06SGarrett D'Amore {
992*49ef7e06SGarrett D'Amore efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
993*49ef7e06SGarrett D'Amore uint32_t mask;
994*49ef7e06SGarrett D'Amore efx_rc_t rc;
995*49ef7e06SGarrett D'Amore
996*49ef7e06SGarrett D'Amore if ((rc = efx_mcdi_privilege_mask(enp, encp->enc_pf, encp->enc_vf,
997*49ef7e06SGarrett D'Amore &mask)) != 0) {
998*49ef7e06SGarrett D'Amore if (rc != ENOTSUP)
999*49ef7e06SGarrett D'Amore goto fail1;
1000*49ef7e06SGarrett D'Amore
1001*49ef7e06SGarrett D'Amore /* Fallback for old firmware without privilege mask support */
1002*49ef7e06SGarrett D'Amore if (EFX_PCI_FUNCTION_IS_PF(encp)) {
1003*49ef7e06SGarrett D'Amore /* Assume PF has admin privilege */
1004*49ef7e06SGarrett D'Amore mask = EF10_LEGACY_PF_PRIVILEGE_MASK;
1005*49ef7e06SGarrett D'Amore } else {
1006*49ef7e06SGarrett D'Amore /* VF is always unprivileged by default */
1007*49ef7e06SGarrett D'Amore mask = EF10_LEGACY_VF_PRIVILEGE_MASK;
1008*49ef7e06SGarrett D'Amore }
1009*49ef7e06SGarrett D'Amore }
1010*49ef7e06SGarrett D'Amore
1011*49ef7e06SGarrett D'Amore *maskp = mask;
1012*49ef7e06SGarrett D'Amore
1013*49ef7e06SGarrett D'Amore return (0);
1014*49ef7e06SGarrett D'Amore
1015*49ef7e06SGarrett D'Amore fail1:
1016*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
1017*49ef7e06SGarrett D'Amore
1018*49ef7e06SGarrett D'Amore return (rc);
1019*49ef7e06SGarrett D'Amore }
1020*49ef7e06SGarrett D'Amore
1021*49ef7e06SGarrett D'Amore
1022*49ef7e06SGarrett D'Amore /*
1023*49ef7e06SGarrett D'Amore * The external port mapping is a one-based numbering of the external
1024*49ef7e06SGarrett D'Amore * connectors on the board. It does not distinguish off-board separated
1025*49ef7e06SGarrett D'Amore * outputs such as multi-headed cables.
1026*49ef7e06SGarrett D'Amore * The number of ports that map to each external port connector
1027*49ef7e06SGarrett D'Amore * on the board is determined by the chip family and the port modes to
1028*49ef7e06SGarrett D'Amore * which the NIC can be configured. The mapping table lists modes with
1029*49ef7e06SGarrett D'Amore * port numbering requirements in increasing order.
1030*49ef7e06SGarrett D'Amore */
1031*49ef7e06SGarrett D'Amore static struct {
1032*49ef7e06SGarrett D'Amore efx_family_t family;
1033*49ef7e06SGarrett D'Amore uint32_t modes_mask;
1034*49ef7e06SGarrett D'Amore uint32_t stride;
1035*49ef7e06SGarrett D'Amore } __ef10_external_port_mappings[] = {
1036*49ef7e06SGarrett D'Amore /* Supported modes requiring 1 output per port */
1037*49ef7e06SGarrett D'Amore {
1038*49ef7e06SGarrett D'Amore EFX_FAMILY_HUNTINGTON,
1039*49ef7e06SGarrett D'Amore (1 << TLV_PORT_MODE_10G) |
1040*49ef7e06SGarrett D'Amore (1 << TLV_PORT_MODE_10G_10G) |
1041*49ef7e06SGarrett D'Amore (1 << TLV_PORT_MODE_10G_10G_10G_10G),
1042*49ef7e06SGarrett D'Amore 1
1043*49ef7e06SGarrett D'Amore },
1044*49ef7e06SGarrett D'Amore {
1045*49ef7e06SGarrett D'Amore EFX_FAMILY_MEDFORD,
1046*49ef7e06SGarrett D'Amore (1 << TLV_PORT_MODE_10G) |
1047*49ef7e06SGarrett D'Amore (1 << TLV_PORT_MODE_10G_10G) |
1048*49ef7e06SGarrett D'Amore (1 << TLV_PORT_MODE_10G_10G_10G_10G),
1049*49ef7e06SGarrett D'Amore 1
1050*49ef7e06SGarrett D'Amore },
1051*49ef7e06SGarrett D'Amore /* Supported modes requiring 2 outputs per port */
1052*49ef7e06SGarrett D'Amore {
1053*49ef7e06SGarrett D'Amore EFX_FAMILY_HUNTINGTON,
1054*49ef7e06SGarrett D'Amore (1 << TLV_PORT_MODE_40G) |
1055*49ef7e06SGarrett D'Amore (1 << TLV_PORT_MODE_40G_40G) |
1056*49ef7e06SGarrett D'Amore (1 << TLV_PORT_MODE_40G_10G_10G) |
1057*49ef7e06SGarrett D'Amore (1 << TLV_PORT_MODE_10G_10G_40G),
1058*49ef7e06SGarrett D'Amore 2
1059*49ef7e06SGarrett D'Amore },
1060*49ef7e06SGarrett D'Amore {
1061*49ef7e06SGarrett D'Amore EFX_FAMILY_MEDFORD,
1062*49ef7e06SGarrett D'Amore (1 << TLV_PORT_MODE_40G) |
1063*49ef7e06SGarrett D'Amore (1 << TLV_PORT_MODE_40G_40G) |
1064*49ef7e06SGarrett D'Amore (1 << TLV_PORT_MODE_40G_10G_10G) |
1065*49ef7e06SGarrett D'Amore (1 << TLV_PORT_MODE_10G_10G_40G),
1066*49ef7e06SGarrett D'Amore 2
1067*49ef7e06SGarrett D'Amore },
1068*49ef7e06SGarrett D'Amore /* Supported modes requiring 4 outputs per port */
1069*49ef7e06SGarrett D'Amore {
1070*49ef7e06SGarrett D'Amore EFX_FAMILY_MEDFORD,
1071*49ef7e06SGarrett D'Amore (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q) |
1072*49ef7e06SGarrett D'Amore (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q2),
1073*49ef7e06SGarrett D'Amore 4
1074*49ef7e06SGarrett D'Amore },
1075*49ef7e06SGarrett D'Amore };
1076*49ef7e06SGarrett D'Amore
1077*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_external_port_mapping(__in efx_nic_t * enp,__in uint32_t port,__out uint8_t * external_portp)1078*49ef7e06SGarrett D'Amore ef10_external_port_mapping(
1079*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
1080*49ef7e06SGarrett D'Amore __in uint32_t port,
1081*49ef7e06SGarrett D'Amore __out uint8_t *external_portp)
1082*49ef7e06SGarrett D'Amore {
1083*49ef7e06SGarrett D'Amore efx_rc_t rc;
1084*49ef7e06SGarrett D'Amore int i;
1085*49ef7e06SGarrett D'Amore uint32_t port_modes;
1086*49ef7e06SGarrett D'Amore uint32_t matches;
1087*49ef7e06SGarrett D'Amore uint32_t stride = 1; /* default 1-1 mapping */
1088*49ef7e06SGarrett D'Amore
1089*49ef7e06SGarrett D'Amore if ((rc = efx_mcdi_get_port_modes(enp, &port_modes)) != 0) {
1090*49ef7e06SGarrett D'Amore /* No port mode information available - use default mapping */
1091*49ef7e06SGarrett D'Amore goto out;
1092*49ef7e06SGarrett D'Amore }
1093*49ef7e06SGarrett D'Amore
1094*49ef7e06SGarrett D'Amore /*
1095*49ef7e06SGarrett D'Amore * Infer the internal port -> external port mapping from
1096*49ef7e06SGarrett D'Amore * the possible port modes for this NIC.
1097*49ef7e06SGarrett D'Amore */
1098*49ef7e06SGarrett D'Amore for (i = 0; i < EFX_ARRAY_SIZE(__ef10_external_port_mappings); ++i) {
1099*49ef7e06SGarrett D'Amore if (__ef10_external_port_mappings[i].family !=
1100*49ef7e06SGarrett D'Amore enp->en_family)
1101*49ef7e06SGarrett D'Amore continue;
1102*49ef7e06SGarrett D'Amore matches = (__ef10_external_port_mappings[i].modes_mask &
1103*49ef7e06SGarrett D'Amore port_modes);
1104*49ef7e06SGarrett D'Amore if (matches != 0) {
1105*49ef7e06SGarrett D'Amore stride = __ef10_external_port_mappings[i].stride;
1106*49ef7e06SGarrett D'Amore port_modes &= ~matches;
1107*49ef7e06SGarrett D'Amore }
1108*49ef7e06SGarrett D'Amore }
1109*49ef7e06SGarrett D'Amore
1110*49ef7e06SGarrett D'Amore if (port_modes != 0) {
1111*49ef7e06SGarrett D'Amore /* Some advertised modes are not supported */
1112*49ef7e06SGarrett D'Amore rc = ENOTSUP;
1113*49ef7e06SGarrett D'Amore goto fail1;
1114*49ef7e06SGarrett D'Amore }
1115*49ef7e06SGarrett D'Amore
1116*49ef7e06SGarrett D'Amore out:
1117*49ef7e06SGarrett D'Amore /*
1118*49ef7e06SGarrett D'Amore * Scale as required by last matched mode and then convert to
1119*49ef7e06SGarrett D'Amore * one-based numbering
1120*49ef7e06SGarrett D'Amore */
1121*49ef7e06SGarrett D'Amore *external_portp = (uint8_t)(port / stride) + 1;
1122*49ef7e06SGarrett D'Amore return (0);
1123*49ef7e06SGarrett D'Amore
1124*49ef7e06SGarrett D'Amore fail1:
1125*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
1126*49ef7e06SGarrett D'Amore
1127*49ef7e06SGarrett D'Amore return (rc);
1128*49ef7e06SGarrett D'Amore }
1129*49ef7e06SGarrett D'Amore
1130*49ef7e06SGarrett D'Amore
1131*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_nic_probe(__in efx_nic_t * enp)1132*49ef7e06SGarrett D'Amore ef10_nic_probe(
1133*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
1134*49ef7e06SGarrett D'Amore {
1135*49ef7e06SGarrett D'Amore const efx_nic_ops_t *enop = enp->en_enop;
1136*49ef7e06SGarrett D'Amore efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1137*49ef7e06SGarrett D'Amore efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1138*49ef7e06SGarrett D'Amore efx_rc_t rc;
1139*49ef7e06SGarrett D'Amore
1140*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1141*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
1142*49ef7e06SGarrett D'Amore
1143*49ef7e06SGarrett D'Amore /* Read and clear any assertion state */
1144*49ef7e06SGarrett D'Amore if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1145*49ef7e06SGarrett D'Amore goto fail1;
1146*49ef7e06SGarrett D'Amore
1147*49ef7e06SGarrett D'Amore /* Exit the assertion handler */
1148*49ef7e06SGarrett D'Amore if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1149*49ef7e06SGarrett D'Amore if (rc != EACCES)
1150*49ef7e06SGarrett D'Amore goto fail2;
1151*49ef7e06SGarrett D'Amore
1152*49ef7e06SGarrett D'Amore if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
1153*49ef7e06SGarrett D'Amore goto fail3;
1154*49ef7e06SGarrett D'Amore
1155*49ef7e06SGarrett D'Amore if ((rc = enop->eno_board_cfg(enp)) != 0)
1156*49ef7e06SGarrett D'Amore if (rc != EACCES)
1157*49ef7e06SGarrett D'Amore goto fail4;
1158*49ef7e06SGarrett D'Amore
1159*49ef7e06SGarrett D'Amore /*
1160*49ef7e06SGarrett D'Amore * Set default driver config limits (based on board config).
1161*49ef7e06SGarrett D'Amore *
1162*49ef7e06SGarrett D'Amore * FIXME: For now allocate a fixed number of VIs which is likely to be
1163*49ef7e06SGarrett D'Amore * sufficient and small enough to allow multiple functions on the same
1164*49ef7e06SGarrett D'Amore * port.
1165*49ef7e06SGarrett D'Amore */
1166*49ef7e06SGarrett D'Amore edcp->edc_min_vi_count = edcp->edc_max_vi_count =
1167*49ef7e06SGarrett D'Amore MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit));
1168*49ef7e06SGarrett D'Amore
1169*49ef7e06SGarrett D'Amore /* The client driver must configure and enable PIO buffer support */
1170*49ef7e06SGarrett D'Amore edcp->edc_max_piobuf_count = 0;
1171*49ef7e06SGarrett D'Amore edcp->edc_pio_alloc_size = 0;
1172*49ef7e06SGarrett D'Amore
1173*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MAC_STATS
1174*49ef7e06SGarrett D'Amore /* Wipe the MAC statistics */
1175*49ef7e06SGarrett D'Amore if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
1176*49ef7e06SGarrett D'Amore goto fail5;
1177*49ef7e06SGarrett D'Amore #endif
1178*49ef7e06SGarrett D'Amore
1179*49ef7e06SGarrett D'Amore #if EFSYS_OPT_LOOPBACK
1180*49ef7e06SGarrett D'Amore if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
1181*49ef7e06SGarrett D'Amore goto fail6;
1182*49ef7e06SGarrett D'Amore #endif
1183*49ef7e06SGarrett D'Amore
1184*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MON_STATS
1185*49ef7e06SGarrett D'Amore if ((rc = mcdi_mon_cfg_build(enp)) != 0) {
1186*49ef7e06SGarrett D'Amore /* Unprivileged functions do not have access to sensors */
1187*49ef7e06SGarrett D'Amore if (rc != EACCES)
1188*49ef7e06SGarrett D'Amore goto fail7;
1189*49ef7e06SGarrett D'Amore }
1190*49ef7e06SGarrett D'Amore #endif
1191*49ef7e06SGarrett D'Amore
1192*49ef7e06SGarrett D'Amore encp->enc_features = enp->en_features;
1193*49ef7e06SGarrett D'Amore
1194*49ef7e06SGarrett D'Amore return (0);
1195*49ef7e06SGarrett D'Amore
1196*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MON_STATS
1197*49ef7e06SGarrett D'Amore fail7:
1198*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail7);
1199*49ef7e06SGarrett D'Amore #endif
1200*49ef7e06SGarrett D'Amore #if EFSYS_OPT_LOOPBACK
1201*49ef7e06SGarrett D'Amore fail6:
1202*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail6);
1203*49ef7e06SGarrett D'Amore #endif
1204*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MAC_STATS
1205*49ef7e06SGarrett D'Amore fail5:
1206*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail5);
1207*49ef7e06SGarrett D'Amore #endif
1208*49ef7e06SGarrett D'Amore fail4:
1209*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail4);
1210*49ef7e06SGarrett D'Amore fail3:
1211*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail3);
1212*49ef7e06SGarrett D'Amore fail2:
1213*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
1214*49ef7e06SGarrett D'Amore fail1:
1215*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
1216*49ef7e06SGarrett D'Amore
1217*49ef7e06SGarrett D'Amore return (rc);
1218*49ef7e06SGarrett D'Amore }
1219*49ef7e06SGarrett D'Amore
1220*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_nic_set_drv_limits(__inout efx_nic_t * enp,__in efx_drv_limits_t * edlp)1221*49ef7e06SGarrett D'Amore ef10_nic_set_drv_limits(
1222*49ef7e06SGarrett D'Amore __inout efx_nic_t *enp,
1223*49ef7e06SGarrett D'Amore __in efx_drv_limits_t *edlp)
1224*49ef7e06SGarrett D'Amore {
1225*49ef7e06SGarrett D'Amore efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1226*49ef7e06SGarrett D'Amore efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1227*49ef7e06SGarrett D'Amore uint32_t min_evq_count, max_evq_count;
1228*49ef7e06SGarrett D'Amore uint32_t min_rxq_count, max_rxq_count;
1229*49ef7e06SGarrett D'Amore uint32_t min_txq_count, max_txq_count;
1230*49ef7e06SGarrett D'Amore efx_rc_t rc;
1231*49ef7e06SGarrett D'Amore
1232*49ef7e06SGarrett D'Amore if (edlp == NULL) {
1233*49ef7e06SGarrett D'Amore rc = EINVAL;
1234*49ef7e06SGarrett D'Amore goto fail1;
1235*49ef7e06SGarrett D'Amore }
1236*49ef7e06SGarrett D'Amore
1237*49ef7e06SGarrett D'Amore /* Get minimum required and maximum usable VI limits */
1238*49ef7e06SGarrett D'Amore min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit);
1239*49ef7e06SGarrett D'Amore min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit);
1240*49ef7e06SGarrett D'Amore min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit);
1241*49ef7e06SGarrett D'Amore
1242*49ef7e06SGarrett D'Amore edcp->edc_min_vi_count =
1243*49ef7e06SGarrett D'Amore MAX(min_evq_count, MAX(min_rxq_count, min_txq_count));
1244*49ef7e06SGarrett D'Amore
1245*49ef7e06SGarrett D'Amore max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit);
1246*49ef7e06SGarrett D'Amore max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit);
1247*49ef7e06SGarrett D'Amore max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit);
1248*49ef7e06SGarrett D'Amore
1249*49ef7e06SGarrett D'Amore edcp->edc_max_vi_count =
1250*49ef7e06SGarrett D'Amore MAX(max_evq_count, MAX(max_rxq_count, max_txq_count));
1251*49ef7e06SGarrett D'Amore
1252*49ef7e06SGarrett D'Amore /*
1253*49ef7e06SGarrett D'Amore * Check limits for sub-allocated piobuf blocks.
1254*49ef7e06SGarrett D'Amore * PIO is optional, so don't fail if the limits are incorrect.
1255*49ef7e06SGarrett D'Amore */
1256*49ef7e06SGarrett D'Amore if ((encp->enc_piobuf_size == 0) ||
1257*49ef7e06SGarrett D'Amore (encp->enc_piobuf_limit == 0) ||
1258*49ef7e06SGarrett D'Amore (edlp->edl_min_pio_alloc_size == 0) ||
1259*49ef7e06SGarrett D'Amore (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) {
1260*49ef7e06SGarrett D'Amore /* Disable PIO */
1261*49ef7e06SGarrett D'Amore edcp->edc_max_piobuf_count = 0;
1262*49ef7e06SGarrett D'Amore edcp->edc_pio_alloc_size = 0;
1263*49ef7e06SGarrett D'Amore } else {
1264*49ef7e06SGarrett D'Amore uint32_t blk_size, blk_count, blks_per_piobuf;
1265*49ef7e06SGarrett D'Amore
1266*49ef7e06SGarrett D'Amore blk_size =
1267*49ef7e06SGarrett D'Amore MAX(edlp->edl_min_pio_alloc_size,
1268*49ef7e06SGarrett D'Amore encp->enc_piobuf_min_alloc_size);
1269*49ef7e06SGarrett D'Amore
1270*49ef7e06SGarrett D'Amore blks_per_piobuf = encp->enc_piobuf_size / blk_size;
1271*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(blks_per_piobuf, <=, 32);
1272*49ef7e06SGarrett D'Amore
1273*49ef7e06SGarrett D'Amore blk_count = (encp->enc_piobuf_limit * blks_per_piobuf);
1274*49ef7e06SGarrett D'Amore
1275*49ef7e06SGarrett D'Amore /* A zero max pio alloc count means unlimited */
1276*49ef7e06SGarrett D'Amore if ((edlp->edl_max_pio_alloc_count > 0) &&
1277*49ef7e06SGarrett D'Amore (edlp->edl_max_pio_alloc_count < blk_count)) {
1278*49ef7e06SGarrett D'Amore blk_count = edlp->edl_max_pio_alloc_count;
1279*49ef7e06SGarrett D'Amore }
1280*49ef7e06SGarrett D'Amore
1281*49ef7e06SGarrett D'Amore edcp->edc_pio_alloc_size = blk_size;
1282*49ef7e06SGarrett D'Amore edcp->edc_max_piobuf_count =
1283*49ef7e06SGarrett D'Amore (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf;
1284*49ef7e06SGarrett D'Amore }
1285*49ef7e06SGarrett D'Amore
1286*49ef7e06SGarrett D'Amore return (0);
1287*49ef7e06SGarrett D'Amore
1288*49ef7e06SGarrett D'Amore fail1:
1289*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
1290*49ef7e06SGarrett D'Amore
1291*49ef7e06SGarrett D'Amore return (rc);
1292*49ef7e06SGarrett D'Amore }
1293*49ef7e06SGarrett D'Amore
1294*49ef7e06SGarrett D'Amore
1295*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_nic_reset(__in efx_nic_t * enp)1296*49ef7e06SGarrett D'Amore ef10_nic_reset(
1297*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
1298*49ef7e06SGarrett D'Amore {
1299*49ef7e06SGarrett D'Amore efx_mcdi_req_t req;
1300*49ef7e06SGarrett D'Amore uint8_t payload[MAX(MC_CMD_ENTITY_RESET_IN_LEN,
1301*49ef7e06SGarrett D'Amore MC_CMD_ENTITY_RESET_OUT_LEN)];
1302*49ef7e06SGarrett D'Amore efx_rc_t rc;
1303*49ef7e06SGarrett D'Amore
1304*49ef7e06SGarrett D'Amore /* ef10_nic_reset() is called to recover from BADASSERT failures. */
1305*49ef7e06SGarrett D'Amore if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1306*49ef7e06SGarrett D'Amore goto fail1;
1307*49ef7e06SGarrett D'Amore if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1308*49ef7e06SGarrett D'Amore goto fail2;
1309*49ef7e06SGarrett D'Amore
1310*49ef7e06SGarrett D'Amore (void) memset(payload, 0, sizeof (payload));
1311*49ef7e06SGarrett D'Amore req.emr_cmd = MC_CMD_ENTITY_RESET;
1312*49ef7e06SGarrett D'Amore req.emr_in_buf = payload;
1313*49ef7e06SGarrett D'Amore req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN;
1314*49ef7e06SGarrett D'Amore req.emr_out_buf = payload;
1315*49ef7e06SGarrett D'Amore req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN;
1316*49ef7e06SGarrett D'Amore
1317*49ef7e06SGarrett D'Amore MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG,
1318*49ef7e06SGarrett D'Amore ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1);
1319*49ef7e06SGarrett D'Amore
1320*49ef7e06SGarrett D'Amore efx_mcdi_execute(enp, &req);
1321*49ef7e06SGarrett D'Amore
1322*49ef7e06SGarrett D'Amore if (req.emr_rc != 0) {
1323*49ef7e06SGarrett D'Amore rc = req.emr_rc;
1324*49ef7e06SGarrett D'Amore goto fail3;
1325*49ef7e06SGarrett D'Amore }
1326*49ef7e06SGarrett D'Amore
1327*49ef7e06SGarrett D'Amore /* Clear RX/TX DMA queue errors */
1328*49ef7e06SGarrett D'Amore enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR);
1329*49ef7e06SGarrett D'Amore
1330*49ef7e06SGarrett D'Amore return (0);
1331*49ef7e06SGarrett D'Amore
1332*49ef7e06SGarrett D'Amore fail3:
1333*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail3);
1334*49ef7e06SGarrett D'Amore fail2:
1335*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
1336*49ef7e06SGarrett D'Amore fail1:
1337*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
1338*49ef7e06SGarrett D'Amore
1339*49ef7e06SGarrett D'Amore return (rc);
1340*49ef7e06SGarrett D'Amore }
1341*49ef7e06SGarrett D'Amore
1342*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_nic_init(__in efx_nic_t * enp)1343*49ef7e06SGarrett D'Amore ef10_nic_init(
1344*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
1345*49ef7e06SGarrett D'Amore {
1346*49ef7e06SGarrett D'Amore efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1347*49ef7e06SGarrett D'Amore uint32_t min_vi_count, max_vi_count;
1348*49ef7e06SGarrett D'Amore uint32_t vi_count, vi_base, vi_shift;
1349*49ef7e06SGarrett D'Amore uint32_t i;
1350*49ef7e06SGarrett D'Amore uint32_t retry;
1351*49ef7e06SGarrett D'Amore uint32_t delay_us;
1352*49ef7e06SGarrett D'Amore efx_rc_t rc;
1353*49ef7e06SGarrett D'Amore
1354*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1355*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
1356*49ef7e06SGarrett D'Amore
1357*49ef7e06SGarrett D'Amore /* Enable reporting of some events (e.g. link change) */
1358*49ef7e06SGarrett D'Amore if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
1359*49ef7e06SGarrett D'Amore goto fail1;
1360*49ef7e06SGarrett D'Amore
1361*49ef7e06SGarrett D'Amore /* Allocate (optional) on-chip PIO buffers */
1362*49ef7e06SGarrett D'Amore ef10_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count);
1363*49ef7e06SGarrett D'Amore
1364*49ef7e06SGarrett D'Amore /*
1365*49ef7e06SGarrett D'Amore * For best performance, PIO writes should use a write-combined
1366*49ef7e06SGarrett D'Amore * (WC) memory mapping. Using a separate WC mapping for the PIO
1367*49ef7e06SGarrett D'Amore * aperture of each VI would be a burden to drivers (and not
1368*49ef7e06SGarrett D'Amore * possible if the host page size is >4Kbyte).
1369*49ef7e06SGarrett D'Amore *
1370*49ef7e06SGarrett D'Amore * To avoid this we use a single uncached (UC) mapping for VI
1371*49ef7e06SGarrett D'Amore * register access, and a single WC mapping for extra VIs used
1372*49ef7e06SGarrett D'Amore * for PIO writes.
1373*49ef7e06SGarrett D'Amore *
1374*49ef7e06SGarrett D'Amore * Each piobuf must be linked to a VI in the WC mapping, and to
1375*49ef7e06SGarrett D'Amore * each VI that is using a sub-allocated block from the piobuf.
1376*49ef7e06SGarrett D'Amore */
1377*49ef7e06SGarrett D'Amore min_vi_count = edcp->edc_min_vi_count;
1378*49ef7e06SGarrett D'Amore max_vi_count =
1379*49ef7e06SGarrett D'Amore edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count;
1380*49ef7e06SGarrett D'Amore
1381*49ef7e06SGarrett D'Amore /* Ensure that the previously attached driver's VIs are freed */
1382*49ef7e06SGarrett D'Amore if ((rc = efx_mcdi_free_vis(enp)) != 0)
1383*49ef7e06SGarrett D'Amore goto fail2;
1384*49ef7e06SGarrett D'Amore
1385*49ef7e06SGarrett D'Amore /*
1386*49ef7e06SGarrett D'Amore * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this
1387*49ef7e06SGarrett D'Amore * fails then retrying the request for fewer VI resources may succeed.
1388*49ef7e06SGarrett D'Amore */
1389*49ef7e06SGarrett D'Amore vi_count = 0;
1390*49ef7e06SGarrett D'Amore if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count,
1391*49ef7e06SGarrett D'Amore &vi_base, &vi_count, &vi_shift)) != 0)
1392*49ef7e06SGarrett D'Amore goto fail3;
1393*49ef7e06SGarrett D'Amore
1394*49ef7e06SGarrett D'Amore EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count);
1395*49ef7e06SGarrett D'Amore
1396*49ef7e06SGarrett D'Amore if (vi_count < min_vi_count) {
1397*49ef7e06SGarrett D'Amore rc = ENOMEM;
1398*49ef7e06SGarrett D'Amore goto fail4;
1399*49ef7e06SGarrett D'Amore }
1400*49ef7e06SGarrett D'Amore
1401*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_vi_base = vi_base;
1402*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_vi_count = vi_count;
1403*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_vi_shift = vi_shift;
1404*49ef7e06SGarrett D'Amore
1405*49ef7e06SGarrett D'Amore if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) {
1406*49ef7e06SGarrett D'Amore /* Not enough extra VIs to map piobufs */
1407*49ef7e06SGarrett D'Amore ef10_nic_free_piobufs(enp);
1408*49ef7e06SGarrett D'Amore }
1409*49ef7e06SGarrett D'Amore
1410*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_pio_write_vi_base =
1411*49ef7e06SGarrett D'Amore vi_count - enp->en_arch.ef10.ena_piobuf_count;
1412*49ef7e06SGarrett D'Amore
1413*49ef7e06SGarrett D'Amore /* Save UC memory mapping details */
1414*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_uc_mem_map_offset = 0;
1415*49ef7e06SGarrett D'Amore if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1416*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_uc_mem_map_size =
1417*49ef7e06SGarrett D'Amore (ER_DZ_TX_PIOBUF_STEP *
1418*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_pio_write_vi_base);
1419*49ef7e06SGarrett D'Amore } else {
1420*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_uc_mem_map_size =
1421*49ef7e06SGarrett D'Amore (ER_DZ_TX_PIOBUF_STEP *
1422*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_vi_count);
1423*49ef7e06SGarrett D'Amore }
1424*49ef7e06SGarrett D'Amore
1425*49ef7e06SGarrett D'Amore /* Save WC memory mapping details */
1426*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_wc_mem_map_offset =
1427*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_uc_mem_map_offset +
1428*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_uc_mem_map_size;
1429*49ef7e06SGarrett D'Amore
1430*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_wc_mem_map_size =
1431*49ef7e06SGarrett D'Amore (ER_DZ_TX_PIOBUF_STEP *
1432*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_piobuf_count);
1433*49ef7e06SGarrett D'Amore
1434*49ef7e06SGarrett D'Amore /* Link piobufs to extra VIs in WC mapping */
1435*49ef7e06SGarrett D'Amore if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1436*49ef7e06SGarrett D'Amore for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1437*49ef7e06SGarrett D'Amore rc = efx_mcdi_link_piobuf(enp,
1438*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_pio_write_vi_base + i,
1439*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_piobuf_handle[i]);
1440*49ef7e06SGarrett D'Amore if (rc != 0)
1441*49ef7e06SGarrett D'Amore break;
1442*49ef7e06SGarrett D'Amore }
1443*49ef7e06SGarrett D'Amore }
1444*49ef7e06SGarrett D'Amore
1445*49ef7e06SGarrett D'Amore /*
1446*49ef7e06SGarrett D'Amore * Allocate a vAdaptor attached to our upstream vPort/pPort.
1447*49ef7e06SGarrett D'Amore *
1448*49ef7e06SGarrett D'Amore * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF
1449*49ef7e06SGarrett D'Amore * driver has yet to bring up the EVB port. See bug 56147. In this case,
1450*49ef7e06SGarrett D'Amore * retry the request several times after waiting a while. The wait time
1451*49ef7e06SGarrett D'Amore * between retries starts small (10ms) and exponentially increases.
1452*49ef7e06SGarrett D'Amore * Total wait time is a little over two seconds. Retry logic in the
1453*49ef7e06SGarrett D'Amore * client driver may mean this whole loop is repeated if it continues to
1454*49ef7e06SGarrett D'Amore * fail.
1455*49ef7e06SGarrett D'Amore */
1456*49ef7e06SGarrett D'Amore retry = 0;
1457*49ef7e06SGarrett D'Amore delay_us = 10000;
1458*49ef7e06SGarrett D'Amore while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) {
1459*49ef7e06SGarrett D'Amore if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) ||
1460*49ef7e06SGarrett D'Amore (rc != ENOENT)) {
1461*49ef7e06SGarrett D'Amore /*
1462*49ef7e06SGarrett D'Amore * Do not retry alloc for PF, or for other errors on
1463*49ef7e06SGarrett D'Amore * a VF.
1464*49ef7e06SGarrett D'Amore */
1465*49ef7e06SGarrett D'Amore goto fail5;
1466*49ef7e06SGarrett D'Amore }
1467*49ef7e06SGarrett D'Amore
1468*49ef7e06SGarrett D'Amore /* VF startup before PF is ready. Retry allocation. */
1469*49ef7e06SGarrett D'Amore if (retry > 5) {
1470*49ef7e06SGarrett D'Amore /* Too many attempts */
1471*49ef7e06SGarrett D'Amore rc = EINVAL;
1472*49ef7e06SGarrett D'Amore goto fail6;
1473*49ef7e06SGarrett D'Amore }
1474*49ef7e06SGarrett D'Amore EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry);
1475*49ef7e06SGarrett D'Amore EFSYS_SLEEP(delay_us);
1476*49ef7e06SGarrett D'Amore retry++;
1477*49ef7e06SGarrett D'Amore if (delay_us < 500000)
1478*49ef7e06SGarrett D'Amore delay_us <<= 2;
1479*49ef7e06SGarrett D'Amore }
1480*49ef7e06SGarrett D'Amore
1481*49ef7e06SGarrett D'Amore enp->en_vport_id = EVB_PORT_ID_ASSIGNED;
1482*49ef7e06SGarrett D'Amore enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2;
1483*49ef7e06SGarrett D'Amore
1484*49ef7e06SGarrett D'Amore return (0);
1485*49ef7e06SGarrett D'Amore
1486*49ef7e06SGarrett D'Amore fail6:
1487*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail6);
1488*49ef7e06SGarrett D'Amore fail5:
1489*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail5);
1490*49ef7e06SGarrett D'Amore fail4:
1491*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail4);
1492*49ef7e06SGarrett D'Amore fail3:
1493*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail3);
1494*49ef7e06SGarrett D'Amore fail2:
1495*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2);
1496*49ef7e06SGarrett D'Amore
1497*49ef7e06SGarrett D'Amore ef10_nic_free_piobufs(enp);
1498*49ef7e06SGarrett D'Amore
1499*49ef7e06SGarrett D'Amore fail1:
1500*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
1501*49ef7e06SGarrett D'Amore
1502*49ef7e06SGarrett D'Amore return (rc);
1503*49ef7e06SGarrett D'Amore }
1504*49ef7e06SGarrett D'Amore
1505*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_nic_get_vi_pool(__in efx_nic_t * enp,__out uint32_t * vi_countp)1506*49ef7e06SGarrett D'Amore ef10_nic_get_vi_pool(
1507*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
1508*49ef7e06SGarrett D'Amore __out uint32_t *vi_countp)
1509*49ef7e06SGarrett D'Amore {
1510*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1511*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
1512*49ef7e06SGarrett D'Amore
1513*49ef7e06SGarrett D'Amore /*
1514*49ef7e06SGarrett D'Amore * Report VIs that the client driver can use.
1515*49ef7e06SGarrett D'Amore * Do not include VIs used for PIO buffer writes.
1516*49ef7e06SGarrett D'Amore */
1517*49ef7e06SGarrett D'Amore *vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base;
1518*49ef7e06SGarrett D'Amore
1519*49ef7e06SGarrett D'Amore return (0);
1520*49ef7e06SGarrett D'Amore }
1521*49ef7e06SGarrett D'Amore
1522*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_nic_get_bar_region(__in efx_nic_t * enp,__in efx_nic_region_t region,__out uint32_t * offsetp,__out size_t * sizep)1523*49ef7e06SGarrett D'Amore ef10_nic_get_bar_region(
1524*49ef7e06SGarrett D'Amore __in efx_nic_t *enp,
1525*49ef7e06SGarrett D'Amore __in efx_nic_region_t region,
1526*49ef7e06SGarrett D'Amore __out uint32_t *offsetp,
1527*49ef7e06SGarrett D'Amore __out size_t *sizep)
1528*49ef7e06SGarrett D'Amore {
1529*49ef7e06SGarrett D'Amore efx_rc_t rc;
1530*49ef7e06SGarrett D'Amore
1531*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1532*49ef7e06SGarrett D'Amore enp->en_family == EFX_FAMILY_MEDFORD);
1533*49ef7e06SGarrett D'Amore
1534*49ef7e06SGarrett D'Amore /*
1535*49ef7e06SGarrett D'Amore * TODO: Specify host memory mapping alignment and granularity
1536*49ef7e06SGarrett D'Amore * in efx_drv_limits_t so that they can be taken into account
1537*49ef7e06SGarrett D'Amore * when allocating extra VIs for PIO writes.
1538*49ef7e06SGarrett D'Amore */
1539*49ef7e06SGarrett D'Amore switch (region) {
1540*49ef7e06SGarrett D'Amore case EFX_REGION_VI:
1541*49ef7e06SGarrett D'Amore /* UC mapped memory BAR region for VI registers */
1542*49ef7e06SGarrett D'Amore *offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset;
1543*49ef7e06SGarrett D'Amore *sizep = enp->en_arch.ef10.ena_uc_mem_map_size;
1544*49ef7e06SGarrett D'Amore break;
1545*49ef7e06SGarrett D'Amore
1546*49ef7e06SGarrett D'Amore case EFX_REGION_PIO_WRITE_VI:
1547*49ef7e06SGarrett D'Amore /* WC mapped memory BAR region for piobuf writes */
1548*49ef7e06SGarrett D'Amore *offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset;
1549*49ef7e06SGarrett D'Amore *sizep = enp->en_arch.ef10.ena_wc_mem_map_size;
1550*49ef7e06SGarrett D'Amore break;
1551*49ef7e06SGarrett D'Amore
1552*49ef7e06SGarrett D'Amore default:
1553*49ef7e06SGarrett D'Amore rc = EINVAL;
1554*49ef7e06SGarrett D'Amore goto fail1;
1555*49ef7e06SGarrett D'Amore }
1556*49ef7e06SGarrett D'Amore
1557*49ef7e06SGarrett D'Amore return (0);
1558*49ef7e06SGarrett D'Amore
1559*49ef7e06SGarrett D'Amore fail1:
1560*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
1561*49ef7e06SGarrett D'Amore
1562*49ef7e06SGarrett D'Amore return (rc);
1563*49ef7e06SGarrett D'Amore }
1564*49ef7e06SGarrett D'Amore
1565*49ef7e06SGarrett D'Amore void
ef10_nic_fini(__in efx_nic_t * enp)1566*49ef7e06SGarrett D'Amore ef10_nic_fini(
1567*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
1568*49ef7e06SGarrett D'Amore {
1569*49ef7e06SGarrett D'Amore uint32_t i;
1570*49ef7e06SGarrett D'Amore efx_rc_t rc;
1571*49ef7e06SGarrett D'Amore
1572*49ef7e06SGarrett D'Amore (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id);
1573*49ef7e06SGarrett D'Amore enp->en_vport_id = 0;
1574*49ef7e06SGarrett D'Amore
1575*49ef7e06SGarrett D'Amore /* Unlink piobufs from extra VIs in WC mapping */
1576*49ef7e06SGarrett D'Amore if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1577*49ef7e06SGarrett D'Amore for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1578*49ef7e06SGarrett D'Amore rc = efx_mcdi_unlink_piobuf(enp,
1579*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_pio_write_vi_base + i);
1580*49ef7e06SGarrett D'Amore if (rc != 0)
1581*49ef7e06SGarrett D'Amore break;
1582*49ef7e06SGarrett D'Amore }
1583*49ef7e06SGarrett D'Amore }
1584*49ef7e06SGarrett D'Amore
1585*49ef7e06SGarrett D'Amore ef10_nic_free_piobufs(enp);
1586*49ef7e06SGarrett D'Amore
1587*49ef7e06SGarrett D'Amore (void) efx_mcdi_free_vis(enp);
1588*49ef7e06SGarrett D'Amore enp->en_arch.ef10.ena_vi_count = 0;
1589*49ef7e06SGarrett D'Amore }
1590*49ef7e06SGarrett D'Amore
1591*49ef7e06SGarrett D'Amore void
ef10_nic_unprobe(__in efx_nic_t * enp)1592*49ef7e06SGarrett D'Amore ef10_nic_unprobe(
1593*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
1594*49ef7e06SGarrett D'Amore {
1595*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MON_STATS
1596*49ef7e06SGarrett D'Amore mcdi_mon_cfg_free(enp);
1597*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_MON_STATS */
1598*49ef7e06SGarrett D'Amore (void) efx_mcdi_drv_attach(enp, B_FALSE);
1599*49ef7e06SGarrett D'Amore }
1600*49ef7e06SGarrett D'Amore
1601*49ef7e06SGarrett D'Amore #if EFSYS_OPT_DIAG
1602*49ef7e06SGarrett D'Amore
1603*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t
ef10_nic_register_test(__in efx_nic_t * enp)1604*49ef7e06SGarrett D'Amore ef10_nic_register_test(
1605*49ef7e06SGarrett D'Amore __in efx_nic_t *enp)
1606*49ef7e06SGarrett D'Amore {
1607*49ef7e06SGarrett D'Amore efx_rc_t rc;
1608*49ef7e06SGarrett D'Amore
1609*49ef7e06SGarrett D'Amore /* FIXME */
1610*49ef7e06SGarrett D'Amore _NOTE(ARGUNUSED(enp))
1611*49ef7e06SGarrett D'Amore _NOTE(CONSTANTCONDITION)
1612*49ef7e06SGarrett D'Amore if (B_FALSE) {
1613*49ef7e06SGarrett D'Amore rc = ENOTSUP;
1614*49ef7e06SGarrett D'Amore goto fail1;
1615*49ef7e06SGarrett D'Amore }
1616*49ef7e06SGarrett D'Amore /* FIXME */
1617*49ef7e06SGarrett D'Amore
1618*49ef7e06SGarrett D'Amore return (0);
1619*49ef7e06SGarrett D'Amore
1620*49ef7e06SGarrett D'Amore fail1:
1621*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc);
1622*49ef7e06SGarrett D'Amore
1623*49ef7e06SGarrett D'Amore return (rc);
1624*49ef7e06SGarrett D'Amore }
1625*49ef7e06SGarrett D'Amore
1626*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_DIAG */
1627*49ef7e06SGarrett D'Amore
1628*49ef7e06SGarrett D'Amore
1629*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
1630