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