ef10_nic.c revision 299517
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: head/sys/dev/sfxge/common/hunt_nic.c 299517 2016-05-12 06:19:06Z arybchik $");
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
45efx_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
80fail2:
81	EFSYS_PROBE(fail2);
82fail1:
83	EFSYS_PROBE1(fail1, efx_rc_t, rc);
84
85	return (rc);
86}
87
88	__checkReturn	efx_rc_t
89efx_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
129fail2:
130	EFSYS_PROBE(fail2);
131fail1:
132	EFSYS_PROBE1(fail1, efx_rc_t, rc);
133
134	return (rc);
135}
136
137
138static	__checkReturn		efx_rc_t
139efx_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
171fail1:
172	EFSYS_PROBE1(fail1, efx_rc_t, rc);
173
174	return (rc);
175}
176
177static	__checkReturn		efx_rc_t
178efx_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
205fail1:
206	EFSYS_PROBE1(fail1, efx_rc_t, rc);
207
208	return (rc);
209}
210
211	__checkReturn	efx_rc_t
212efx_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
259fail3:
260	EFSYS_PROBE(fail3);
261fail2:
262	EFSYS_PROBE(fail2);
263fail1:
264	EFSYS_PROBE1(fail1, efx_rc_t, rc);
265
266	return (rc);
267}
268
269	__checkReturn	efx_rc_t
270efx_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
322fail3:
323	EFSYS_PROBE(fail3);
324fail2:
325	EFSYS_PROBE(fail2);
326fail1:
327	EFSYS_PROBE1(fail1, efx_rc_t, rc);
328
329	return (rc);
330}
331
332	__checkReturn	efx_rc_t
333efx_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
372fail3:
373	EFSYS_PROBE(fail3);
374fail2:
375	EFSYS_PROBE(fail2);
376fail1:
377	EFSYS_PROBE1(fail1, efx_rc_t, rc);
378
379	return (rc);
380}
381
382	__checkReturn	efx_rc_t
383efx_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
422fail2:
423	EFSYS_PROBE(fail2);
424fail1:
425	EFSYS_PROBE1(fail1, efx_rc_t, rc);
426
427	return (rc);
428}
429
430static	__checkReturn	efx_rc_t
431efx_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
469fail2:
470	EFSYS_PROBE(fail2);
471fail1:
472	EFSYS_PROBE1(fail1, efx_rc_t, rc);
473
474	return (rc);
475}
476
477
478static	__checkReturn	efx_rc_t
479efx_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
530fail3:
531	EFSYS_PROBE(fail3);
532fail2:
533	EFSYS_PROBE(fail2);
534fail1:
535	EFSYS_PROBE1(fail1, efx_rc_t, rc);
536
537	return (rc);
538}
539
540
541static	__checkReturn	efx_rc_t
542efx_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
567fail1:
568	EFSYS_PROBE1(fail1, efx_rc_t, rc);
569
570	return (rc);
571}
572
573
574static	__checkReturn	efx_rc_t
575efx_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
612fail3:
613	EFSYS_PROBE(fail3);
614fail2:
615	EFSYS_PROBE(fail2);
616fail1:
617	EFSYS_PROBE1(fail1, efx_rc_t, rc);
618
619	return (rc);
620}
621
622static	__checkReturn	efx_rc_t
623efx_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
650fail1:
651	EFSYS_PROBE1(fail1, efx_rc_t, rc);
652
653	return (rc);
654}
655
656static	__checkReturn	efx_rc_t
657efx_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
686fail1:
687	EFSYS_PROBE1(fail1, efx_rc_t, rc);
688
689	return (rc);
690}
691
692static	__checkReturn	efx_rc_t
693efx_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
720fail1:
721	EFSYS_PROBE1(fail1, efx_rc_t, rc);
722
723	return (rc);
724}
725
726static			void
727ef10_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
752fail1:
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
763static			void
764ef10_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
781ef10_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
827done:
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
836fail2:
837	EFSYS_PROBE(fail2);
838fail1:
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
846ef10_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
869fail2:
870	EFSYS_PROBE(fail2);
871fail1:
872	EFSYS_PROBE1(fail1, efx_rc_t, rc);
873
874	return (rc);
875}
876
877	__checkReturn	efx_rc_t
878ef10_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
887ef10_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
895ef10_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
966fail2:
967	EFSYS_PROBE(fail2);
968fail1:
969	EFSYS_PROBE1(fail1, efx_rc_t, rc);
970
971	return (rc);
972}
973
974
975	__checkReturn		efx_rc_t
976ef10_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
1003fail1:
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 */
1019static 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
1066ef10_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
1104out:
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
1112fail1:
1113	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1114
1115	return (rc);
1116}
1117
1118	__checkReturn	efx_rc_t
1119hunt_board_cfg(
1120	__in		efx_nic_t *enp)
1121{
1122	efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
1123	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1124	uint8_t mac_addr[6];
1125	uint32_t board_type = 0;
1126	ef10_link_state_t els;
1127	efx_port_t *epp = &(enp->en_port);
1128	uint32_t port;
1129	uint32_t pf;
1130	uint32_t vf;
1131	uint32_t mask;
1132	uint32_t flags;
1133	uint32_t sysclk;
1134	uint32_t base, nvec;
1135	efx_rc_t rc;
1136
1137	if ((rc = efx_mcdi_get_port_assignment(enp, &port)) != 0)
1138		goto fail1;
1139
1140	/*
1141	 * NOTE: The MCDI protocol numbers ports from zero.
1142	 * The common code MCDI interface numbers ports from one.
1143	 */
1144	emip->emi_port = port + 1;
1145
1146	if ((rc = ef10_external_port_mapping(enp, port,
1147		    &encp->enc_external_port)) != 0)
1148		goto fail2;
1149
1150	/*
1151	 * Get PCIe function number from firmware (used for
1152	 * per-function privilege and dynamic config info).
1153	 *  - PCIe PF: pf = PF number, vf = 0xffff.
1154	 *  - PCIe VF: pf = parent PF, vf = VF number.
1155	 */
1156	if ((rc = efx_mcdi_get_function_info(enp, &pf, &vf)) != 0)
1157		goto fail3;
1158
1159	encp->enc_pf = pf;
1160	encp->enc_vf = vf;
1161
1162	/* MAC address for this function */
1163	if (EFX_PCI_FUNCTION_IS_PF(encp)) {
1164		rc = efx_mcdi_get_mac_address_pf(enp, mac_addr);
1165		if ((rc == 0) && (mac_addr[0] & 0x02)) {
1166			/*
1167			 * If the static config does not include a global MAC
1168			 * address pool then the board may return a locally
1169			 * administered MAC address (this should only happen on
1170			 * incorrectly programmed boards).
1171			 */
1172			rc = EINVAL;
1173		}
1174	} else {
1175		rc = efx_mcdi_get_mac_address_vf(enp, mac_addr);
1176	}
1177	if (rc != 0)
1178		goto fail4;
1179
1180	EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
1181
1182	/* Board configuration */
1183	rc = efx_mcdi_get_board_cfg(enp, &board_type, NULL, NULL);
1184	if (rc != 0) {
1185		/* Unprivileged functions may not be able to read board cfg */
1186		if (rc == EACCES)
1187			board_type = 0;
1188		else
1189			goto fail5;
1190	}
1191
1192	encp->enc_board_type = board_type;
1193	encp->enc_clk_mult = 1; /* not used for Huntington */
1194
1195	/* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
1196	if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
1197		goto fail6;
1198
1199	/* Obtain the default PHY advertised capabilities */
1200	if ((rc = ef10_phy_get_link(enp, &els)) != 0)
1201		goto fail7;
1202	epp->ep_default_adv_cap_mask = els.els_adv_cap_mask;
1203	epp->ep_adv_cap_mask = els.els_adv_cap_mask;
1204
1205	/*
1206	 * Enable firmware workarounds for hardware errata.
1207	 * Expected responses are:
1208	 *  - 0 (zero):
1209	 *	Success: workaround enabled or disabled as requested.
1210	 *  - MC_CMD_ERR_ENOSYS (reported as ENOTSUP):
1211	 *	Firmware does not support the MC_CMD_WORKAROUND request.
1212	 *	(assume that the workaround is not supported).
1213	 *  - MC_CMD_ERR_ENOENT (reported as ENOENT):
1214	 *	Firmware does not support the requested workaround.
1215	 *  - MC_CMD_ERR_EPERM  (reported as EACCES):
1216	 *	Unprivileged function cannot enable/disable workarounds.
1217	 *
1218	 * See efx_mcdi_request_errcode() for MCDI error translations.
1219	 */
1220
1221	/*
1222	 * If the bug35388 workaround is enabled, then use an indirect access
1223	 * method to avoid unsafe EVQ writes.
1224	 */
1225	rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG35388, B_TRUE,
1226	    NULL);
1227	if ((rc == 0) || (rc == EACCES))
1228		encp->enc_bug35388_workaround = B_TRUE;
1229	else if ((rc == ENOTSUP) || (rc == ENOENT))
1230		encp->enc_bug35388_workaround = B_FALSE;
1231	else
1232		goto fail8;
1233
1234	/*
1235	 * If the bug41750 workaround is enabled, then do not test interrupts,
1236	 * as the test will fail (seen with Greenport controllers).
1237	 */
1238	rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG41750, B_TRUE,
1239	    NULL);
1240	if (rc == 0) {
1241		encp->enc_bug41750_workaround = B_TRUE;
1242	} else if (rc == EACCES) {
1243		/* Assume a controller with 40G ports needs the workaround. */
1244		if (epp->ep_default_adv_cap_mask & EFX_PHY_CAP_40000FDX)
1245			encp->enc_bug41750_workaround = B_TRUE;
1246		else
1247			encp->enc_bug41750_workaround = B_FALSE;
1248	} else if ((rc == ENOTSUP) || (rc == ENOENT)) {
1249		encp->enc_bug41750_workaround = B_FALSE;
1250	} else {
1251		goto fail9;
1252	}
1253	if (EFX_PCI_FUNCTION_IS_VF(encp)) {
1254		/* Interrupt testing does not work for VFs. See bug50084. */
1255		encp->enc_bug41750_workaround = B_TRUE;
1256	}
1257
1258	/*
1259	 * If the bug26807 workaround is enabled, then firmware has enabled
1260	 * support for chained multicast filters. Firmware will reset (FLR)
1261	 * functions which have filters in the hardware filter table when the
1262	 * workaround is enabled/disabled.
1263	 *
1264	 * We must recheck if the workaround is enabled after inserting the
1265	 * first hardware filter, in case it has been changed since this check.
1266	 */
1267	rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG26807,
1268	    B_TRUE, &flags);
1269	if (rc == 0) {
1270		encp->enc_bug26807_workaround = B_TRUE;
1271		if (flags & (1 << MC_CMD_WORKAROUND_EXT_OUT_FLR_DONE_LBN)) {
1272			/*
1273			 * Other functions had installed filters before the
1274			 * workaround was enabled, and they have been reset
1275			 * by firmware.
1276			 */
1277			EFSYS_PROBE(bug26807_workaround_flr_done);
1278			/* FIXME: bump MC warm boot count ? */
1279		}
1280	} else if (rc == EACCES) {
1281		/*
1282		 * Unprivileged functions cannot enable the workaround in older
1283		 * firmware.
1284		 */
1285		encp->enc_bug26807_workaround = B_FALSE;
1286	} else if ((rc == ENOTSUP) || (rc == ENOENT)) {
1287		encp->enc_bug26807_workaround = B_FALSE;
1288	} else {
1289		goto fail10;
1290	}
1291
1292	/* Get sysclk frequency (in MHz). */
1293	if ((rc = efx_mcdi_get_clock(enp, &sysclk)) != 0)
1294		goto fail11;
1295
1296	/*
1297	 * The timer quantum is 1536 sysclk cycles, documented for the
1298	 * EV_TMR_VAL field of EV_TIMER_TBL. Scale for MHz and ns units.
1299	 */
1300	encp->enc_evq_timer_quantum_ns = 1536000UL / sysclk; /* 1536 cycles */
1301	if (encp->enc_bug35388_workaround) {
1302		encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
1303		ERF_DD_EVQ_IND_TIMER_VAL_WIDTH) / 1000;
1304	} else {
1305		encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
1306		FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
1307	}
1308
1309	/* Check capabilities of running datapath firmware */
1310	if ((rc = ef10_get_datapath_caps(enp)) != 0)
1311	    goto fail12;
1312
1313	/* Alignment for receive packet DMA buffers */
1314	encp->enc_rx_buf_align_start = 1;
1315	encp->enc_rx_buf_align_end = 64; /* RX DMA end padding */
1316
1317	/* Alignment for WPTR updates */
1318	encp->enc_rx_push_align = EF10_RX_WPTR_ALIGN;
1319
1320	/*
1321	 * Set resource limits for MC_CMD_ALLOC_VIS. Note that we cannot use
1322	 * MC_CMD_GET_RESOURCE_LIMITS here as that reports the available
1323	 * resources (allocated to this PCIe function), which is zero until
1324	 * after we have allocated VIs.
1325	 */
1326	encp->enc_evq_limit = 1024;
1327	encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
1328	encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
1329
1330	encp->enc_buftbl_limit = 0xFFFFFFFF;
1331
1332	encp->enc_piobuf_limit = HUNT_PIOBUF_NBUFS;
1333	encp->enc_piobuf_size = HUNT_PIOBUF_SIZE;
1334	encp->enc_piobuf_min_alloc_size = HUNT_MIN_PIO_ALLOC_SIZE;
1335
1336	/*
1337	 * Get the current privilege mask. Note that this may be modified
1338	 * dynamically, so this value is informational only. DO NOT use
1339	 * the privilege mask to check for sufficient privileges, as that
1340	 * can result in time-of-check/time-of-use bugs.
1341	 */
1342	if ((rc = ef10_get_privilege_mask(enp, &mask)) != 0)
1343		goto fail13;
1344	encp->enc_privilege_mask = mask;
1345
1346	/* Get interrupt vector limits */
1347	if ((rc = efx_mcdi_get_vector_cfg(enp, &base, &nvec, NULL)) != 0) {
1348		if (EFX_PCI_FUNCTION_IS_PF(encp))
1349			goto fail14;
1350
1351		/* Ignore error (cannot query vector limits from a VF). */
1352		base = 0;
1353		nvec = 1024;
1354	}
1355	encp->enc_intr_vec_base = base;
1356	encp->enc_intr_limit = nvec;
1357
1358	/*
1359	 * Maximum number of bytes into the frame the TCP header can start for
1360	 * firmware assisted TSO to work.
1361	 */
1362	encp->enc_tx_tso_tcp_header_offset_limit = EF10_TCP_HEADER_OFFSET_LIMIT;
1363
1364	return (0);
1365
1366fail14:
1367	EFSYS_PROBE(fail14);
1368fail13:
1369	EFSYS_PROBE(fail13);
1370fail12:
1371	EFSYS_PROBE(fail12);
1372fail11:
1373	EFSYS_PROBE(fail11);
1374fail10:
1375	EFSYS_PROBE(fail10);
1376fail9:
1377	EFSYS_PROBE(fail9);
1378fail8:
1379	EFSYS_PROBE(fail8);
1380fail7:
1381	EFSYS_PROBE(fail7);
1382fail6:
1383	EFSYS_PROBE(fail6);
1384fail5:
1385	EFSYS_PROBE(fail5);
1386fail4:
1387	EFSYS_PROBE(fail4);
1388fail3:
1389	EFSYS_PROBE(fail3);
1390fail2:
1391	EFSYS_PROBE(fail2);
1392fail1:
1393	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1394
1395	return (rc);
1396}
1397
1398
1399	__checkReturn	efx_rc_t
1400ef10_nic_probe(
1401	__in		efx_nic_t *enp)
1402{
1403	const efx_nic_ops_t *enop = enp->en_enop;
1404	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1405	efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1406	efx_rc_t rc;
1407
1408	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1409		    enp->en_family == EFX_FAMILY_MEDFORD);
1410
1411	/* Read and clear any assertion state */
1412	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1413		goto fail1;
1414
1415	/* Exit the assertion handler */
1416	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1417		if (rc != EACCES)
1418			goto fail2;
1419
1420	if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
1421		goto fail3;
1422
1423	if ((rc = enop->eno_board_cfg(enp)) != 0)
1424		if (rc != EACCES)
1425			goto fail4;
1426
1427	/*
1428	 * Set default driver config limits (based on board config).
1429	 *
1430	 * FIXME: For now allocate a fixed number of VIs which is likely to be
1431	 * sufficient and small enough to allow multiple functions on the same
1432	 * port.
1433	 */
1434	edcp->edc_min_vi_count = edcp->edc_max_vi_count =
1435	    MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit));
1436
1437	/* The client driver must configure and enable PIO buffer support */
1438	edcp->edc_max_piobuf_count = 0;
1439	edcp->edc_pio_alloc_size = 0;
1440
1441#if EFSYS_OPT_MAC_STATS
1442	/* Wipe the MAC statistics */
1443	if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
1444		goto fail5;
1445#endif
1446
1447#if EFSYS_OPT_LOOPBACK
1448	if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
1449		goto fail6;
1450#endif
1451
1452#if EFSYS_OPT_MON_STATS
1453	if ((rc = mcdi_mon_cfg_build(enp)) != 0) {
1454		/* Unprivileged functions do not have access to sensors */
1455		if (rc != EACCES)
1456			goto fail7;
1457	}
1458#endif
1459
1460	encp->enc_features = enp->en_features;
1461
1462	return (0);
1463
1464#if EFSYS_OPT_MON_STATS
1465fail7:
1466	EFSYS_PROBE(fail7);
1467#endif
1468#if EFSYS_OPT_LOOPBACK
1469fail6:
1470	EFSYS_PROBE(fail6);
1471#endif
1472#if EFSYS_OPT_MAC_STATS
1473fail5:
1474	EFSYS_PROBE(fail5);
1475#endif
1476fail4:
1477	EFSYS_PROBE(fail4);
1478fail3:
1479	EFSYS_PROBE(fail3);
1480fail2:
1481	EFSYS_PROBE(fail2);
1482fail1:
1483	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1484
1485	return (rc);
1486}
1487
1488	__checkReturn	efx_rc_t
1489ef10_nic_set_drv_limits(
1490	__inout		efx_nic_t *enp,
1491	__in		efx_drv_limits_t *edlp)
1492{
1493	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1494	efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1495	uint32_t min_evq_count, max_evq_count;
1496	uint32_t min_rxq_count, max_rxq_count;
1497	uint32_t min_txq_count, max_txq_count;
1498	efx_rc_t rc;
1499
1500	if (edlp == NULL) {
1501		rc = EINVAL;
1502		goto fail1;
1503	}
1504
1505	/* Get minimum required and maximum usable VI limits */
1506	min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit);
1507	min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit);
1508	min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit);
1509
1510	edcp->edc_min_vi_count =
1511	    MAX(min_evq_count, MAX(min_rxq_count, min_txq_count));
1512
1513	max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit);
1514	max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit);
1515	max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit);
1516
1517	edcp->edc_max_vi_count =
1518	    MAX(max_evq_count, MAX(max_rxq_count, max_txq_count));
1519
1520	/*
1521	 * Check limits for sub-allocated piobuf blocks.
1522	 * PIO is optional, so don't fail if the limits are incorrect.
1523	 */
1524	if ((encp->enc_piobuf_size == 0) ||
1525	    (encp->enc_piobuf_limit == 0) ||
1526	    (edlp->edl_min_pio_alloc_size == 0) ||
1527	    (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) {
1528		/* Disable PIO */
1529		edcp->edc_max_piobuf_count = 0;
1530		edcp->edc_pio_alloc_size = 0;
1531	} else {
1532		uint32_t blk_size, blk_count, blks_per_piobuf;
1533
1534		blk_size =
1535		    MAX(edlp->edl_min_pio_alloc_size,
1536			    encp->enc_piobuf_min_alloc_size);
1537
1538		blks_per_piobuf = encp->enc_piobuf_size / blk_size;
1539		EFSYS_ASSERT3U(blks_per_piobuf, <=, 32);
1540
1541		blk_count = (encp->enc_piobuf_limit * blks_per_piobuf);
1542
1543		/* A zero max pio alloc count means unlimited */
1544		if ((edlp->edl_max_pio_alloc_count > 0) &&
1545		    (edlp->edl_max_pio_alloc_count < blk_count)) {
1546			blk_count = edlp->edl_max_pio_alloc_count;
1547		}
1548
1549		edcp->edc_pio_alloc_size = blk_size;
1550		edcp->edc_max_piobuf_count =
1551		    (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf;
1552	}
1553
1554	return (0);
1555
1556fail1:
1557	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1558
1559	return (rc);
1560}
1561
1562
1563	__checkReturn	efx_rc_t
1564ef10_nic_reset(
1565	__in		efx_nic_t *enp)
1566{
1567	efx_mcdi_req_t req;
1568	uint8_t payload[MAX(MC_CMD_ENTITY_RESET_IN_LEN,
1569			    MC_CMD_ENTITY_RESET_OUT_LEN)];
1570	efx_rc_t rc;
1571
1572	/* ef10_nic_reset() is called to recover from BADASSERT failures. */
1573	if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1574		goto fail1;
1575	if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1576		goto fail2;
1577
1578	(void) memset(payload, 0, sizeof (payload));
1579	req.emr_cmd = MC_CMD_ENTITY_RESET;
1580	req.emr_in_buf = payload;
1581	req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN;
1582	req.emr_out_buf = payload;
1583	req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN;
1584
1585	MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG,
1586	    ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1);
1587
1588	efx_mcdi_execute(enp, &req);
1589
1590	if (req.emr_rc != 0) {
1591		rc = req.emr_rc;
1592		goto fail3;
1593	}
1594
1595	/* Clear RX/TX DMA queue errors */
1596	enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR);
1597
1598	return (0);
1599
1600fail3:
1601	EFSYS_PROBE(fail3);
1602fail2:
1603	EFSYS_PROBE(fail2);
1604fail1:
1605	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1606
1607	return (rc);
1608}
1609
1610	__checkReturn	efx_rc_t
1611ef10_nic_init(
1612	__in		efx_nic_t *enp)
1613{
1614	efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1615	uint32_t min_vi_count, max_vi_count;
1616	uint32_t vi_count, vi_base, vi_shift;
1617	uint32_t i;
1618	uint32_t retry;
1619	uint32_t delay_us;
1620	efx_rc_t rc;
1621
1622	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1623		    enp->en_family == EFX_FAMILY_MEDFORD);
1624
1625	/* Enable reporting of some events (e.g. link change) */
1626	if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
1627		goto fail1;
1628
1629	/* Allocate (optional) on-chip PIO buffers */
1630	ef10_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count);
1631
1632	/*
1633	 * For best performance, PIO writes should use a write-combined
1634	 * (WC) memory mapping. Using a separate WC mapping for the PIO
1635	 * aperture of each VI would be a burden to drivers (and not
1636	 * possible if the host page size is >4Kbyte).
1637	 *
1638	 * To avoid this we use a single uncached (UC) mapping for VI
1639	 * register access, and a single WC mapping for extra VIs used
1640	 * for PIO writes.
1641	 *
1642	 * Each piobuf must be linked to a VI in the WC mapping, and to
1643	 * each VI that is using a sub-allocated block from the piobuf.
1644	 */
1645	min_vi_count = edcp->edc_min_vi_count;
1646	max_vi_count =
1647	    edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count;
1648
1649	/* Ensure that the previously attached driver's VIs are freed */
1650	if ((rc = efx_mcdi_free_vis(enp)) != 0)
1651		goto fail2;
1652
1653	/*
1654	 * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this
1655	 * fails then retrying the request for fewer VI resources may succeed.
1656	 */
1657	vi_count = 0;
1658	if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count,
1659		    &vi_base, &vi_count, &vi_shift)) != 0)
1660		goto fail3;
1661
1662	EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count);
1663
1664	if (vi_count < min_vi_count) {
1665		rc = ENOMEM;
1666		goto fail4;
1667	}
1668
1669	enp->en_arch.ef10.ena_vi_base = vi_base;
1670	enp->en_arch.ef10.ena_vi_count = vi_count;
1671	enp->en_arch.ef10.ena_vi_shift = vi_shift;
1672
1673	if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) {
1674		/* Not enough extra VIs to map piobufs */
1675		ef10_nic_free_piobufs(enp);
1676	}
1677
1678	enp->en_arch.ef10.ena_pio_write_vi_base =
1679	    vi_count - enp->en_arch.ef10.ena_piobuf_count;
1680
1681	/* Save UC memory mapping details */
1682	enp->en_arch.ef10.ena_uc_mem_map_offset = 0;
1683	if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1684		enp->en_arch.ef10.ena_uc_mem_map_size =
1685		    (ER_DZ_TX_PIOBUF_STEP *
1686		    enp->en_arch.ef10.ena_pio_write_vi_base);
1687	} else {
1688		enp->en_arch.ef10.ena_uc_mem_map_size =
1689		    (ER_DZ_TX_PIOBUF_STEP *
1690		    enp->en_arch.ef10.ena_vi_count);
1691	}
1692
1693	/* Save WC memory mapping details */
1694	enp->en_arch.ef10.ena_wc_mem_map_offset =
1695	    enp->en_arch.ef10.ena_uc_mem_map_offset +
1696	    enp->en_arch.ef10.ena_uc_mem_map_size;
1697
1698	enp->en_arch.ef10.ena_wc_mem_map_size =
1699	    (ER_DZ_TX_PIOBUF_STEP *
1700	    enp->en_arch.ef10.ena_piobuf_count);
1701
1702	/* Link piobufs to extra VIs in WC mapping */
1703	if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1704		for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1705			rc = efx_mcdi_link_piobuf(enp,
1706			    enp->en_arch.ef10.ena_pio_write_vi_base + i,
1707			    enp->en_arch.ef10.ena_piobuf_handle[i]);
1708			if (rc != 0)
1709				break;
1710		}
1711	}
1712
1713	/*
1714	 * Allocate a vAdaptor attached to our upstream vPort/pPort.
1715	 *
1716	 * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF
1717	 * driver has yet to bring up the EVB port. See bug 56147. In this case,
1718	 * retry the request several times after waiting a while. The wait time
1719	 * between retries starts small (10ms) and exponentially increases.
1720	 * Total wait time is a little over two seconds. Retry logic in the
1721	 * client driver may mean this whole loop is repeated if it continues to
1722	 * fail.
1723	 */
1724	retry = 0;
1725	delay_us = 10000;
1726	while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) {
1727		if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) ||
1728		    (rc != ENOENT)) {
1729			/*
1730			 * Do not retry alloc for PF, or for other errors on
1731			 * a VF.
1732			 */
1733			goto fail5;
1734		}
1735
1736		/* VF startup before PF is ready. Retry allocation. */
1737		if (retry > 5) {
1738			/* Too many attempts */
1739			rc = EINVAL;
1740			goto fail6;
1741		}
1742		EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry);
1743		EFSYS_SLEEP(delay_us);
1744		retry++;
1745		if (delay_us < 500000)
1746			delay_us <<= 2;
1747	}
1748
1749	enp->en_vport_id = EVB_PORT_ID_ASSIGNED;
1750	enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2;
1751
1752	return (0);
1753
1754fail6:
1755	EFSYS_PROBE(fail6);
1756fail5:
1757	EFSYS_PROBE(fail5);
1758fail4:
1759	EFSYS_PROBE(fail4);
1760fail3:
1761	EFSYS_PROBE(fail3);
1762fail2:
1763	EFSYS_PROBE(fail2);
1764
1765	ef10_nic_free_piobufs(enp);
1766
1767fail1:
1768	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1769
1770	return (rc);
1771}
1772
1773	__checkReturn	efx_rc_t
1774ef10_nic_get_vi_pool(
1775	__in		efx_nic_t *enp,
1776	__out		uint32_t *vi_countp)
1777{
1778	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1779		    enp->en_family == EFX_FAMILY_MEDFORD);
1780
1781	/*
1782	 * Report VIs that the client driver can use.
1783	 * Do not include VIs used for PIO buffer writes.
1784	 */
1785	*vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base;
1786
1787	return (0);
1788}
1789
1790	__checkReturn	efx_rc_t
1791ef10_nic_get_bar_region(
1792	__in		efx_nic_t *enp,
1793	__in		efx_nic_region_t region,
1794	__out		uint32_t *offsetp,
1795	__out		size_t *sizep)
1796{
1797	efx_rc_t rc;
1798
1799	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1800		    enp->en_family == EFX_FAMILY_MEDFORD);
1801
1802	/*
1803	 * TODO: Specify host memory mapping alignment and granularity
1804	 * in efx_drv_limits_t so that they can be taken into account
1805	 * when allocating extra VIs for PIO writes.
1806	 */
1807	switch (region) {
1808	case EFX_REGION_VI:
1809		/* UC mapped memory BAR region for VI registers */
1810		*offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset;
1811		*sizep = enp->en_arch.ef10.ena_uc_mem_map_size;
1812		break;
1813
1814	case EFX_REGION_PIO_WRITE_VI:
1815		/* WC mapped memory BAR region for piobuf writes */
1816		*offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset;
1817		*sizep = enp->en_arch.ef10.ena_wc_mem_map_size;
1818		break;
1819
1820	default:
1821		rc = EINVAL;
1822		goto fail1;
1823	}
1824
1825	return (0);
1826
1827fail1:
1828	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1829
1830	return (rc);
1831}
1832
1833			void
1834ef10_nic_fini(
1835	__in		efx_nic_t *enp)
1836{
1837	uint32_t i;
1838	efx_rc_t rc;
1839
1840	(void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id);
1841	enp->en_vport_id = 0;
1842
1843	/* Unlink piobufs from extra VIs in WC mapping */
1844	if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1845		for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1846			rc = efx_mcdi_unlink_piobuf(enp,
1847			    enp->en_arch.ef10.ena_pio_write_vi_base + i);
1848			if (rc != 0)
1849				break;
1850		}
1851	}
1852
1853	ef10_nic_free_piobufs(enp);
1854
1855	(void) efx_mcdi_free_vis(enp);
1856	enp->en_arch.ef10.ena_vi_count = 0;
1857}
1858
1859			void
1860ef10_nic_unprobe(
1861	__in		efx_nic_t *enp)
1862{
1863#if EFSYS_OPT_MON_STATS
1864	mcdi_mon_cfg_free(enp);
1865#endif /* EFSYS_OPT_MON_STATS */
1866	(void) efx_mcdi_drv_attach(enp, B_FALSE);
1867}
1868
1869#if EFSYS_OPT_DIAG
1870
1871	__checkReturn	efx_rc_t
1872ef10_nic_register_test(
1873	__in		efx_nic_t *enp)
1874{
1875	efx_rc_t rc;
1876
1877	/* FIXME */
1878	_NOTE(ARGUNUSED(enp))
1879	if (B_FALSE) {
1880		rc = ENOTSUP;
1881		goto fail1;
1882	}
1883	/* FIXME */
1884
1885	return (0);
1886
1887fail1:
1888	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1889
1890	return (rc);
1891}
1892
1893#endif	/* EFSYS_OPT_DIAG */
1894
1895
1896
1897#endif	/* EFSYS_OPT_HUNTINGTON */
1898