]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/sfxge/common/hunt_nic.c
sfxge: fix interrupt handling for Medford
[FreeBSD/FreeBSD.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_arch.ef10.ena_piobuf_handle));
719
720         enp->en_arch.ef10.ena_piobuf_count = 0;
721
722         for (i = 0; i < max_piobuf_count; i++) {
723                 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
724
725                 if ((rc = efx_mcdi_alloc_piobuf(enp, handlep)) != 0)
726                         goto fail1;
727
728                 enp->en_arch.ef10.ena_pio_alloc_map[i] = 0;
729                 enp->en_arch.ef10.ena_piobuf_count++;
730         }
731
732         return;
733
734 fail1:
735         for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
736                 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
737
738                 efx_mcdi_free_piobuf(enp, *handlep);
739                 *handlep = EFX_PIOBUF_HANDLE_INVALID;
740         }
741         enp->en_arch.ef10.ena_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_arch.ef10.ena_piobuf_count; i++) {
753                 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
754
755                 efx_mcdi_free_piobuf(enp, *handlep);
756                 *handlep = EFX_PIOBUF_HANDLE_INVALID;
757         }
758         enp->en_arch.ef10.ena_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_nic_cfg_t *encp = &enp->en_nic_cfg;
772         efx_drv_cfg_t *edcp = &enp->en_drv_cfg;
773         uint32_t blk_per_buf;
774         uint32_t buf, blk;
775         efx_rc_t rc;
776
777         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_HUNTINGTON);
778         EFSYS_ASSERT(bufnump);
779         EFSYS_ASSERT(handlep);
780         EFSYS_ASSERT(blknump);
781         EFSYS_ASSERT(offsetp);
782         EFSYS_ASSERT(sizep);
783
784         if ((edcp->edc_pio_alloc_size == 0) ||
785             (enp->en_arch.ef10.ena_piobuf_count == 0)) {
786                 rc = ENOMEM;
787                 goto fail1;
788         }
789         blk_per_buf = encp->enc_piobuf_size / edcp->edc_pio_alloc_size;
790
791         for (buf = 0; buf < enp->en_arch.ef10.ena_piobuf_count; buf++) {
792                 uint32_t *map = &enp->en_arch.ef10.ena_pio_alloc_map[buf];
793
794                 if (~(*map) == 0)
795                         continue;
796
797                 EFSYS_ASSERT3U(blk_per_buf, <=, (8 * sizeof (*map)));
798                 for (blk = 0; blk < blk_per_buf; blk++) {
799                         if ((*map & (1u << blk)) == 0) {
800                                 *map |= (1u << blk);
801                                 goto done;
802                         }
803                 }
804         }
805         rc = ENOMEM;
806         goto fail2;
807
808 done:
809         *handlep = enp->en_arch.ef10.ena_piobuf_handle[buf];
810         *bufnump = buf;
811         *blknump = blk;
812         *sizep = edcp->edc_pio_alloc_size;
813         *offsetp = blk * (*sizep);
814
815         return (0);
816
817 fail2:
818         EFSYS_PROBE(fail2);
819 fail1:
820         EFSYS_PROBE1(fail1, efx_rc_t, rc);
821
822         return (rc);
823 }
824
825 /* Free a piobuf sub-allocated block */
826         __checkReturn   efx_rc_t
827 hunt_nic_pio_free(
828         __inout         efx_nic_t *enp,
829         __in            uint32_t bufnum,
830         __in            uint32_t blknum)
831 {
832         uint32_t *map;
833         efx_rc_t rc;
834
835         if ((bufnum >= enp->en_arch.ef10.ena_piobuf_count) ||
836             (blknum >= (8 * sizeof (*map)))) {
837                 rc = EINVAL;
838                 goto fail1;
839         }
840
841         map = &enp->en_arch.ef10.ena_pio_alloc_map[bufnum];
842         if ((*map & (1u << blknum)) == 0) {
843                 rc = ENOENT;
844                 goto fail2;
845         }
846         *map &= ~(1u << blknum);
847
848         return (0);
849
850 fail2:
851         EFSYS_PROBE(fail2);
852 fail1:
853         EFSYS_PROBE1(fail1, efx_rc_t, rc);
854
855         return (rc);
856 }
857
858         __checkReturn   efx_rc_t
859 hunt_nic_pio_link(
860         __inout         efx_nic_t *enp,
861         __in            uint32_t vi_index,
862         __in            efx_piobuf_handle_t handle)
863 {
864         return (efx_mcdi_link_piobuf(enp, vi_index, handle));
865 }
866
867         __checkReturn   efx_rc_t
868 hunt_nic_pio_unlink(
869         __inout         efx_nic_t *enp,
870         __in            uint32_t vi_index)
871 {
872         return (efx_mcdi_unlink_piobuf(enp, vi_index));
873 }
874
875 static  __checkReturn   efx_rc_t
876 hunt_get_datapath_caps(
877         __in            efx_nic_t *enp)
878 {
879         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
880         efx_dword_t datapath_capabilities;
881         efx_rc_t rc;
882
883         if ((rc = efx_mcdi_get_capabilities(enp, &datapath_capabilities)) != 0)
884                 goto fail1;
885
886         /*
887          * Huntington RXDP firmware inserts a 0 or 14 byte prefix.
888          * We only support the 14 byte prefix here.
889          */
890         if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities,
891                 GET_CAPABILITIES_OUT_RX_PREFIX_LEN_14) != 1) {
892                 rc = ENOTSUP;
893                 goto fail2;
894         }
895         encp->enc_rx_prefix_size = 14;
896
897         /* Check if the firmware supports TSO */
898         if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities,
899                                 GET_CAPABILITIES_OUT_TX_TSO) == 1)
900                 encp->enc_fw_assisted_tso_enabled = B_TRUE;
901         else
902                 encp->enc_fw_assisted_tso_enabled = B_FALSE;
903
904         /* Check if the firmware has vadapter/vport/vswitch support */
905         if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities,
906                                 GET_CAPABILITIES_OUT_EVB) == 1)
907                 encp->enc_datapath_cap_evb = B_TRUE;
908         else
909                 encp->enc_datapath_cap_evb = B_FALSE;
910
911         /* Check if the firmware supports VLAN insertion */
912         if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities,
913                                 GET_CAPABILITIES_OUT_TX_VLAN_INSERTION) == 1)
914                 encp->enc_hw_tx_insert_vlan_enabled = B_TRUE;
915         else
916                 encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
917
918         /* Check if the firmware supports RX event batching */
919         if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities,
920                 GET_CAPABILITIES_OUT_RX_BATCHING) == 1) {
921                 encp->enc_rx_batching_enabled = B_TRUE;
922                 encp->enc_rx_batch_max = 16;
923         } else {
924                 encp->enc_rx_batching_enabled = B_FALSE;
925         }
926
927         /* Check if the firmware supports disabling scatter on RXQs */
928         if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities,
929                             GET_CAPABILITIES_OUT_RX_DISABLE_SCATTER) == 1) {
930                 encp->enc_rx_disable_scatter_supported = B_TRUE;
931         } else {
932                 encp->enc_rx_disable_scatter_supported = B_FALSE;
933         }
934
935         /* Check if the firmware supports set mac with running filters */
936         if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities,
937             GET_CAPABILITIES_OUT_VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED)
938             == 1) {
939                 encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
940         } else {
941                 encp->enc_allow_set_mac_with_installed_filters = B_FALSE;
942         }
943
944         return (0);
945
946 fail2:
947         EFSYS_PROBE(fail2);
948 fail1:
949         EFSYS_PROBE1(fail1, efx_rc_t, rc);
950
951         return (rc);
952 }
953
954 /*
955  * The external port mapping is a one-based numbering of the external
956  * connectors on the board. It does not distinguish off-board separated
957  * outputs such as multi-headed cables.
958  * The number of ports that map to each external port connector
959  * on the board is determined by the chip family and the port modes to
960  * which the NIC can be configured. The mapping table lists modes with
961  * port numbering requirements in increasing order.
962  */
963 static struct {
964         efx_family_t    family;
965         uint32_t        modes_mask;
966         uint32_t        stride;
967 }       __hunt_external_port_mappings[] = {
968         /* Supported modes requiring 1 output per port */
969         {
970                 EFX_FAMILY_HUNTINGTON,
971                 (1 << TLV_PORT_MODE_10G) |
972                 (1 << TLV_PORT_MODE_10G_10G) |
973                 (1 << TLV_PORT_MODE_10G_10G_10G_10G),
974                 1
975         },
976         /* Supported modes requiring 2 outputs per port */
977         {
978                 EFX_FAMILY_HUNTINGTON,
979                 (1 << TLV_PORT_MODE_40G) |
980                 (1 << TLV_PORT_MODE_40G_40G) |
981                 (1 << TLV_PORT_MODE_40G_10G_10G) |
982                 (1 << TLV_PORT_MODE_10G_10G_40G),
983                 2
984         }
985         /*
986          * NOTE: Medford modes will require 4 outputs per port:
987          *      TLV_PORT_MODE_10G_10G_10G_10G_Q
988          *      TLV_PORT_MODE_10G_10G_10G_10G_Q2
989          * The Q2 mode routes outputs to external port 2. Support for this
990          * will require a new field specifying the number to add after
991          * scaling by stride. This is fixed at 1 currently.
992          */
993 };
994
995 static  __checkReturn   efx_rc_t
996 hunt_external_port_mapping(
997         __in            efx_nic_t *enp,
998         __in            uint32_t port,
999         __out           uint8_t *external_portp)
1000 {
1001         efx_rc_t rc;
1002         int i;
1003         uint32_t port_modes;
1004         uint32_t matches;
1005         uint32_t stride = 1; /* default 1-1 mapping */
1006
1007         if ((rc = efx_mcdi_get_port_modes(enp, &port_modes)) != 0) {
1008                 /* No port mode information available - use default mapping */
1009                 goto out;
1010         }
1011
1012         /*
1013          * Infer the internal port -> external port mapping from
1014          * the possible port modes for this NIC.
1015          */
1016         for (i = 0; i < EFX_ARRAY_SIZE(__hunt_external_port_mappings); ++i) {
1017                 if (__hunt_external_port_mappings[i].family !=
1018                     enp->en_family)
1019                         continue;
1020                 matches = (__hunt_external_port_mappings[i].modes_mask &
1021                     port_modes);
1022                 if (matches != 0) {
1023                         stride = __hunt_external_port_mappings[i].stride;
1024                         port_modes &= ~matches;
1025                 }
1026         }
1027
1028         if (port_modes != 0) {
1029                 /* Some advertised modes are not supported */
1030                 rc = ENOTSUP;
1031                 goto fail1;
1032         }
1033
1034 out:
1035         /*
1036          * Scale as required by last matched mode and then convert to
1037          * one-based numbering
1038          */
1039         *external_portp = (uint8_t)(port / stride) + 1;
1040         return (0);
1041
1042 fail1:
1043         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1044
1045         return (rc);
1046 }
1047
1048 static  __checkReturn   efx_rc_t
1049 hunt_board_cfg(
1050         __in            efx_nic_t *enp)
1051 {
1052         efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
1053         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1054         uint8_t mac_addr[6];
1055         uint32_t board_type = 0;
1056         hunt_link_state_t hls;
1057         efx_port_t *epp = &(enp->en_port);
1058         uint32_t port;
1059         uint32_t pf;
1060         uint32_t vf;
1061         uint32_t mask;
1062         uint32_t flags;
1063         uint32_t sysclk;
1064         uint32_t base, nvec;
1065         efx_rc_t rc;
1066
1067         if ((rc = efx_mcdi_get_port_assignment(enp, &port)) != 0)
1068                 goto fail1;
1069
1070         /*
1071          * NOTE: The MCDI protocol numbers ports from zero.
1072          * The common code MCDI interface numbers ports from one.
1073          */
1074         emip->emi_port = port + 1;
1075
1076         if ((rc = hunt_external_port_mapping(enp, port,
1077                     &encp->enc_external_port)) != 0)
1078                 goto fail2;
1079
1080         /*
1081          * Get PCIe function number from firmware (used for
1082          * per-function privilege and dynamic config info).
1083          *  - PCIe PF: pf = PF number, vf = 0xffff.
1084          *  - PCIe VF: pf = parent PF, vf = VF number.
1085          */
1086         if ((rc = efx_mcdi_get_function_info(enp, &pf, &vf)) != 0)
1087                 goto fail3;
1088
1089         encp->enc_pf = pf;
1090         encp->enc_vf = vf;
1091
1092         /* MAC address for this function */
1093         if (EFX_PCI_FUNCTION_IS_PF(encp)) {
1094                 rc = efx_mcdi_get_mac_address_pf(enp, mac_addr);
1095                 if ((rc == 0) && (mac_addr[0] & 0x02)) {
1096                         /*
1097                          * If the static config does not include a global MAC
1098                          * address pool then the board may return a locally
1099                          * administered MAC address (this should only happen on
1100                          * incorrectly programmed boards).
1101                          */
1102                         rc = EINVAL;
1103                 }
1104         } else {
1105                 rc = efx_mcdi_get_mac_address_vf(enp, mac_addr);
1106         }
1107         if (rc != 0)
1108                 goto fail4;
1109
1110         EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
1111
1112         /* Board configuration */
1113         rc = efx_mcdi_get_board_cfg(enp, &board_type, NULL, NULL);
1114         if (rc != 0) {
1115                 /* Unprivileged functions may not be able to read board cfg */
1116                 if (rc == EACCES)
1117                         board_type = 0;
1118                 else
1119                         goto fail5;
1120         }
1121
1122         encp->enc_board_type = board_type;
1123         encp->enc_clk_mult = 1; /* not used for Huntington */
1124
1125         /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
1126         if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
1127                 goto fail6;
1128
1129         /* Obtain the default PHY advertised capabilities */
1130         if ((rc = hunt_phy_get_link(enp, &hls)) != 0)
1131                 goto fail7;
1132         epp->ep_default_adv_cap_mask = hls.hls_adv_cap_mask;
1133         epp->ep_adv_cap_mask = hls.hls_adv_cap_mask;
1134
1135         /*
1136          * Enable firmware workarounds for hardware errata.
1137          * Expected responses are:
1138          *  - 0 (zero):
1139          *      Success: workaround enabled or disabled as requested.
1140          *  - MC_CMD_ERR_ENOSYS (reported as ENOTSUP):
1141          *      Firmware does not support the MC_CMD_WORKAROUND request.
1142          *      (assume that the workaround is not supported).
1143          *  - MC_CMD_ERR_ENOENT (reported as ENOENT):
1144          *      Firmware does not support the requested workaround.
1145          *  - MC_CMD_ERR_EPERM  (reported as EACCES):
1146          *      Unprivileged function cannot enable/disable workarounds.
1147          *
1148          * See efx_mcdi_request_errcode() for MCDI error translations.
1149          */
1150
1151         /*
1152          * If the bug35388 workaround is enabled, then use an indirect access
1153          * method to avoid unsafe EVQ writes.
1154          */
1155         rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG35388, B_TRUE,
1156             NULL);
1157         if ((rc == 0) || (rc == EACCES))
1158                 encp->enc_bug35388_workaround = B_TRUE;
1159         else if ((rc == ENOTSUP) || (rc == ENOENT))
1160                 encp->enc_bug35388_workaround = B_FALSE;
1161         else
1162                 goto fail8;
1163
1164         /*
1165          * If the bug41750 workaround is enabled, then do not test interrupts,
1166          * as the test will fail (seen with Greenport controllers).
1167          */
1168         rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG41750, B_TRUE,
1169             NULL);
1170         if (rc == 0) {
1171                 encp->enc_bug41750_workaround = B_TRUE;
1172         } else if (rc == EACCES) {
1173                 /* Assume a controller with 40G ports needs the workaround. */
1174                 if (epp->ep_default_adv_cap_mask & EFX_PHY_CAP_40000FDX)
1175                         encp->enc_bug41750_workaround = B_TRUE;
1176                 else
1177                         encp->enc_bug41750_workaround = B_FALSE;
1178         } else if ((rc == ENOTSUP) || (rc == ENOENT)) {
1179                 encp->enc_bug41750_workaround = B_FALSE;
1180         } else {
1181                 goto fail9;
1182         }
1183         if (EFX_PCI_FUNCTION_IS_VF(encp)) {
1184                 /* Interrupt testing does not work for VFs. See bug50084. */
1185                 encp->enc_bug41750_workaround = B_TRUE;
1186         }
1187
1188         /*
1189          * If the bug26807 workaround is enabled, then firmware has enabled
1190          * support for chained multicast filters. Firmware will reset (FLR)
1191          * functions which have filters in the hardware filter table when the
1192          * workaround is enabled/disabled.
1193          *
1194          * We must recheck if the workaround is enabled after inserting the
1195          * first hardware filter, in case it has been changed since this check.
1196          */
1197         rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG26807,
1198             B_TRUE, &flags);
1199         if (rc == 0) {
1200                 encp->enc_bug26807_workaround = B_TRUE;
1201                 if (flags & (1 << MC_CMD_WORKAROUND_EXT_OUT_FLR_DONE_LBN)) {
1202                         /*
1203                          * Other functions had installed filters before the
1204                          * workaround was enabled, and they have been reset
1205                          * by firmware.
1206                          */
1207                         EFSYS_PROBE(bug26807_workaround_flr_done);
1208                         /* FIXME: bump MC warm boot count ? */
1209                 }
1210         } else if (rc == EACCES) {
1211                 /*
1212                  * Unprivileged functions cannot enable the workaround in older
1213                  * firmware.
1214                  */
1215                 encp->enc_bug26807_workaround = B_FALSE;
1216         } else if ((rc == ENOTSUP) || (rc == ENOENT)) {
1217                 encp->enc_bug26807_workaround = B_FALSE;
1218         } else {
1219                 goto fail10;
1220         }
1221
1222         /* Get sysclk frequency (in MHz). */
1223         if ((rc = efx_mcdi_get_clock(enp, &sysclk)) != 0)
1224                 goto fail11;
1225
1226         /*
1227          * The timer quantum is 1536 sysclk cycles, documented for the
1228          * EV_TMR_VAL field of EV_TIMER_TBL. Scale for MHz and ns units.
1229          */
1230         encp->enc_evq_timer_quantum_ns = 1536000UL / sysclk; /* 1536 cycles */
1231         if (encp->enc_bug35388_workaround) {
1232                 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
1233                 ERF_DD_EVQ_IND_TIMER_VAL_WIDTH) / 1000;
1234         } else {
1235                 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
1236                 FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
1237         }
1238
1239         /* Check capabilities of running datapath firmware */
1240         if ((rc = hunt_get_datapath_caps(enp)) != 0)
1241             goto fail12;
1242
1243         /* Alignment for receive packet DMA buffers */
1244         encp->enc_rx_buf_align_start = 1;
1245         encp->enc_rx_buf_align_end = 64; /* RX DMA end padding */
1246
1247         /* Alignment for WPTR updates */
1248         encp->enc_rx_push_align = HUNTINGTON_RX_WPTR_ALIGN;
1249
1250         /*
1251          * Set resource limits for MC_CMD_ALLOC_VIS. Note that we cannot use
1252          * MC_CMD_GET_RESOURCE_LIMITS here as that reports the available
1253          * resources (allocated to this PCIe function), which is zero until
1254          * after we have allocated VIs.
1255          */
1256         encp->enc_evq_limit = 1024;
1257         encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
1258         encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
1259
1260         encp->enc_buftbl_limit = 0xFFFFFFFF;
1261
1262         encp->enc_piobuf_limit = HUNT_PIOBUF_NBUFS;
1263         encp->enc_piobuf_size = HUNT_PIOBUF_SIZE;
1264         encp->enc_piobuf_min_alloc_size = HUNT_MIN_PIO_ALLOC_SIZE;
1265
1266         /*
1267          * Get the current privilege mask. Note that this may be modified
1268          * dynamically, so this value is informational only. DO NOT use
1269          * the privilege mask to check for sufficient privileges, as that
1270          * can result in time-of-check/time-of-use bugs.
1271          */
1272         if ((rc = efx_mcdi_privilege_mask(enp, pf, vf, &mask)) != 0) {
1273                 if (rc != ENOTSUP)
1274                         goto fail13;
1275
1276                 /* Fallback for old firmware without privilege mask support */
1277                 if (EFX_PCI_FUNCTION_IS_PF(encp)) {
1278                         /* Assume PF has admin privilege */
1279                         mask = HUNT_LEGACY_PF_PRIVILEGE_MASK;
1280                 } else {
1281                         /* VF is always unprivileged by default */
1282                         mask = HUNT_LEGACY_VF_PRIVILEGE_MASK;
1283                 }
1284         }
1285
1286         encp->enc_privilege_mask = mask;
1287
1288         /* Get interrupt vector limits */
1289         if ((rc = efx_mcdi_get_vector_cfg(enp, &base, &nvec, NULL)) != 0) {
1290                 if (EFX_PCI_FUNCTION_IS_PF(encp))
1291                         goto fail14;
1292
1293                 /* Ignore error (cannot query vector limits from a VF). */
1294                 base = 0;
1295                 nvec = 1024;
1296         }
1297         encp->enc_intr_vec_base = base;
1298         encp->enc_intr_limit = nvec;
1299
1300         /*
1301          * Maximum number of bytes into the frame the TCP header can start for
1302          * firmware assisted TSO to work.
1303          */
1304         encp->enc_tx_tso_tcp_header_offset_limit = 208;
1305
1306         return (0);
1307
1308 fail14:
1309         EFSYS_PROBE(fail14);
1310 fail13:
1311         EFSYS_PROBE(fail13);
1312 fail12:
1313         EFSYS_PROBE(fail12);
1314 fail11:
1315         EFSYS_PROBE(fail11);
1316 fail10:
1317         EFSYS_PROBE(fail10);
1318 fail9:
1319         EFSYS_PROBE(fail9);
1320 fail8:
1321         EFSYS_PROBE(fail8);
1322 fail7:
1323         EFSYS_PROBE(fail7);
1324 fail6:
1325         EFSYS_PROBE(fail6);
1326 fail5:
1327         EFSYS_PROBE(fail5);
1328 fail4:
1329         EFSYS_PROBE(fail4);
1330 fail3:
1331         EFSYS_PROBE(fail3);
1332 fail2:
1333         EFSYS_PROBE(fail2);
1334 fail1:
1335         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1336
1337         return (rc);
1338 }
1339
1340
1341         __checkReturn   efx_rc_t
1342 hunt_nic_probe(
1343         __in            efx_nic_t *enp)
1344 {
1345         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1346         efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1347         efx_rc_t rc;
1348
1349         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_HUNTINGTON);
1350
1351         /* Read and clear any assertion state */
1352         if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1353                 goto fail1;
1354
1355         /* Exit the assertion handler */
1356         if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1357                 if (rc != EACCES)
1358                         goto fail2;
1359
1360         if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
1361                 goto fail3;
1362
1363         if ((rc = hunt_board_cfg(enp)) != 0)
1364                 if (rc != EACCES)
1365                         goto fail4;
1366
1367         /*
1368          * Set default driver config limits (based on board config).
1369          *
1370          * FIXME: For now allocate a fixed number of VIs which is likely to be
1371          * sufficient and small enough to allow multiple functions on the same
1372          * port.
1373          */
1374         edcp->edc_min_vi_count = edcp->edc_max_vi_count =
1375             MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit));
1376
1377         /* The client driver must configure and enable PIO buffer support */
1378         edcp->edc_max_piobuf_count = 0;
1379         edcp->edc_pio_alloc_size = 0;
1380
1381 #if EFSYS_OPT_MAC_STATS
1382         /* Wipe the MAC statistics */
1383         if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
1384                 goto fail5;
1385 #endif
1386
1387 #if EFSYS_OPT_LOOPBACK
1388         if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
1389                 goto fail6;
1390 #endif
1391
1392 #if EFSYS_OPT_MON_STATS
1393         if ((rc = mcdi_mon_cfg_build(enp)) != 0) {
1394                 /* Unprivileged functions do not have access to sensors */
1395                 if (rc != EACCES)
1396                         goto fail7;
1397         }
1398 #endif
1399
1400         encp->enc_features = enp->en_features;
1401
1402         return (0);
1403
1404 #if EFSYS_OPT_MON_STATS
1405 fail7:
1406         EFSYS_PROBE(fail7);
1407 #endif
1408 #if EFSYS_OPT_LOOPBACK
1409 fail6:
1410         EFSYS_PROBE(fail6);
1411 #endif
1412 #if EFSYS_OPT_MAC_STATS
1413 fail5:
1414         EFSYS_PROBE(fail5);
1415 #endif
1416 fail4:
1417         EFSYS_PROBE(fail4);
1418 fail3:
1419         EFSYS_PROBE(fail3);
1420 fail2:
1421         EFSYS_PROBE(fail2);
1422 fail1:
1423         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1424
1425         return (rc);
1426 }
1427
1428         __checkReturn   efx_rc_t
1429 hunt_nic_set_drv_limits(
1430         __inout         efx_nic_t *enp,
1431         __in            efx_drv_limits_t *edlp)
1432 {
1433         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1434         efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1435         uint32_t min_evq_count, max_evq_count;
1436         uint32_t min_rxq_count, max_rxq_count;
1437         uint32_t min_txq_count, max_txq_count;
1438         efx_rc_t rc;
1439
1440         if (edlp == NULL) {
1441                 rc = EINVAL;
1442                 goto fail1;
1443         }
1444
1445         /* Get minimum required and maximum usable VI limits */
1446         min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit);
1447         min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit);
1448         min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit);
1449
1450         edcp->edc_min_vi_count =
1451             MAX(min_evq_count, MAX(min_rxq_count, min_txq_count));
1452
1453         max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit);
1454         max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit);
1455         max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit);
1456
1457         edcp->edc_max_vi_count =
1458             MAX(max_evq_count, MAX(max_rxq_count, max_txq_count));
1459
1460         /*
1461          * Check limits for sub-allocated piobuf blocks.
1462          * PIO is optional, so don't fail if the limits are incorrect.
1463          */
1464         if ((encp->enc_piobuf_size == 0) ||
1465             (encp->enc_piobuf_limit == 0) ||
1466             (edlp->edl_min_pio_alloc_size == 0) ||
1467             (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) {
1468                 /* Disable PIO */
1469                 edcp->edc_max_piobuf_count = 0;
1470                 edcp->edc_pio_alloc_size = 0;
1471         } else {
1472                 uint32_t blk_size, blk_count, blks_per_piobuf;
1473
1474                 blk_size =
1475                     MAX(edlp->edl_min_pio_alloc_size,
1476                             encp->enc_piobuf_min_alloc_size);
1477
1478                 blks_per_piobuf = encp->enc_piobuf_size / blk_size;
1479                 EFSYS_ASSERT3U(blks_per_piobuf, <=, 32);
1480
1481                 blk_count = (encp->enc_piobuf_limit * blks_per_piobuf);
1482
1483                 /* A zero max pio alloc count means unlimited */
1484                 if ((edlp->edl_max_pio_alloc_count > 0) &&
1485                     (edlp->edl_max_pio_alloc_count < blk_count)) {
1486                         blk_count = edlp->edl_max_pio_alloc_count;
1487                 }
1488
1489                 edcp->edc_pio_alloc_size = blk_size;
1490                 edcp->edc_max_piobuf_count =
1491                     (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf;
1492         }
1493
1494         return (0);
1495
1496 fail1:
1497         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1498
1499         return (rc);
1500 }
1501
1502
1503         __checkReturn   efx_rc_t
1504 hunt_nic_reset(
1505         __in            efx_nic_t *enp)
1506 {
1507         efx_mcdi_req_t req;
1508         uint8_t payload[MAX(MC_CMD_ENTITY_RESET_IN_LEN,
1509                             MC_CMD_ENTITY_RESET_OUT_LEN)];
1510         efx_rc_t rc;
1511
1512         /* hunt_nic_reset() is called to recover from BADASSERT failures. */
1513         if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1514                 goto fail1;
1515         if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1516                 goto fail2;
1517
1518         (void) memset(payload, 0, sizeof (payload));
1519         req.emr_cmd = MC_CMD_ENTITY_RESET;
1520         req.emr_in_buf = payload;
1521         req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN;
1522         req.emr_out_buf = payload;
1523         req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN;
1524
1525         MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG,
1526             ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1);
1527
1528         efx_mcdi_execute(enp, &req);
1529
1530         if (req.emr_rc != 0) {
1531                 rc = req.emr_rc;
1532                 goto fail3;
1533         }
1534
1535         /* Clear RX/TX DMA queue errors */
1536         enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR);
1537
1538         return (0);
1539
1540 fail3:
1541         EFSYS_PROBE(fail3);
1542 fail2:
1543         EFSYS_PROBE(fail2);
1544 fail1:
1545         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1546
1547         return (rc);
1548 }
1549
1550         __checkReturn   efx_rc_t
1551 hunt_nic_init(
1552         __in            efx_nic_t *enp)
1553 {
1554         efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1555         uint32_t min_vi_count, max_vi_count;
1556         uint32_t vi_count, vi_base;
1557         uint32_t i;
1558         uint32_t retry;
1559         uint32_t delay_us;
1560         efx_rc_t rc;
1561
1562         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_HUNTINGTON);
1563
1564         /* Enable reporting of some events (e.g. link change) */
1565         if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
1566                 goto fail1;
1567
1568         /* Allocate (optional) on-chip PIO buffers */
1569         hunt_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count);
1570
1571         /*
1572          * For best performance, PIO writes should use a write-combined
1573          * (WC) memory mapping. Using a separate WC mapping for the PIO
1574          * aperture of each VI would be a burden to drivers (and not
1575          * possible if the host page size is >4Kbyte).
1576          *
1577          * To avoid this we use a single uncached (UC) mapping for VI
1578          * register access, and a single WC mapping for extra VIs used
1579          * for PIO writes.
1580          *
1581          * Each piobuf must be linked to a VI in the WC mapping, and to
1582          * each VI that is using a sub-allocated block from the piobuf.
1583          */
1584         min_vi_count = edcp->edc_min_vi_count;
1585         max_vi_count =
1586             edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count;
1587
1588         /* Ensure that the previously attached driver's VIs are freed */
1589         if ((rc = efx_mcdi_free_vis(enp)) != 0)
1590                 goto fail2;
1591
1592         /*
1593          * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this
1594          * fails then retrying the request for fewer VI resources may succeed.
1595          */
1596         vi_count = 0;
1597         if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count,
1598                     &vi_base, &vi_count)) != 0)
1599                 goto fail3;
1600
1601         EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count);
1602
1603         if (vi_count < min_vi_count) {
1604                 rc = ENOMEM;
1605                 goto fail4;
1606         }
1607
1608         enp->en_arch.ef10.ena_vi_base = vi_base;
1609         enp->en_arch.ef10.ena_vi_count = vi_count;
1610
1611         if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) {
1612                 /* Not enough extra VIs to map piobufs */
1613                 hunt_nic_free_piobufs(enp);
1614         }
1615
1616         enp->en_arch.ef10.ena_pio_write_vi_base =
1617             vi_count - enp->en_arch.ef10.ena_piobuf_count;
1618
1619         /* Save UC memory mapping details */
1620         enp->en_arch.ef10.ena_uc_mem_map_offset = 0;
1621         if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1622                 enp->en_arch.ef10.ena_uc_mem_map_size =
1623                     (ER_DZ_TX_PIOBUF_STEP *
1624                     enp->en_arch.ef10.ena_pio_write_vi_base);
1625         } else {
1626                 enp->en_arch.ef10.ena_uc_mem_map_size =
1627                     (ER_DZ_TX_PIOBUF_STEP *
1628                     enp->en_arch.ef10.ena_vi_count);
1629         }
1630
1631         /* Save WC memory mapping details */
1632         enp->en_arch.ef10.ena_wc_mem_map_offset =
1633             enp->en_arch.ef10.ena_uc_mem_map_offset +
1634             enp->en_arch.ef10.ena_uc_mem_map_size;
1635
1636         enp->en_arch.ef10.ena_wc_mem_map_size =
1637             (ER_DZ_TX_PIOBUF_STEP *
1638             enp->en_arch.ef10.ena_piobuf_count);
1639
1640         /* Link piobufs to extra VIs in WC mapping */
1641         if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1642                 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1643                         rc = efx_mcdi_link_piobuf(enp,
1644                             enp->en_arch.ef10.ena_pio_write_vi_base + i,
1645                             enp->en_arch.ef10.ena_piobuf_handle[i]);
1646                         if (rc != 0)
1647                                 break;
1648                 }
1649         }
1650
1651         /*
1652          * Allocate a vAdaptor attached to our upstream vPort/pPort.
1653          *
1654          * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF
1655          * driver has yet to bring up the EVB port. See bug 56147. In this case,
1656          * retry the request several times after waiting a while. The wait time
1657          * between retries starts small (10ms) and exponentially increases.
1658          * Total wait time is a little over two seconds. Retry logic in the
1659          * client driver may mean this whole loop is repeated if it continues to
1660          * fail.
1661          */
1662         retry = 0;
1663         delay_us = 10000;
1664         while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) {
1665                 if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) ||
1666                     (rc != ENOENT)) {
1667                         /*
1668                          * Do not retry alloc for PF, or for other errors on
1669                          * a VF.
1670                          */
1671                         goto fail5;
1672                 }
1673
1674                 /* VF startup before PF is ready. Retry allocation. */
1675                 if (retry > 5) {
1676                         /* Too many attempts */
1677                         rc = EINVAL;
1678                         goto fail6;
1679                 }
1680                 EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry);
1681                 EFSYS_SLEEP(delay_us);
1682                 retry++;
1683                 if (delay_us < 500000)
1684                         delay_us <<= 2;
1685         }
1686
1687         enp->en_vport_id = EVB_PORT_ID_ASSIGNED;
1688         enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2;
1689
1690         return (0);
1691
1692 fail6:
1693         EFSYS_PROBE(fail6);
1694 fail5:
1695         EFSYS_PROBE(fail5);
1696 fail4:
1697         EFSYS_PROBE(fail4);
1698 fail3:
1699         EFSYS_PROBE(fail3);
1700 fail2:
1701         EFSYS_PROBE(fail2);
1702
1703         hunt_nic_free_piobufs(enp);
1704
1705 fail1:
1706         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1707
1708         return (rc);
1709 }
1710
1711         __checkReturn   efx_rc_t
1712 hunt_nic_get_vi_pool(
1713         __in            efx_nic_t *enp,
1714         __out           uint32_t *vi_countp)
1715 {
1716         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_HUNTINGTON);
1717
1718         /*
1719          * Report VIs that the client driver can use.
1720          * Do not include VIs used for PIO buffer writes.
1721          */
1722         *vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base;
1723
1724         return (0);
1725 }
1726
1727         __checkReturn   efx_rc_t
1728 hunt_nic_get_bar_region(
1729         __in            efx_nic_t *enp,
1730         __in            efx_nic_region_t region,
1731         __out           uint32_t *offsetp,
1732         __out           size_t *sizep)
1733 {
1734         efx_rc_t rc;
1735
1736         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_HUNTINGTON);
1737
1738         /*
1739          * TODO: Specify host memory mapping alignment and granularity
1740          * in efx_drv_limits_t so that they can be taken into account
1741          * when allocating extra VIs for PIO writes.
1742          */
1743         switch (region) {
1744         case EFX_REGION_VI:
1745                 /* UC mapped memory BAR region for VI registers */
1746                 *offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset;
1747                 *sizep = enp->en_arch.ef10.ena_uc_mem_map_size;
1748                 break;
1749
1750         case EFX_REGION_PIO_WRITE_VI:
1751                 /* WC mapped memory BAR region for piobuf writes */
1752                 *offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset;
1753                 *sizep = enp->en_arch.ef10.ena_wc_mem_map_size;
1754                 break;
1755
1756         default:
1757                 rc = EINVAL;
1758                 goto fail1;
1759         }
1760
1761         return (0);
1762
1763 fail1:
1764         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1765
1766         return (rc);
1767 }
1768
1769                         void
1770 hunt_nic_fini(
1771         __in            efx_nic_t *enp)
1772 {
1773         uint32_t i;
1774         efx_rc_t rc;
1775
1776         (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id);
1777         enp->en_vport_id = 0;
1778
1779         /* Unlink piobufs from extra VIs in WC mapping */
1780         if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1781                 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1782                         rc = efx_mcdi_unlink_piobuf(enp,
1783                             enp->en_arch.ef10.ena_pio_write_vi_base + i);
1784                         if (rc != 0)
1785                                 break;
1786                 }
1787         }
1788
1789         hunt_nic_free_piobufs(enp);
1790
1791         (void) efx_mcdi_free_vis(enp);
1792         enp->en_arch.ef10.ena_vi_count = 0;
1793 }
1794
1795                         void
1796 hunt_nic_unprobe(
1797         __in            efx_nic_t *enp)
1798 {
1799 #if EFSYS_OPT_MON_STATS
1800         mcdi_mon_cfg_free(enp);
1801 #endif /* EFSYS_OPT_MON_STATS */
1802         (void) efx_mcdi_drv_attach(enp, B_FALSE);
1803 }
1804
1805 #if EFSYS_OPT_DIAG
1806
1807         __checkReturn   efx_rc_t
1808 hunt_nic_register_test(
1809         __in            efx_nic_t *enp)
1810 {
1811         efx_rc_t rc;
1812
1813         /* FIXME */
1814         _NOTE(ARGUNUSED(enp))
1815         if (B_FALSE) {
1816                 rc = ENOTSUP;
1817                 goto fail1;
1818         }
1819         /* FIXME */
1820
1821         return (0);
1822
1823 fail1:
1824         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1825
1826         return (rc);
1827 }
1828
1829 #endif  /* EFSYS_OPT_DIAG */
1830
1831
1832
1833 #endif  /* EFSYS_OPT_HUNTINGTON */