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