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