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