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