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