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