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