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