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