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