xref: /freebsd/sys/dev/sfxge/common/hunt_nic.c (revision c084ac288389198f36d80439576f890fb48fef65)
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 #undef CAP_FLAG
955 #undef CAP_FLAG2
956 
957 	return (0);
958 
959 fail2:
960 	EFSYS_PROBE(fail2);
961 fail1:
962 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
963 
964 	return (rc);
965 }
966 
967 
968 	__checkReturn		efx_rc_t
969 ef10_get_privilege_mask(
970 	__in			efx_nic_t *enp,
971 	__out			uint32_t *maskp)
972 {
973 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
974 	uint32_t mask;
975 	efx_rc_t rc;
976 
977 	if ((rc = efx_mcdi_privilege_mask(enp, encp->enc_pf, encp->enc_vf,
978 					    &mask)) != 0) {
979 		if (rc != ENOTSUP)
980 			goto fail1;
981 
982 		/* Fallback for old firmware without privilege mask support */
983 		if (EFX_PCI_FUNCTION_IS_PF(encp)) {
984 			/* Assume PF has admin privilege */
985 			mask = EF10_LEGACY_PF_PRIVILEGE_MASK;
986 		} else {
987 			/* VF is always unprivileged by default */
988 			mask = EF10_LEGACY_VF_PRIVILEGE_MASK;
989 		}
990 	}
991 
992 	*maskp = mask;
993 
994 	return (0);
995 
996 fail1:
997 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
998 
999 	return (rc);
1000 }
1001 
1002 
1003 /*
1004  * The external port mapping is a one-based numbering of the external
1005  * connectors on the board. It does not distinguish off-board separated
1006  * outputs such as multi-headed cables.
1007  * The number of ports that map to each external port connector
1008  * on the board is determined by the chip family and the port modes to
1009  * which the NIC can be configured. The mapping table lists modes with
1010  * port numbering requirements in increasing order.
1011  */
1012 static struct {
1013 	efx_family_t	family;
1014 	uint32_t	modes_mask;
1015 	uint32_t	stride;
1016 }	__ef10_external_port_mappings[] = {
1017 	/* Supported modes requiring 1 output per port */
1018 	{
1019 		EFX_FAMILY_HUNTINGTON,
1020 		(1 << TLV_PORT_MODE_10G) |
1021 		(1 << TLV_PORT_MODE_10G_10G) |
1022 		(1 << TLV_PORT_MODE_10G_10G_10G_10G),
1023 		1
1024 	},
1025 	{
1026 		EFX_FAMILY_MEDFORD,
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 	/* Supported modes requiring 2 outputs per port */
1033 	{
1034 		EFX_FAMILY_HUNTINGTON,
1035 		(1 << TLV_PORT_MODE_40G) |
1036 		(1 << TLV_PORT_MODE_40G_40G) |
1037 		(1 << TLV_PORT_MODE_40G_10G_10G) |
1038 		(1 << TLV_PORT_MODE_10G_10G_40G),
1039 		2
1040 	},
1041 	{
1042 		EFX_FAMILY_MEDFORD,
1043 		(1 << TLV_PORT_MODE_40G) |
1044 		(1 << TLV_PORT_MODE_40G_40G) |
1045 		(1 << TLV_PORT_MODE_40G_10G_10G) |
1046 		(1 << TLV_PORT_MODE_10G_10G_40G),
1047 		2
1048 	},
1049 	/* Supported modes requiring 4 outputs per port */
1050 	{
1051 		EFX_FAMILY_MEDFORD,
1052 		(1 << TLV_PORT_MODE_10G_10G_10G_10G_Q) |
1053 		(1 << TLV_PORT_MODE_10G_10G_10G_10G_Q2),
1054 		4
1055 	},
1056 };
1057 
1058 	__checkReturn	efx_rc_t
1059 ef10_external_port_mapping(
1060 	__in		efx_nic_t *enp,
1061 	__in		uint32_t port,
1062 	__out		uint8_t *external_portp)
1063 {
1064 	efx_rc_t rc;
1065 	int i;
1066 	uint32_t port_modes;
1067 	uint32_t matches;
1068 	uint32_t stride = 1; /* default 1-1 mapping */
1069 
1070 	if ((rc = efx_mcdi_get_port_modes(enp, &port_modes)) != 0) {
1071 		/* No port mode information available - use default mapping */
1072 		goto out;
1073 	}
1074 
1075 	/*
1076 	 * Infer the internal port -> external port mapping from
1077 	 * the possible port modes for this NIC.
1078 	 */
1079 	for (i = 0; i < EFX_ARRAY_SIZE(__ef10_external_port_mappings); ++i) {
1080 		if (__ef10_external_port_mappings[i].family !=
1081 		    enp->en_family)
1082 			continue;
1083 		matches = (__ef10_external_port_mappings[i].modes_mask &
1084 		    port_modes);
1085 		if (matches != 0) {
1086 			stride = __ef10_external_port_mappings[i].stride;
1087 			port_modes &= ~matches;
1088 		}
1089 	}
1090 
1091 	if (port_modes != 0) {
1092 		/* Some advertised modes are not supported */
1093 		rc = ENOTSUP;
1094 		goto fail1;
1095 	}
1096 
1097 out:
1098 	/*
1099 	 * Scale as required by last matched mode and then convert to
1100 	 * one-based numbering
1101 	 */
1102 	*external_portp = (uint8_t)(port / stride) + 1;
1103 	return (0);
1104 
1105 fail1:
1106 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1107 
1108 	return (rc);
1109 }
1110 
1111 	__checkReturn	efx_rc_t
1112 hunt_board_cfg(
1113 	__in		efx_nic_t *enp)
1114 {
1115 	efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
1116 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1117 	uint8_t mac_addr[6];
1118 	uint32_t board_type = 0;
1119 	ef10_link_state_t els;
1120 	efx_port_t *epp = &(enp->en_port);
1121 	uint32_t port;
1122 	uint32_t pf;
1123 	uint32_t vf;
1124 	uint32_t mask;
1125 	uint32_t flags;
1126 	uint32_t sysclk;
1127 	uint32_t base, nvec;
1128 	efx_rc_t rc;
1129 
1130 	if ((rc = efx_mcdi_get_port_assignment(enp, &port)) != 0)
1131 		goto fail1;
1132 
1133 	/*
1134 	 * NOTE: The MCDI protocol numbers ports from zero.
1135 	 * The common code MCDI interface numbers ports from one.
1136 	 */
1137 	emip->emi_port = port + 1;
1138 
1139 	if ((rc = ef10_external_port_mapping(enp, port,
1140 		    &encp->enc_external_port)) != 0)
1141 		goto fail2;
1142 
1143 	/*
1144 	 * Get PCIe function number from firmware (used for
1145 	 * per-function privilege and dynamic config info).
1146 	 *  - PCIe PF: pf = PF number, vf = 0xffff.
1147 	 *  - PCIe VF: pf = parent PF, vf = VF number.
1148 	 */
1149 	if ((rc = efx_mcdi_get_function_info(enp, &pf, &vf)) != 0)
1150 		goto fail3;
1151 
1152 	encp->enc_pf = pf;
1153 	encp->enc_vf = vf;
1154 
1155 	/* MAC address for this function */
1156 	if (EFX_PCI_FUNCTION_IS_PF(encp)) {
1157 		rc = efx_mcdi_get_mac_address_pf(enp, mac_addr);
1158 		if ((rc == 0) && (mac_addr[0] & 0x02)) {
1159 			/*
1160 			 * If the static config does not include a global MAC
1161 			 * address pool then the board may return a locally
1162 			 * administered MAC address (this should only happen on
1163 			 * incorrectly programmed boards).
1164 			 */
1165 			rc = EINVAL;
1166 		}
1167 	} else {
1168 		rc = efx_mcdi_get_mac_address_vf(enp, mac_addr);
1169 	}
1170 	if (rc != 0)
1171 		goto fail4;
1172 
1173 	EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
1174 
1175 	/* Board configuration */
1176 	rc = efx_mcdi_get_board_cfg(enp, &board_type, NULL, NULL);
1177 	if (rc != 0) {
1178 		/* Unprivileged functions may not be able to read board cfg */
1179 		if (rc == EACCES)
1180 			board_type = 0;
1181 		else
1182 			goto fail5;
1183 	}
1184 
1185 	encp->enc_board_type = board_type;
1186 	encp->enc_clk_mult = 1; /* not used for Huntington */
1187 
1188 	/* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
1189 	if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
1190 		goto fail6;
1191 
1192 	/* Obtain the default PHY advertised capabilities */
1193 	if ((rc = ef10_phy_get_link(enp, &els)) != 0)
1194 		goto fail7;
1195 	epp->ep_default_adv_cap_mask = els.els_adv_cap_mask;
1196 	epp->ep_adv_cap_mask = els.els_adv_cap_mask;
1197 
1198 	/*
1199 	 * Enable firmware workarounds for hardware errata.
1200 	 * Expected responses are:
1201 	 *  - 0 (zero):
1202 	 *	Success: workaround enabled or disabled as requested.
1203 	 *  - MC_CMD_ERR_ENOSYS (reported as ENOTSUP):
1204 	 *	Firmware does not support the MC_CMD_WORKAROUND request.
1205 	 *	(assume that the workaround is not supported).
1206 	 *  - MC_CMD_ERR_ENOENT (reported as ENOENT):
1207 	 *	Firmware does not support the requested workaround.
1208 	 *  - MC_CMD_ERR_EPERM  (reported as EACCES):
1209 	 *	Unprivileged function cannot enable/disable workarounds.
1210 	 *
1211 	 * See efx_mcdi_request_errcode() for MCDI error translations.
1212 	 */
1213 
1214 	/*
1215 	 * If the bug35388 workaround is enabled, then use an indirect access
1216 	 * method to avoid unsafe EVQ writes.
1217 	 */
1218 	rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG35388, B_TRUE,
1219 	    NULL);
1220 	if ((rc == 0) || (rc == EACCES))
1221 		encp->enc_bug35388_workaround = B_TRUE;
1222 	else if ((rc == ENOTSUP) || (rc == ENOENT))
1223 		encp->enc_bug35388_workaround = B_FALSE;
1224 	else
1225 		goto fail8;
1226 
1227 	/*
1228 	 * If the bug41750 workaround is enabled, then do not test interrupts,
1229 	 * as the test will fail (seen with Greenport controllers).
1230 	 */
1231 	rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG41750, B_TRUE,
1232 	    NULL);
1233 	if (rc == 0) {
1234 		encp->enc_bug41750_workaround = B_TRUE;
1235 	} else if (rc == EACCES) {
1236 		/* Assume a controller with 40G ports needs the workaround. */
1237 		if (epp->ep_default_adv_cap_mask & EFX_PHY_CAP_40000FDX)
1238 			encp->enc_bug41750_workaround = B_TRUE;
1239 		else
1240 			encp->enc_bug41750_workaround = B_FALSE;
1241 	} else if ((rc == ENOTSUP) || (rc == ENOENT)) {
1242 		encp->enc_bug41750_workaround = B_FALSE;
1243 	} else {
1244 		goto fail9;
1245 	}
1246 	if (EFX_PCI_FUNCTION_IS_VF(encp)) {
1247 		/* Interrupt testing does not work for VFs. See bug50084. */
1248 		encp->enc_bug41750_workaround = B_TRUE;
1249 	}
1250 
1251 	/*
1252 	 * If the bug26807 workaround is enabled, then firmware has enabled
1253 	 * support for chained multicast filters. Firmware will reset (FLR)
1254 	 * functions which have filters in the hardware filter table when the
1255 	 * workaround is enabled/disabled.
1256 	 *
1257 	 * We must recheck if the workaround is enabled after inserting the
1258 	 * first hardware filter, in case it has been changed since this check.
1259 	 */
1260 	rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG26807,
1261 	    B_TRUE, &flags);
1262 	if (rc == 0) {
1263 		encp->enc_bug26807_workaround = B_TRUE;
1264 		if (flags & (1 << MC_CMD_WORKAROUND_EXT_OUT_FLR_DONE_LBN)) {
1265 			/*
1266 			 * Other functions had installed filters before the
1267 			 * workaround was enabled, and they have been reset
1268 			 * by firmware.
1269 			 */
1270 			EFSYS_PROBE(bug26807_workaround_flr_done);
1271 			/* FIXME: bump MC warm boot count ? */
1272 		}
1273 	} else if (rc == EACCES) {
1274 		/*
1275 		 * Unprivileged functions cannot enable the workaround in older
1276 		 * firmware.
1277 		 */
1278 		encp->enc_bug26807_workaround = B_FALSE;
1279 	} else if ((rc == ENOTSUP) || (rc == ENOENT)) {
1280 		encp->enc_bug26807_workaround = B_FALSE;
1281 	} else {
1282 		goto fail10;
1283 	}
1284 
1285 	/* Get sysclk frequency (in MHz). */
1286 	if ((rc = efx_mcdi_get_clock(enp, &sysclk)) != 0)
1287 		goto fail11;
1288 
1289 	/*
1290 	 * The timer quantum is 1536 sysclk cycles, documented for the
1291 	 * EV_TMR_VAL field of EV_TIMER_TBL. Scale for MHz and ns units.
1292 	 */
1293 	encp->enc_evq_timer_quantum_ns = 1536000UL / sysclk; /* 1536 cycles */
1294 	if (encp->enc_bug35388_workaround) {
1295 		encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
1296 		ERF_DD_EVQ_IND_TIMER_VAL_WIDTH) / 1000;
1297 	} else {
1298 		encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
1299 		FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
1300 	}
1301 
1302 	/* Check capabilities of running datapath firmware */
1303 	if ((rc = ef10_get_datapath_caps(enp)) != 0)
1304 	    goto fail12;
1305 
1306 	/* Alignment for receive packet DMA buffers */
1307 	encp->enc_rx_buf_align_start = 1;
1308 	encp->enc_rx_buf_align_end = 64; /* RX DMA end padding */
1309 
1310 	/* Alignment for WPTR updates */
1311 	encp->enc_rx_push_align = EF10_RX_WPTR_ALIGN;
1312 
1313 	/*
1314 	 * Set resource limits for MC_CMD_ALLOC_VIS. Note that we cannot use
1315 	 * MC_CMD_GET_RESOURCE_LIMITS here as that reports the available
1316 	 * resources (allocated to this PCIe function), which is zero until
1317 	 * after we have allocated VIs.
1318 	 */
1319 	encp->enc_evq_limit = 1024;
1320 	encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
1321 	encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
1322 
1323 	encp->enc_buftbl_limit = 0xFFFFFFFF;
1324 
1325 	encp->enc_piobuf_limit = HUNT_PIOBUF_NBUFS;
1326 	encp->enc_piobuf_size = HUNT_PIOBUF_SIZE;
1327 	encp->enc_piobuf_min_alloc_size = HUNT_MIN_PIO_ALLOC_SIZE;
1328 
1329 	/*
1330 	 * Get the current privilege mask. Note that this may be modified
1331 	 * dynamically, so this value is informational only. DO NOT use
1332 	 * the privilege mask to check for sufficient privileges, as that
1333 	 * can result in time-of-check/time-of-use bugs.
1334 	 */
1335 	if ((rc = ef10_get_privilege_mask(enp, &mask)) != 0)
1336 		goto fail13;
1337 	encp->enc_privilege_mask = mask;
1338 
1339 	/* Get interrupt vector limits */
1340 	if ((rc = efx_mcdi_get_vector_cfg(enp, &base, &nvec, NULL)) != 0) {
1341 		if (EFX_PCI_FUNCTION_IS_PF(encp))
1342 			goto fail14;
1343 
1344 		/* Ignore error (cannot query vector limits from a VF). */
1345 		base = 0;
1346 		nvec = 1024;
1347 	}
1348 	encp->enc_intr_vec_base = base;
1349 	encp->enc_intr_limit = nvec;
1350 
1351 	/*
1352 	 * Maximum number of bytes into the frame the TCP header can start for
1353 	 * firmware assisted TSO to work.
1354 	 */
1355 	encp->enc_tx_tso_tcp_header_offset_limit = EF10_TCP_HEADER_OFFSET_LIMIT;
1356 
1357 	return (0);
1358 
1359 fail14:
1360 	EFSYS_PROBE(fail14);
1361 fail13:
1362 	EFSYS_PROBE(fail13);
1363 fail12:
1364 	EFSYS_PROBE(fail12);
1365 fail11:
1366 	EFSYS_PROBE(fail11);
1367 fail10:
1368 	EFSYS_PROBE(fail10);
1369 fail9:
1370 	EFSYS_PROBE(fail9);
1371 fail8:
1372 	EFSYS_PROBE(fail8);
1373 fail7:
1374 	EFSYS_PROBE(fail7);
1375 fail6:
1376 	EFSYS_PROBE(fail6);
1377 fail5:
1378 	EFSYS_PROBE(fail5);
1379 fail4:
1380 	EFSYS_PROBE(fail4);
1381 fail3:
1382 	EFSYS_PROBE(fail3);
1383 fail2:
1384 	EFSYS_PROBE(fail2);
1385 fail1:
1386 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1387 
1388 	return (rc);
1389 }
1390 
1391 
1392 	__checkReturn	efx_rc_t
1393 ef10_nic_probe(
1394 	__in		efx_nic_t *enp)
1395 {
1396 	efx_nic_ops_t *enop = enp->en_enop;
1397 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1398 	efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1399 	efx_rc_t rc;
1400 
1401 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1402 		    enp->en_family == EFX_FAMILY_MEDFORD);
1403 
1404 	/* Read and clear any assertion state */
1405 	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1406 		goto fail1;
1407 
1408 	/* Exit the assertion handler */
1409 	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1410 		if (rc != EACCES)
1411 			goto fail2;
1412 
1413 	if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
1414 		goto fail3;
1415 
1416 	if ((rc = enop->eno_board_cfg(enp)) != 0)
1417 		if (rc != EACCES)
1418 			goto fail4;
1419 
1420 	/*
1421 	 * Set default driver config limits (based on board config).
1422 	 *
1423 	 * FIXME: For now allocate a fixed number of VIs which is likely to be
1424 	 * sufficient and small enough to allow multiple functions on the same
1425 	 * port.
1426 	 */
1427 	edcp->edc_min_vi_count = edcp->edc_max_vi_count =
1428 	    MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit));
1429 
1430 	/* The client driver must configure and enable PIO buffer support */
1431 	edcp->edc_max_piobuf_count = 0;
1432 	edcp->edc_pio_alloc_size = 0;
1433 
1434 #if EFSYS_OPT_MAC_STATS
1435 	/* Wipe the MAC statistics */
1436 	if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
1437 		goto fail5;
1438 #endif
1439 
1440 #if EFSYS_OPT_LOOPBACK
1441 	if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
1442 		goto fail6;
1443 #endif
1444 
1445 #if EFSYS_OPT_MON_STATS
1446 	if ((rc = mcdi_mon_cfg_build(enp)) != 0) {
1447 		/* Unprivileged functions do not have access to sensors */
1448 		if (rc != EACCES)
1449 			goto fail7;
1450 	}
1451 #endif
1452 
1453 	encp->enc_features = enp->en_features;
1454 
1455 	return (0);
1456 
1457 #if EFSYS_OPT_MON_STATS
1458 fail7:
1459 	EFSYS_PROBE(fail7);
1460 #endif
1461 #if EFSYS_OPT_LOOPBACK
1462 fail6:
1463 	EFSYS_PROBE(fail6);
1464 #endif
1465 #if EFSYS_OPT_MAC_STATS
1466 fail5:
1467 	EFSYS_PROBE(fail5);
1468 #endif
1469 fail4:
1470 	EFSYS_PROBE(fail4);
1471 fail3:
1472 	EFSYS_PROBE(fail3);
1473 fail2:
1474 	EFSYS_PROBE(fail2);
1475 fail1:
1476 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1477 
1478 	return (rc);
1479 }
1480 
1481 	__checkReturn	efx_rc_t
1482 ef10_nic_set_drv_limits(
1483 	__inout		efx_nic_t *enp,
1484 	__in		efx_drv_limits_t *edlp)
1485 {
1486 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1487 	efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1488 	uint32_t min_evq_count, max_evq_count;
1489 	uint32_t min_rxq_count, max_rxq_count;
1490 	uint32_t min_txq_count, max_txq_count;
1491 	efx_rc_t rc;
1492 
1493 	if (edlp == NULL) {
1494 		rc = EINVAL;
1495 		goto fail1;
1496 	}
1497 
1498 	/* Get minimum required and maximum usable VI limits */
1499 	min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit);
1500 	min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit);
1501 	min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit);
1502 
1503 	edcp->edc_min_vi_count =
1504 	    MAX(min_evq_count, MAX(min_rxq_count, min_txq_count));
1505 
1506 	max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit);
1507 	max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit);
1508 	max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit);
1509 
1510 	edcp->edc_max_vi_count =
1511 	    MAX(max_evq_count, MAX(max_rxq_count, max_txq_count));
1512 
1513 	/*
1514 	 * Check limits for sub-allocated piobuf blocks.
1515 	 * PIO is optional, so don't fail if the limits are incorrect.
1516 	 */
1517 	if ((encp->enc_piobuf_size == 0) ||
1518 	    (encp->enc_piobuf_limit == 0) ||
1519 	    (edlp->edl_min_pio_alloc_size == 0) ||
1520 	    (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) {
1521 		/* Disable PIO */
1522 		edcp->edc_max_piobuf_count = 0;
1523 		edcp->edc_pio_alloc_size = 0;
1524 	} else {
1525 		uint32_t blk_size, blk_count, blks_per_piobuf;
1526 
1527 		blk_size =
1528 		    MAX(edlp->edl_min_pio_alloc_size,
1529 			    encp->enc_piobuf_min_alloc_size);
1530 
1531 		blks_per_piobuf = encp->enc_piobuf_size / blk_size;
1532 		EFSYS_ASSERT3U(blks_per_piobuf, <=, 32);
1533 
1534 		blk_count = (encp->enc_piobuf_limit * blks_per_piobuf);
1535 
1536 		/* A zero max pio alloc count means unlimited */
1537 		if ((edlp->edl_max_pio_alloc_count > 0) &&
1538 		    (edlp->edl_max_pio_alloc_count < blk_count)) {
1539 			blk_count = edlp->edl_max_pio_alloc_count;
1540 		}
1541 
1542 		edcp->edc_pio_alloc_size = blk_size;
1543 		edcp->edc_max_piobuf_count =
1544 		    (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf;
1545 	}
1546 
1547 	return (0);
1548 
1549 fail1:
1550 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1551 
1552 	return (rc);
1553 }
1554 
1555 
1556 	__checkReturn	efx_rc_t
1557 ef10_nic_reset(
1558 	__in		efx_nic_t *enp)
1559 {
1560 	efx_mcdi_req_t req;
1561 	uint8_t payload[MAX(MC_CMD_ENTITY_RESET_IN_LEN,
1562 			    MC_CMD_ENTITY_RESET_OUT_LEN)];
1563 	efx_rc_t rc;
1564 
1565 	/* ef10_nic_reset() is called to recover from BADASSERT failures. */
1566 	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1567 		goto fail1;
1568 	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1569 		goto fail2;
1570 
1571 	(void) memset(payload, 0, sizeof (payload));
1572 	req.emr_cmd = MC_CMD_ENTITY_RESET;
1573 	req.emr_in_buf = payload;
1574 	req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN;
1575 	req.emr_out_buf = payload;
1576 	req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN;
1577 
1578 	MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG,
1579 	    ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1);
1580 
1581 	efx_mcdi_execute(enp, &req);
1582 
1583 	if (req.emr_rc != 0) {
1584 		rc = req.emr_rc;
1585 		goto fail3;
1586 	}
1587 
1588 	/* Clear RX/TX DMA queue errors */
1589 	enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR);
1590 
1591 	return (0);
1592 
1593 fail3:
1594 	EFSYS_PROBE(fail3);
1595 fail2:
1596 	EFSYS_PROBE(fail2);
1597 fail1:
1598 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1599 
1600 	return (rc);
1601 }
1602 
1603 	__checkReturn	efx_rc_t
1604 ef10_nic_init(
1605 	__in		efx_nic_t *enp)
1606 {
1607 	efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1608 	uint32_t min_vi_count, max_vi_count;
1609 	uint32_t vi_count, vi_base, vi_shift;
1610 	uint32_t i;
1611 	uint32_t retry;
1612 	uint32_t delay_us;
1613 	efx_rc_t rc;
1614 
1615 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1616 		    enp->en_family == EFX_FAMILY_MEDFORD);
1617 
1618 	/* Enable reporting of some events (e.g. link change) */
1619 	if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
1620 		goto fail1;
1621 
1622 	/* Allocate (optional) on-chip PIO buffers */
1623 	ef10_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count);
1624 
1625 	/*
1626 	 * For best performance, PIO writes should use a write-combined
1627 	 * (WC) memory mapping. Using a separate WC mapping for the PIO
1628 	 * aperture of each VI would be a burden to drivers (and not
1629 	 * possible if the host page size is >4Kbyte).
1630 	 *
1631 	 * To avoid this we use a single uncached (UC) mapping for VI
1632 	 * register access, and a single WC mapping for extra VIs used
1633 	 * for PIO writes.
1634 	 *
1635 	 * Each piobuf must be linked to a VI in the WC mapping, and to
1636 	 * each VI that is using a sub-allocated block from the piobuf.
1637 	 */
1638 	min_vi_count = edcp->edc_min_vi_count;
1639 	max_vi_count =
1640 	    edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count;
1641 
1642 	/* Ensure that the previously attached driver's VIs are freed */
1643 	if ((rc = efx_mcdi_free_vis(enp)) != 0)
1644 		goto fail2;
1645 
1646 	/*
1647 	 * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this
1648 	 * fails then retrying the request for fewer VI resources may succeed.
1649 	 */
1650 	vi_count = 0;
1651 	if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count,
1652 		    &vi_base, &vi_count, &vi_shift)) != 0)
1653 		goto fail3;
1654 
1655 	EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count);
1656 
1657 	if (vi_count < min_vi_count) {
1658 		rc = ENOMEM;
1659 		goto fail4;
1660 	}
1661 
1662 	enp->en_arch.ef10.ena_vi_base = vi_base;
1663 	enp->en_arch.ef10.ena_vi_count = vi_count;
1664 	enp->en_arch.ef10.ena_vi_shift = vi_shift;
1665 
1666 	if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) {
1667 		/* Not enough extra VIs to map piobufs */
1668 		ef10_nic_free_piobufs(enp);
1669 	}
1670 
1671 	enp->en_arch.ef10.ena_pio_write_vi_base =
1672 	    vi_count - enp->en_arch.ef10.ena_piobuf_count;
1673 
1674 	/* Save UC memory mapping details */
1675 	enp->en_arch.ef10.ena_uc_mem_map_offset = 0;
1676 	if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1677 		enp->en_arch.ef10.ena_uc_mem_map_size =
1678 		    (ER_DZ_TX_PIOBUF_STEP *
1679 		    enp->en_arch.ef10.ena_pio_write_vi_base);
1680 	} else {
1681 		enp->en_arch.ef10.ena_uc_mem_map_size =
1682 		    (ER_DZ_TX_PIOBUF_STEP *
1683 		    enp->en_arch.ef10.ena_vi_count);
1684 	}
1685 
1686 	/* Save WC memory mapping details */
1687 	enp->en_arch.ef10.ena_wc_mem_map_offset =
1688 	    enp->en_arch.ef10.ena_uc_mem_map_offset +
1689 	    enp->en_arch.ef10.ena_uc_mem_map_size;
1690 
1691 	enp->en_arch.ef10.ena_wc_mem_map_size =
1692 	    (ER_DZ_TX_PIOBUF_STEP *
1693 	    enp->en_arch.ef10.ena_piobuf_count);
1694 
1695 	/* Link piobufs to extra VIs in WC mapping */
1696 	if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1697 		for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1698 			rc = efx_mcdi_link_piobuf(enp,
1699 			    enp->en_arch.ef10.ena_pio_write_vi_base + i,
1700 			    enp->en_arch.ef10.ena_piobuf_handle[i]);
1701 			if (rc != 0)
1702 				break;
1703 		}
1704 	}
1705 
1706 	/*
1707 	 * Allocate a vAdaptor attached to our upstream vPort/pPort.
1708 	 *
1709 	 * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF
1710 	 * driver has yet to bring up the EVB port. See bug 56147. In this case,
1711 	 * retry the request several times after waiting a while. The wait time
1712 	 * between retries starts small (10ms) and exponentially increases.
1713 	 * Total wait time is a little over two seconds. Retry logic in the
1714 	 * client driver may mean this whole loop is repeated if it continues to
1715 	 * fail.
1716 	 */
1717 	retry = 0;
1718 	delay_us = 10000;
1719 	while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) {
1720 		if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) ||
1721 		    (rc != ENOENT)) {
1722 			/*
1723 			 * Do not retry alloc for PF, or for other errors on
1724 			 * a VF.
1725 			 */
1726 			goto fail5;
1727 		}
1728 
1729 		/* VF startup before PF is ready. Retry allocation. */
1730 		if (retry > 5) {
1731 			/* Too many attempts */
1732 			rc = EINVAL;
1733 			goto fail6;
1734 		}
1735 		EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry);
1736 		EFSYS_SLEEP(delay_us);
1737 		retry++;
1738 		if (delay_us < 500000)
1739 			delay_us <<= 2;
1740 	}
1741 
1742 	enp->en_vport_id = EVB_PORT_ID_ASSIGNED;
1743 	enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2;
1744 
1745 	return (0);
1746 
1747 fail6:
1748 	EFSYS_PROBE(fail6);
1749 fail5:
1750 	EFSYS_PROBE(fail5);
1751 fail4:
1752 	EFSYS_PROBE(fail4);
1753 fail3:
1754 	EFSYS_PROBE(fail3);
1755 fail2:
1756 	EFSYS_PROBE(fail2);
1757 
1758 	ef10_nic_free_piobufs(enp);
1759 
1760 fail1:
1761 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1762 
1763 	return (rc);
1764 }
1765 
1766 	__checkReturn	efx_rc_t
1767 ef10_nic_get_vi_pool(
1768 	__in		efx_nic_t *enp,
1769 	__out		uint32_t *vi_countp)
1770 {
1771 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1772 		    enp->en_family == EFX_FAMILY_MEDFORD);
1773 
1774 	/*
1775 	 * Report VIs that the client driver can use.
1776 	 * Do not include VIs used for PIO buffer writes.
1777 	 */
1778 	*vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base;
1779 
1780 	return (0);
1781 }
1782 
1783 	__checkReturn	efx_rc_t
1784 ef10_nic_get_bar_region(
1785 	__in		efx_nic_t *enp,
1786 	__in		efx_nic_region_t region,
1787 	__out		uint32_t *offsetp,
1788 	__out		size_t *sizep)
1789 {
1790 	efx_rc_t rc;
1791 
1792 	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1793 		    enp->en_family == EFX_FAMILY_MEDFORD);
1794 
1795 	/*
1796 	 * TODO: Specify host memory mapping alignment and granularity
1797 	 * in efx_drv_limits_t so that they can be taken into account
1798 	 * when allocating extra VIs for PIO writes.
1799 	 */
1800 	switch (region) {
1801 	case EFX_REGION_VI:
1802 		/* UC mapped memory BAR region for VI registers */
1803 		*offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset;
1804 		*sizep = enp->en_arch.ef10.ena_uc_mem_map_size;
1805 		break;
1806 
1807 	case EFX_REGION_PIO_WRITE_VI:
1808 		/* WC mapped memory BAR region for piobuf writes */
1809 		*offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset;
1810 		*sizep = enp->en_arch.ef10.ena_wc_mem_map_size;
1811 		break;
1812 
1813 	default:
1814 		rc = EINVAL;
1815 		goto fail1;
1816 	}
1817 
1818 	return (0);
1819 
1820 fail1:
1821 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1822 
1823 	return (rc);
1824 }
1825 
1826 			void
1827 ef10_nic_fini(
1828 	__in		efx_nic_t *enp)
1829 {
1830 	uint32_t i;
1831 	efx_rc_t rc;
1832 
1833 	(void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id);
1834 	enp->en_vport_id = 0;
1835 
1836 	/* Unlink piobufs from extra VIs in WC mapping */
1837 	if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1838 		for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1839 			rc = efx_mcdi_unlink_piobuf(enp,
1840 			    enp->en_arch.ef10.ena_pio_write_vi_base + i);
1841 			if (rc != 0)
1842 				break;
1843 		}
1844 	}
1845 
1846 	ef10_nic_free_piobufs(enp);
1847 
1848 	(void) efx_mcdi_free_vis(enp);
1849 	enp->en_arch.ef10.ena_vi_count = 0;
1850 }
1851 
1852 			void
1853 ef10_nic_unprobe(
1854 	__in		efx_nic_t *enp)
1855 {
1856 #if EFSYS_OPT_MON_STATS
1857 	mcdi_mon_cfg_free(enp);
1858 #endif /* EFSYS_OPT_MON_STATS */
1859 	(void) efx_mcdi_drv_attach(enp, B_FALSE);
1860 }
1861 
1862 #if EFSYS_OPT_DIAG
1863 
1864 	__checkReturn	efx_rc_t
1865 ef10_nic_register_test(
1866 	__in		efx_nic_t *enp)
1867 {
1868 	efx_rc_t rc;
1869 
1870 	/* FIXME */
1871 	_NOTE(ARGUNUSED(enp))
1872 	if (B_FALSE) {
1873 		rc = ENOTSUP;
1874 		goto fail1;
1875 	}
1876 	/* FIXME */
1877 
1878 	return (0);
1879 
1880 fail1:
1881 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1882 
1883 	return (rc);
1884 }
1885 
1886 #endif	/* EFSYS_OPT_DIAG */
1887 
1888 
1889 
1890 #endif	/* EFSYS_OPT_HUNTINGTON */
1891