xref: /freebsd/sys/dev/sfxge/common/ef10_nic.c (revision e27abb6689c5733dd08ce240d5402a0de3a42254)
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 	if (encp->enc_rx_batching_enabled)
1007 		encp->enc_rx_batch_max = 16;
1008 
1009 	/* Check if the firmware supports disabling scatter on RXQs */
1010 	encp->enc_rx_disable_scatter_supported =
1011 	    CAP_FLAG(flags, RX_DISABLE_SCATTER) ? B_TRUE : B_FALSE;
1012 
1013 	/* Check if the firmware supports set mac with running filters */
1014 	encp->enc_allow_set_mac_with_installed_filters =
1015 	    CAP_FLAG(flags, VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED) ?
1016 	    B_TRUE : B_FALSE;
1017 
1018 	/*
1019 	 * Check if firmware supports the extended MC_CMD_SET_MAC, which allows
1020 	 * specifying which parameters to configure.
1021 	 */
1022 	encp->enc_enhanced_set_mac_supported =
1023 		CAP_FLAG(flags, SET_MAC_ENHANCED) ? B_TRUE : B_FALSE;
1024 
1025 #undef CAP_FLAG
1026 #undef CAP_FLAG2
1027 
1028 	return (0);
1029 
1030 fail2:
1031 	EFSYS_PROBE(fail2);
1032 fail1:
1033 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1034 
1035 	return (rc);
1036 }
1037 
1038 
1039 #define	EF10_LEGACY_PF_PRIVILEGE_MASK					\
1040 	(MC_CMD_PRIVILEGE_MASK_IN_GRP_ADMIN			|	\
1041 	MC_CMD_PRIVILEGE_MASK_IN_GRP_LINK			|	\
1042 	MC_CMD_PRIVILEGE_MASK_IN_GRP_ONLOAD			|	\
1043 	MC_CMD_PRIVILEGE_MASK_IN_GRP_PTP			|	\
1044 	MC_CMD_PRIVILEGE_MASK_IN_GRP_INSECURE_FILTERS		|	\
1045 	MC_CMD_PRIVILEGE_MASK_IN_GRP_MAC_SPOOFING		|	\
1046 	MC_CMD_PRIVILEGE_MASK_IN_GRP_UNICAST			|	\
1047 	MC_CMD_PRIVILEGE_MASK_IN_GRP_MULTICAST			|	\
1048 	MC_CMD_PRIVILEGE_MASK_IN_GRP_BROADCAST			|	\
1049 	MC_CMD_PRIVILEGE_MASK_IN_GRP_ALL_MULTICAST		|	\
1050 	MC_CMD_PRIVILEGE_MASK_IN_GRP_PROMISCUOUS)
1051 
1052 #define	EF10_LEGACY_VF_PRIVILEGE_MASK	0
1053 
1054 
1055 	__checkReturn		efx_rc_t
1056 ef10_get_privilege_mask(
1057 	__in			efx_nic_t *enp,
1058 	__out			uint32_t *maskp)
1059 {
1060 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1061 	uint32_t mask;
1062 	efx_rc_t rc;
1063 
1064 	if ((rc = efx_mcdi_privilege_mask(enp, encp->enc_pf, encp->enc_vf,
1065 					    &mask)) != 0) {
1066 		if (rc != ENOTSUP)
1067 			goto fail1;
1068 
1069 		/* Fallback for old firmware without privilege mask support */
1070 		if (EFX_PCI_FUNCTION_IS_PF(encp)) {
1071 			/* Assume PF has admin privilege */
1072 			mask = EF10_LEGACY_PF_PRIVILEGE_MASK;
1073 		} else {
1074 			/* VF is always unprivileged by default */
1075 			mask = EF10_LEGACY_VF_PRIVILEGE_MASK;
1076 		}
1077 	}
1078 
1079 	*maskp = mask;
1080 
1081 	return (0);
1082 
1083 fail1:
1084 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1085 
1086 	return (rc);
1087 }
1088 
1089 
1090 /*
1091  * The external port mapping is a one-based numbering of the external
1092  * connectors on the board. It does not distinguish off-board separated
1093  * outputs such as multi-headed cables.
1094  * The number of ports that map to each external port connector
1095  * on the board is determined by the chip family and the port modes to
1096  * which the NIC can be configured. The mapping table lists modes with
1097  * port numbering requirements in increasing order.
1098  */
1099 static struct {
1100 	efx_family_t	family;
1101 	uint32_t	modes_mask;
1102 	uint32_t	stride;
1103 }	__ef10_external_port_mappings[] = {
1104 	/* Supported modes requiring 1 output per port */
1105 	{
1106 		EFX_FAMILY_HUNTINGTON,
1107 		(1 << TLV_PORT_MODE_10G) |
1108 		(1 << TLV_PORT_MODE_10G_10G) |
1109 		(1 << TLV_PORT_MODE_10G_10G_10G_10G),
1110 		1
1111 	},
1112 	{
1113 		EFX_FAMILY_MEDFORD,
1114 		(1 << TLV_PORT_MODE_10G) |
1115 		(1 << TLV_PORT_MODE_10G_10G) |
1116 		(1 << TLV_PORT_MODE_10G_10G_10G_10G),
1117 		1
1118 	},
1119 	/* Supported modes requiring 2 outputs per port */
1120 	{
1121 		EFX_FAMILY_HUNTINGTON,
1122 		(1 << TLV_PORT_MODE_40G) |
1123 		(1 << TLV_PORT_MODE_40G_40G) |
1124 		(1 << TLV_PORT_MODE_40G_10G_10G) |
1125 		(1 << TLV_PORT_MODE_10G_10G_40G),
1126 		2
1127 	},
1128 	{
1129 		EFX_FAMILY_MEDFORD,
1130 		(1 << TLV_PORT_MODE_40G) |
1131 		(1 << TLV_PORT_MODE_40G_40G) |
1132 		(1 << TLV_PORT_MODE_40G_10G_10G) |
1133 		(1 << TLV_PORT_MODE_10G_10G_40G),
1134 		2
1135 	},
1136 	/* Supported modes requiring 4 outputs per port */
1137 	{
1138 		EFX_FAMILY_MEDFORD,
1139 		(1 << TLV_PORT_MODE_10G_10G_10G_10G_Q) |
1140 		(1 << TLV_PORT_MODE_10G_10G_10G_10G_Q2),
1141 		4
1142 	},
1143 };
1144 
1145 	__checkReturn	efx_rc_t
1146 ef10_external_port_mapping(
1147 	__in		efx_nic_t *enp,
1148 	__in		uint32_t port,
1149 	__out		uint8_t *external_portp)
1150 {
1151 	efx_rc_t rc;
1152 	int i;
1153 	uint32_t port_modes;
1154 	uint32_t matches;
1155 	uint32_t stride = 1; /* default 1-1 mapping */
1156 
1157 	if ((rc = efx_mcdi_get_port_modes(enp, &port_modes, NULL)) != 0) {
1158 		/* No port mode information available - use default mapping */
1159 		goto out;
1160 	}
1161 
1162 	/*
1163 	 * Infer the internal port -> external port mapping from
1164 	 * the possible port modes for this NIC.
1165 	 */
1166 	for (i = 0; i < EFX_ARRAY_SIZE(__ef10_external_port_mappings); ++i) {
1167 		if (__ef10_external_port_mappings[i].family !=
1168 		    enp->en_family)
1169 			continue;
1170 		matches = (__ef10_external_port_mappings[i].modes_mask &
1171 		    port_modes);
1172 		if (matches != 0) {
1173 			stride = __ef10_external_port_mappings[i].stride;
1174 			port_modes &= ~matches;
1175 		}
1176 	}
1177 
1178 	if (port_modes != 0) {
1179 		/* Some advertised modes are not supported */
1180 		rc = ENOTSUP;
1181 		goto fail1;
1182 	}
1183 
1184 out:
1185 	/*
1186 	 * Scale as required by last matched mode and then convert to
1187 	 * one-based numbering
1188 	 */
1189 	*external_portp = (uint8_t)(port / stride) + 1;
1190 	return (0);
1191 
1192 fail1:
1193 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1194 
1195 	return (rc);
1196 }
1197 
1198 
1199 	__checkReturn	efx_rc_t
1200 ef10_nic_probe(
1201 	__in		efx_nic_t *enp)
1202 {
1203 	const efx_nic_ops_t *enop = enp->en_enop;
1204 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1205 	efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1206 	efx_rc_t rc;
1207 
1208 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1209 		    enp->en_family == EFX_FAMILY_MEDFORD);
1210 
1211 	/* Read and clear any assertion state */
1212 	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1213 		goto fail1;
1214 
1215 	/* Exit the assertion handler */
1216 	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1217 		if (rc != EACCES)
1218 			goto fail2;
1219 
1220 	if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
1221 		goto fail3;
1222 
1223 	if ((rc = enop->eno_board_cfg(enp)) != 0)
1224 		if (rc != EACCES)
1225 			goto fail4;
1226 
1227 	/*
1228 	 * Set default driver config limits (based on board config).
1229 	 *
1230 	 * FIXME: For now allocate a fixed number of VIs which is likely to be
1231 	 * sufficient and small enough to allow multiple functions on the same
1232 	 * port.
1233 	 */
1234 	edcp->edc_min_vi_count = edcp->edc_max_vi_count =
1235 	    MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit));
1236 
1237 	/* The client driver must configure and enable PIO buffer support */
1238 	edcp->edc_max_piobuf_count = 0;
1239 	edcp->edc_pio_alloc_size = 0;
1240 
1241 #if EFSYS_OPT_MAC_STATS
1242 	/* Wipe the MAC statistics */
1243 	if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
1244 		goto fail5;
1245 #endif
1246 
1247 #if EFSYS_OPT_LOOPBACK
1248 	if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
1249 		goto fail6;
1250 #endif
1251 
1252 #if EFSYS_OPT_MON_STATS
1253 	if ((rc = mcdi_mon_cfg_build(enp)) != 0) {
1254 		/* Unprivileged functions do not have access to sensors */
1255 		if (rc != EACCES)
1256 			goto fail7;
1257 	}
1258 #endif
1259 
1260 	encp->enc_features = enp->en_features;
1261 
1262 	return (0);
1263 
1264 #if EFSYS_OPT_MON_STATS
1265 fail7:
1266 	EFSYS_PROBE(fail7);
1267 #endif
1268 #if EFSYS_OPT_LOOPBACK
1269 fail6:
1270 	EFSYS_PROBE(fail6);
1271 #endif
1272 #if EFSYS_OPT_MAC_STATS
1273 fail5:
1274 	EFSYS_PROBE(fail5);
1275 #endif
1276 fail4:
1277 	EFSYS_PROBE(fail4);
1278 fail3:
1279 	EFSYS_PROBE(fail3);
1280 fail2:
1281 	EFSYS_PROBE(fail2);
1282 fail1:
1283 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1284 
1285 	return (rc);
1286 }
1287 
1288 	__checkReturn	efx_rc_t
1289 ef10_nic_set_drv_limits(
1290 	__inout		efx_nic_t *enp,
1291 	__in		efx_drv_limits_t *edlp)
1292 {
1293 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1294 	efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1295 	uint32_t min_evq_count, max_evq_count;
1296 	uint32_t min_rxq_count, max_rxq_count;
1297 	uint32_t min_txq_count, max_txq_count;
1298 	efx_rc_t rc;
1299 
1300 	if (edlp == NULL) {
1301 		rc = EINVAL;
1302 		goto fail1;
1303 	}
1304 
1305 	/* Get minimum required and maximum usable VI limits */
1306 	min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit);
1307 	min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit);
1308 	min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit);
1309 
1310 	edcp->edc_min_vi_count =
1311 	    MAX(min_evq_count, MAX(min_rxq_count, min_txq_count));
1312 
1313 	max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit);
1314 	max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit);
1315 	max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit);
1316 
1317 	edcp->edc_max_vi_count =
1318 	    MAX(max_evq_count, MAX(max_rxq_count, max_txq_count));
1319 
1320 	/*
1321 	 * Check limits for sub-allocated piobuf blocks.
1322 	 * PIO is optional, so don't fail if the limits are incorrect.
1323 	 */
1324 	if ((encp->enc_piobuf_size == 0) ||
1325 	    (encp->enc_piobuf_limit == 0) ||
1326 	    (edlp->edl_min_pio_alloc_size == 0) ||
1327 	    (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) {
1328 		/* Disable PIO */
1329 		edcp->edc_max_piobuf_count = 0;
1330 		edcp->edc_pio_alloc_size = 0;
1331 	} else {
1332 		uint32_t blk_size, blk_count, blks_per_piobuf;
1333 
1334 		blk_size =
1335 		    MAX(edlp->edl_min_pio_alloc_size,
1336 			    encp->enc_piobuf_min_alloc_size);
1337 
1338 		blks_per_piobuf = encp->enc_piobuf_size / blk_size;
1339 		EFSYS_ASSERT3U(blks_per_piobuf, <=, 32);
1340 
1341 		blk_count = (encp->enc_piobuf_limit * blks_per_piobuf);
1342 
1343 		/* A zero max pio alloc count means unlimited */
1344 		if ((edlp->edl_max_pio_alloc_count > 0) &&
1345 		    (edlp->edl_max_pio_alloc_count < blk_count)) {
1346 			blk_count = edlp->edl_max_pio_alloc_count;
1347 		}
1348 
1349 		edcp->edc_pio_alloc_size = blk_size;
1350 		edcp->edc_max_piobuf_count =
1351 		    (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf;
1352 	}
1353 
1354 	return (0);
1355 
1356 fail1:
1357 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1358 
1359 	return (rc);
1360 }
1361 
1362 
1363 	__checkReturn	efx_rc_t
1364 ef10_nic_reset(
1365 	__in		efx_nic_t *enp)
1366 {
1367 	efx_mcdi_req_t req;
1368 	uint8_t payload[MAX(MC_CMD_ENTITY_RESET_IN_LEN,
1369 			    MC_CMD_ENTITY_RESET_OUT_LEN)];
1370 	efx_rc_t rc;
1371 
1372 	/* ef10_nic_reset() is called to recover from BADASSERT failures. */
1373 	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1374 		goto fail1;
1375 	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1376 		goto fail2;
1377 
1378 	(void) memset(payload, 0, sizeof (payload));
1379 	req.emr_cmd = MC_CMD_ENTITY_RESET;
1380 	req.emr_in_buf = payload;
1381 	req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN;
1382 	req.emr_out_buf = payload;
1383 	req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN;
1384 
1385 	MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG,
1386 	    ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1);
1387 
1388 	efx_mcdi_execute(enp, &req);
1389 
1390 	if (req.emr_rc != 0) {
1391 		rc = req.emr_rc;
1392 		goto fail3;
1393 	}
1394 
1395 	/* Clear RX/TX DMA queue errors */
1396 	enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR);
1397 
1398 	return (0);
1399 
1400 fail3:
1401 	EFSYS_PROBE(fail3);
1402 fail2:
1403 	EFSYS_PROBE(fail2);
1404 fail1:
1405 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1406 
1407 	return (rc);
1408 }
1409 
1410 	__checkReturn	efx_rc_t
1411 ef10_nic_init(
1412 	__in		efx_nic_t *enp)
1413 {
1414 	efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1415 	uint32_t min_vi_count, max_vi_count;
1416 	uint32_t vi_count, vi_base, vi_shift;
1417 	uint32_t i;
1418 	uint32_t retry;
1419 	uint32_t delay_us;
1420 	efx_rc_t rc;
1421 
1422 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1423 		    enp->en_family == EFX_FAMILY_MEDFORD);
1424 
1425 	/* Enable reporting of some events (e.g. link change) */
1426 	if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
1427 		goto fail1;
1428 
1429 	/* Allocate (optional) on-chip PIO buffers */
1430 	ef10_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count);
1431 
1432 	/*
1433 	 * For best performance, PIO writes should use a write-combined
1434 	 * (WC) memory mapping. Using a separate WC mapping for the PIO
1435 	 * aperture of each VI would be a burden to drivers (and not
1436 	 * possible if the host page size is >4Kbyte).
1437 	 *
1438 	 * To avoid this we use a single uncached (UC) mapping for VI
1439 	 * register access, and a single WC mapping for extra VIs used
1440 	 * for PIO writes.
1441 	 *
1442 	 * Each piobuf must be linked to a VI in the WC mapping, and to
1443 	 * each VI that is using a sub-allocated block from the piobuf.
1444 	 */
1445 	min_vi_count = edcp->edc_min_vi_count;
1446 	max_vi_count =
1447 	    edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count;
1448 
1449 	/* Ensure that the previously attached driver's VIs are freed */
1450 	if ((rc = efx_mcdi_free_vis(enp)) != 0)
1451 		goto fail2;
1452 
1453 	/*
1454 	 * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this
1455 	 * fails then retrying the request for fewer VI resources may succeed.
1456 	 */
1457 	vi_count = 0;
1458 	if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count,
1459 		    &vi_base, &vi_count, &vi_shift)) != 0)
1460 		goto fail3;
1461 
1462 	EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count);
1463 
1464 	if (vi_count < min_vi_count) {
1465 		rc = ENOMEM;
1466 		goto fail4;
1467 	}
1468 
1469 	enp->en_arch.ef10.ena_vi_base = vi_base;
1470 	enp->en_arch.ef10.ena_vi_count = vi_count;
1471 	enp->en_arch.ef10.ena_vi_shift = vi_shift;
1472 
1473 	if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) {
1474 		/* Not enough extra VIs to map piobufs */
1475 		ef10_nic_free_piobufs(enp);
1476 	}
1477 
1478 	enp->en_arch.ef10.ena_pio_write_vi_base =
1479 	    vi_count - enp->en_arch.ef10.ena_piobuf_count;
1480 
1481 	/* Save UC memory mapping details */
1482 	enp->en_arch.ef10.ena_uc_mem_map_offset = 0;
1483 	if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1484 		enp->en_arch.ef10.ena_uc_mem_map_size =
1485 		    (ER_DZ_TX_PIOBUF_STEP *
1486 		    enp->en_arch.ef10.ena_pio_write_vi_base);
1487 	} else {
1488 		enp->en_arch.ef10.ena_uc_mem_map_size =
1489 		    (ER_DZ_TX_PIOBUF_STEP *
1490 		    enp->en_arch.ef10.ena_vi_count);
1491 	}
1492 
1493 	/* Save WC memory mapping details */
1494 	enp->en_arch.ef10.ena_wc_mem_map_offset =
1495 	    enp->en_arch.ef10.ena_uc_mem_map_offset +
1496 	    enp->en_arch.ef10.ena_uc_mem_map_size;
1497 
1498 	enp->en_arch.ef10.ena_wc_mem_map_size =
1499 	    (ER_DZ_TX_PIOBUF_STEP *
1500 	    enp->en_arch.ef10.ena_piobuf_count);
1501 
1502 	/* Link piobufs to extra VIs in WC mapping */
1503 	if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1504 		for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1505 			rc = efx_mcdi_link_piobuf(enp,
1506 			    enp->en_arch.ef10.ena_pio_write_vi_base + i,
1507 			    enp->en_arch.ef10.ena_piobuf_handle[i]);
1508 			if (rc != 0)
1509 				break;
1510 		}
1511 	}
1512 
1513 	/*
1514 	 * Allocate a vAdaptor attached to our upstream vPort/pPort.
1515 	 *
1516 	 * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF
1517 	 * driver has yet to bring up the EVB port. See bug 56147. In this case,
1518 	 * retry the request several times after waiting a while. The wait time
1519 	 * between retries starts small (10ms) and exponentially increases.
1520 	 * Total wait time is a little over two seconds. Retry logic in the
1521 	 * client driver may mean this whole loop is repeated if it continues to
1522 	 * fail.
1523 	 */
1524 	retry = 0;
1525 	delay_us = 10000;
1526 	while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) {
1527 		if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) ||
1528 		    (rc != ENOENT)) {
1529 			/*
1530 			 * Do not retry alloc for PF, or for other errors on
1531 			 * a VF.
1532 			 */
1533 			goto fail5;
1534 		}
1535 
1536 		/* VF startup before PF is ready. Retry allocation. */
1537 		if (retry > 5) {
1538 			/* Too many attempts */
1539 			rc = EINVAL;
1540 			goto fail6;
1541 		}
1542 		EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry);
1543 		EFSYS_SLEEP(delay_us);
1544 		retry++;
1545 		if (delay_us < 500000)
1546 			delay_us <<= 2;
1547 	}
1548 
1549 	enp->en_vport_id = EVB_PORT_ID_ASSIGNED;
1550 	enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2;
1551 
1552 	return (0);
1553 
1554 fail6:
1555 	EFSYS_PROBE(fail6);
1556 fail5:
1557 	EFSYS_PROBE(fail5);
1558 fail4:
1559 	EFSYS_PROBE(fail4);
1560 fail3:
1561 	EFSYS_PROBE(fail3);
1562 fail2:
1563 	EFSYS_PROBE(fail2);
1564 
1565 	ef10_nic_free_piobufs(enp);
1566 
1567 fail1:
1568 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1569 
1570 	return (rc);
1571 }
1572 
1573 	__checkReturn	efx_rc_t
1574 ef10_nic_get_vi_pool(
1575 	__in		efx_nic_t *enp,
1576 	__out		uint32_t *vi_countp)
1577 {
1578 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1579 		    enp->en_family == EFX_FAMILY_MEDFORD);
1580 
1581 	/*
1582 	 * Report VIs that the client driver can use.
1583 	 * Do not include VIs used for PIO buffer writes.
1584 	 */
1585 	*vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base;
1586 
1587 	return (0);
1588 }
1589 
1590 	__checkReturn	efx_rc_t
1591 ef10_nic_get_bar_region(
1592 	__in		efx_nic_t *enp,
1593 	__in		efx_nic_region_t region,
1594 	__out		uint32_t *offsetp,
1595 	__out		size_t *sizep)
1596 {
1597 	efx_rc_t rc;
1598 
1599 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1600 		    enp->en_family == EFX_FAMILY_MEDFORD);
1601 
1602 	/*
1603 	 * TODO: Specify host memory mapping alignment and granularity
1604 	 * in efx_drv_limits_t so that they can be taken into account
1605 	 * when allocating extra VIs for PIO writes.
1606 	 */
1607 	switch (region) {
1608 	case EFX_REGION_VI:
1609 		/* UC mapped memory BAR region for VI registers */
1610 		*offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset;
1611 		*sizep = enp->en_arch.ef10.ena_uc_mem_map_size;
1612 		break;
1613 
1614 	case EFX_REGION_PIO_WRITE_VI:
1615 		/* WC mapped memory BAR region for piobuf writes */
1616 		*offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset;
1617 		*sizep = enp->en_arch.ef10.ena_wc_mem_map_size;
1618 		break;
1619 
1620 	default:
1621 		rc = EINVAL;
1622 		goto fail1;
1623 	}
1624 
1625 	return (0);
1626 
1627 fail1:
1628 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1629 
1630 	return (rc);
1631 }
1632 
1633 			void
1634 ef10_nic_fini(
1635 	__in		efx_nic_t *enp)
1636 {
1637 	uint32_t i;
1638 	efx_rc_t rc;
1639 
1640 	(void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id);
1641 	enp->en_vport_id = 0;
1642 
1643 	/* Unlink piobufs from extra VIs in WC mapping */
1644 	if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1645 		for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1646 			rc = efx_mcdi_unlink_piobuf(enp,
1647 			    enp->en_arch.ef10.ena_pio_write_vi_base + i);
1648 			if (rc != 0)
1649 				break;
1650 		}
1651 	}
1652 
1653 	ef10_nic_free_piobufs(enp);
1654 
1655 	(void) efx_mcdi_free_vis(enp);
1656 	enp->en_arch.ef10.ena_vi_count = 0;
1657 }
1658 
1659 			void
1660 ef10_nic_unprobe(
1661 	__in		efx_nic_t *enp)
1662 {
1663 #if EFSYS_OPT_MON_STATS
1664 	mcdi_mon_cfg_free(enp);
1665 #endif /* EFSYS_OPT_MON_STATS */
1666 	(void) efx_mcdi_drv_attach(enp, B_FALSE);
1667 }
1668 
1669 #if EFSYS_OPT_DIAG
1670 
1671 	__checkReturn	efx_rc_t
1672 ef10_nic_register_test(
1673 	__in		efx_nic_t *enp)
1674 {
1675 	efx_rc_t rc;
1676 
1677 	/* FIXME */
1678 	_NOTE(ARGUNUSED(enp))
1679 	_NOTE(CONSTANTCONDITION)
1680 	if (B_FALSE) {
1681 		rc = ENOTSUP;
1682 		goto fail1;
1683 	}
1684 	/* FIXME */
1685 
1686 	return (0);
1687 
1688 fail1:
1689 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1690 
1691 	return (rc);
1692 }
1693 
1694 #endif	/* EFSYS_OPT_DIAG */
1695 
1696 
1697 #endif	/* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
1698