]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/dev/sfxge/common/ef10_nic.c
MFC r310747
[FreeBSD/stable/10.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 #undef CAP_FLAG
1109 #undef CAP_FLAG2
1110
1111         return (0);
1112
1113 fail2:
1114         EFSYS_PROBE(fail2);
1115 fail1:
1116         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1117
1118         return (rc);
1119 }
1120
1121
1122 #define EF10_LEGACY_PF_PRIVILEGE_MASK                                   \
1123         (MC_CMD_PRIVILEGE_MASK_IN_GRP_ADMIN                     |       \
1124         MC_CMD_PRIVILEGE_MASK_IN_GRP_LINK                       |       \
1125         MC_CMD_PRIVILEGE_MASK_IN_GRP_ONLOAD                     |       \
1126         MC_CMD_PRIVILEGE_MASK_IN_GRP_PTP                        |       \
1127         MC_CMD_PRIVILEGE_MASK_IN_GRP_INSECURE_FILTERS           |       \
1128         MC_CMD_PRIVILEGE_MASK_IN_GRP_MAC_SPOOFING               |       \
1129         MC_CMD_PRIVILEGE_MASK_IN_GRP_UNICAST                    |       \
1130         MC_CMD_PRIVILEGE_MASK_IN_GRP_MULTICAST                  |       \
1131         MC_CMD_PRIVILEGE_MASK_IN_GRP_BROADCAST                  |       \
1132         MC_CMD_PRIVILEGE_MASK_IN_GRP_ALL_MULTICAST              |       \
1133         MC_CMD_PRIVILEGE_MASK_IN_GRP_PROMISCUOUS)
1134
1135 #define EF10_LEGACY_VF_PRIVILEGE_MASK   0
1136
1137
1138         __checkReturn           efx_rc_t
1139 ef10_get_privilege_mask(
1140         __in                    efx_nic_t *enp,
1141         __out                   uint32_t *maskp)
1142 {
1143         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1144         uint32_t mask;
1145         efx_rc_t rc;
1146
1147         if ((rc = efx_mcdi_privilege_mask(enp, encp->enc_pf, encp->enc_vf,
1148                                             &mask)) != 0) {
1149                 if (rc != ENOTSUP)
1150                         goto fail1;
1151
1152                 /* Fallback for old firmware without privilege mask support */
1153                 if (EFX_PCI_FUNCTION_IS_PF(encp)) {
1154                         /* Assume PF has admin privilege */
1155                         mask = EF10_LEGACY_PF_PRIVILEGE_MASK;
1156                 } else {
1157                         /* VF is always unprivileged by default */
1158                         mask = EF10_LEGACY_VF_PRIVILEGE_MASK;
1159                 }
1160         }
1161
1162         *maskp = mask;
1163
1164         return (0);
1165
1166 fail1:
1167         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1168
1169         return (rc);
1170 }
1171
1172
1173 /*
1174  * Table of mapping schemes from port number to the number of the external
1175  * connector on the board. The external numbering does not distinguish
1176  * off-board separated outputs such as from multi-headed cables.
1177  *
1178  * The count of adjacent port numbers that map to each external port
1179  * and the offset in the numbering, is determined by the chip family and
1180  * current port mode.
1181  *
1182  * For the Huntington family, the current port mode cannot be discovered,
1183  * so the mapping used is instead the last match in the table to the full
1184  * set of port modes to which the NIC can be configured. Therefore the
1185  * ordering of entries in the the mapping table is significant.
1186  */
1187 static struct {
1188         efx_family_t    family;
1189         uint32_t        modes_mask;
1190         int32_t         count;
1191         int32_t         offset;
1192 }       __ef10_external_port_mappings[] = {
1193         /* Supported modes with 1 output per external port */
1194         {
1195                 EFX_FAMILY_HUNTINGTON,
1196                 (1 << TLV_PORT_MODE_10G) |
1197                 (1 << TLV_PORT_MODE_10G_10G) |
1198                 (1 << TLV_PORT_MODE_10G_10G_10G_10G),
1199                 1,
1200                 1
1201         },
1202         {
1203                 EFX_FAMILY_MEDFORD,
1204                 (1 << TLV_PORT_MODE_10G) |
1205                 (1 << TLV_PORT_MODE_10G_10G),
1206                 1,
1207                 1
1208         },
1209         /* Supported modes with 2 outputs per external port */
1210         {
1211                 EFX_FAMILY_HUNTINGTON,
1212                 (1 << TLV_PORT_MODE_40G) |
1213                 (1 << TLV_PORT_MODE_40G_40G) |
1214                 (1 << TLV_PORT_MODE_40G_10G_10G) |
1215                 (1 << TLV_PORT_MODE_10G_10G_40G),
1216                 2,
1217                 1
1218         },
1219         {
1220                 EFX_FAMILY_MEDFORD,
1221                 (1 << TLV_PORT_MODE_40G) |
1222                 (1 << TLV_PORT_MODE_40G_40G) |
1223                 (1 << TLV_PORT_MODE_40G_10G_10G) |
1224                 (1 << TLV_PORT_MODE_10G_10G_40G) |
1225                 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2),
1226                 2,
1227                 1
1228         },
1229         /* Supported modes with 4 outputs per external port */
1230         {
1231                 EFX_FAMILY_MEDFORD,
1232                 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q) |
1233                 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q1),
1234                 4,
1235                 1,
1236         },
1237         {
1238                 EFX_FAMILY_MEDFORD,
1239                 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q2),
1240                 4,
1241                 2
1242         },
1243 };
1244
1245         __checkReturn   efx_rc_t
1246 ef10_external_port_mapping(
1247         __in            efx_nic_t *enp,
1248         __in            uint32_t port,
1249         __out           uint8_t *external_portp)
1250 {
1251         efx_rc_t rc;
1252         int i;
1253         uint32_t port_modes;
1254         uint32_t matches;
1255         uint32_t current;
1256         int32_t count = 1; /* Default 1-1 mapping */
1257         int32_t offset = 1; /* Default starting external port number */
1258
1259         if ((rc = efx_mcdi_get_port_modes(enp, &port_modes, &current)) != 0) {
1260                 /*
1261                  * No current port mode information
1262                  * - infer mapping from available modes
1263                  */
1264                 if ((rc = efx_mcdi_get_port_modes(enp,
1265                             &port_modes, NULL)) != 0) {
1266                         /*
1267                          * No port mode information available
1268                          * - use default mapping
1269                          */
1270                         goto out;
1271                 }
1272         } else {
1273                 /* Only need to scan the current mode */
1274                 port_modes = 1 << current;
1275         }
1276
1277         /*
1278          * Infer the internal port -> external port mapping from
1279          * the possible port modes for this NIC.
1280          */
1281         for (i = 0; i < EFX_ARRAY_SIZE(__ef10_external_port_mappings); ++i) {
1282                 if (__ef10_external_port_mappings[i].family !=
1283                     enp->en_family)
1284                         continue;
1285                 matches = (__ef10_external_port_mappings[i].modes_mask &
1286                     port_modes);
1287                 if (matches != 0) {
1288                         count = __ef10_external_port_mappings[i].count;
1289                         offset = __ef10_external_port_mappings[i].offset;
1290                         port_modes &= ~matches;
1291                 }
1292         }
1293
1294         if (port_modes != 0) {
1295                 /* Some advertised modes are not supported */
1296                 rc = ENOTSUP;
1297                 goto fail1;
1298         }
1299
1300 out:
1301         /*
1302          * Scale as required by last matched mode and then convert to
1303          * correctly offset numbering
1304          */
1305         *external_portp = (uint8_t)((port / count) + offset);
1306         return (0);
1307
1308 fail1:
1309         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1310
1311         return (rc);
1312 }
1313
1314
1315         __checkReturn   efx_rc_t
1316 ef10_nic_probe(
1317         __in            efx_nic_t *enp)
1318 {
1319         const efx_nic_ops_t *enop = enp->en_enop;
1320         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1321         efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1322         efx_rc_t rc;
1323
1324         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1325                     enp->en_family == EFX_FAMILY_MEDFORD);
1326
1327         /* Read and clear any assertion state */
1328         if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1329                 goto fail1;
1330
1331         /* Exit the assertion handler */
1332         if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1333                 if (rc != EACCES)
1334                         goto fail2;
1335
1336         if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
1337                 goto fail3;
1338
1339         if ((rc = enop->eno_board_cfg(enp)) != 0)
1340                 if (rc != EACCES)
1341                         goto fail4;
1342
1343         /*
1344          * Set default driver config limits (based on board config).
1345          *
1346          * FIXME: For now allocate a fixed number of VIs which is likely to be
1347          * sufficient and small enough to allow multiple functions on the same
1348          * port.
1349          */
1350         edcp->edc_min_vi_count = edcp->edc_max_vi_count =
1351             MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit));
1352
1353         /* The client driver must configure and enable PIO buffer support */
1354         edcp->edc_max_piobuf_count = 0;
1355         edcp->edc_pio_alloc_size = 0;
1356
1357 #if EFSYS_OPT_MAC_STATS
1358         /* Wipe the MAC statistics */
1359         if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
1360                 goto fail5;
1361 #endif
1362
1363 #if EFSYS_OPT_LOOPBACK
1364         if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
1365                 goto fail6;
1366 #endif
1367
1368 #if EFSYS_OPT_MON_STATS
1369         if ((rc = mcdi_mon_cfg_build(enp)) != 0) {
1370                 /* Unprivileged functions do not have access to sensors */
1371                 if (rc != EACCES)
1372                         goto fail7;
1373         }
1374 #endif
1375
1376         encp->enc_features = enp->en_features;
1377
1378         return (0);
1379
1380 #if EFSYS_OPT_MON_STATS
1381 fail7:
1382         EFSYS_PROBE(fail7);
1383 #endif
1384 #if EFSYS_OPT_LOOPBACK
1385 fail6:
1386         EFSYS_PROBE(fail6);
1387 #endif
1388 #if EFSYS_OPT_MAC_STATS
1389 fail5:
1390         EFSYS_PROBE(fail5);
1391 #endif
1392 fail4:
1393         EFSYS_PROBE(fail4);
1394 fail3:
1395         EFSYS_PROBE(fail3);
1396 fail2:
1397         EFSYS_PROBE(fail2);
1398 fail1:
1399         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1400
1401         return (rc);
1402 }
1403
1404         __checkReturn   efx_rc_t
1405 ef10_nic_set_drv_limits(
1406         __inout         efx_nic_t *enp,
1407         __in            efx_drv_limits_t *edlp)
1408 {
1409         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1410         efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1411         uint32_t min_evq_count, max_evq_count;
1412         uint32_t min_rxq_count, max_rxq_count;
1413         uint32_t min_txq_count, max_txq_count;
1414         efx_rc_t rc;
1415
1416         if (edlp == NULL) {
1417                 rc = EINVAL;
1418                 goto fail1;
1419         }
1420
1421         /* Get minimum required and maximum usable VI limits */
1422         min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit);
1423         min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit);
1424         min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit);
1425
1426         edcp->edc_min_vi_count =
1427             MAX(min_evq_count, MAX(min_rxq_count, min_txq_count));
1428
1429         max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit);
1430         max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit);
1431         max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit);
1432
1433         edcp->edc_max_vi_count =
1434             MAX(max_evq_count, MAX(max_rxq_count, max_txq_count));
1435
1436         /*
1437          * Check limits for sub-allocated piobuf blocks.
1438          * PIO is optional, so don't fail if the limits are incorrect.
1439          */
1440         if ((encp->enc_piobuf_size == 0) ||
1441             (encp->enc_piobuf_limit == 0) ||
1442             (edlp->edl_min_pio_alloc_size == 0) ||
1443             (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) {
1444                 /* Disable PIO */
1445                 edcp->edc_max_piobuf_count = 0;
1446                 edcp->edc_pio_alloc_size = 0;
1447         } else {
1448                 uint32_t blk_size, blk_count, blks_per_piobuf;
1449
1450                 blk_size =
1451                     MAX(edlp->edl_min_pio_alloc_size,
1452                             encp->enc_piobuf_min_alloc_size);
1453
1454                 blks_per_piobuf = encp->enc_piobuf_size / blk_size;
1455                 EFSYS_ASSERT3U(blks_per_piobuf, <=, 32);
1456
1457                 blk_count = (encp->enc_piobuf_limit * blks_per_piobuf);
1458
1459                 /* A zero max pio alloc count means unlimited */
1460                 if ((edlp->edl_max_pio_alloc_count > 0) &&
1461                     (edlp->edl_max_pio_alloc_count < blk_count)) {
1462                         blk_count = edlp->edl_max_pio_alloc_count;
1463                 }
1464
1465                 edcp->edc_pio_alloc_size = blk_size;
1466                 edcp->edc_max_piobuf_count =
1467                     (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf;
1468         }
1469
1470         return (0);
1471
1472 fail1:
1473         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1474
1475         return (rc);
1476 }
1477
1478
1479         __checkReturn   efx_rc_t
1480 ef10_nic_reset(
1481         __in            efx_nic_t *enp)
1482 {
1483         efx_mcdi_req_t req;
1484         uint8_t payload[MAX(MC_CMD_ENTITY_RESET_IN_LEN,
1485                             MC_CMD_ENTITY_RESET_OUT_LEN)];
1486         efx_rc_t rc;
1487
1488         /* ef10_nic_reset() is called to recover from BADASSERT failures. */
1489         if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1490                 goto fail1;
1491         if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1492                 goto fail2;
1493
1494         (void) memset(payload, 0, sizeof (payload));
1495         req.emr_cmd = MC_CMD_ENTITY_RESET;
1496         req.emr_in_buf = payload;
1497         req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN;
1498         req.emr_out_buf = payload;
1499         req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN;
1500
1501         MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG,
1502             ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1);
1503
1504         efx_mcdi_execute(enp, &req);
1505
1506         if (req.emr_rc != 0) {
1507                 rc = req.emr_rc;
1508                 goto fail3;
1509         }
1510
1511         /* Clear RX/TX DMA queue errors */
1512         enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR);
1513
1514         return (0);
1515
1516 fail3:
1517         EFSYS_PROBE(fail3);
1518 fail2:
1519         EFSYS_PROBE(fail2);
1520 fail1:
1521         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1522
1523         return (rc);
1524 }
1525
1526         __checkReturn   efx_rc_t
1527 ef10_nic_init(
1528         __in            efx_nic_t *enp)
1529 {
1530         efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1531         uint32_t min_vi_count, max_vi_count;
1532         uint32_t vi_count, vi_base, vi_shift;
1533         uint32_t i;
1534         uint32_t retry;
1535         uint32_t delay_us;
1536         efx_rc_t rc;
1537
1538         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1539                     enp->en_family == EFX_FAMILY_MEDFORD);
1540
1541         /* Enable reporting of some events (e.g. link change) */
1542         if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
1543                 goto fail1;
1544
1545         /* Allocate (optional) on-chip PIO buffers */
1546         ef10_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count);
1547
1548         /*
1549          * For best performance, PIO writes should use a write-combined
1550          * (WC) memory mapping. Using a separate WC mapping for the PIO
1551          * aperture of each VI would be a burden to drivers (and not
1552          * possible if the host page size is >4Kbyte).
1553          *
1554          * To avoid this we use a single uncached (UC) mapping for VI
1555          * register access, and a single WC mapping for extra VIs used
1556          * for PIO writes.
1557          *
1558          * Each piobuf must be linked to a VI in the WC mapping, and to
1559          * each VI that is using a sub-allocated block from the piobuf.
1560          */
1561         min_vi_count = edcp->edc_min_vi_count;
1562         max_vi_count =
1563             edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count;
1564
1565         /* Ensure that the previously attached driver's VIs are freed */
1566         if ((rc = efx_mcdi_free_vis(enp)) != 0)
1567                 goto fail2;
1568
1569         /*
1570          * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this
1571          * fails then retrying the request for fewer VI resources may succeed.
1572          */
1573         vi_count = 0;
1574         if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count,
1575                     &vi_base, &vi_count, &vi_shift)) != 0)
1576                 goto fail3;
1577
1578         EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count);
1579
1580         if (vi_count < min_vi_count) {
1581                 rc = ENOMEM;
1582                 goto fail4;
1583         }
1584
1585         enp->en_arch.ef10.ena_vi_base = vi_base;
1586         enp->en_arch.ef10.ena_vi_count = vi_count;
1587         enp->en_arch.ef10.ena_vi_shift = vi_shift;
1588
1589         if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) {
1590                 /* Not enough extra VIs to map piobufs */
1591                 ef10_nic_free_piobufs(enp);
1592         }
1593
1594         enp->en_arch.ef10.ena_pio_write_vi_base =
1595             vi_count - enp->en_arch.ef10.ena_piobuf_count;
1596
1597         /* Save UC memory mapping details */
1598         enp->en_arch.ef10.ena_uc_mem_map_offset = 0;
1599         if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1600                 enp->en_arch.ef10.ena_uc_mem_map_size =
1601                     (ER_DZ_TX_PIOBUF_STEP *
1602                     enp->en_arch.ef10.ena_pio_write_vi_base);
1603         } else {
1604                 enp->en_arch.ef10.ena_uc_mem_map_size =
1605                     (ER_DZ_TX_PIOBUF_STEP *
1606                     enp->en_arch.ef10.ena_vi_count);
1607         }
1608
1609         /* Save WC memory mapping details */
1610         enp->en_arch.ef10.ena_wc_mem_map_offset =
1611             enp->en_arch.ef10.ena_uc_mem_map_offset +
1612             enp->en_arch.ef10.ena_uc_mem_map_size;
1613
1614         enp->en_arch.ef10.ena_wc_mem_map_size =
1615             (ER_DZ_TX_PIOBUF_STEP *
1616             enp->en_arch.ef10.ena_piobuf_count);
1617
1618         /* Link piobufs to extra VIs in WC mapping */
1619         if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1620                 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1621                         rc = efx_mcdi_link_piobuf(enp,
1622                             enp->en_arch.ef10.ena_pio_write_vi_base + i,
1623                             enp->en_arch.ef10.ena_piobuf_handle[i]);
1624                         if (rc != 0)
1625                                 break;
1626                 }
1627         }
1628
1629         /*
1630          * Allocate a vAdaptor attached to our upstream vPort/pPort.
1631          *
1632          * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF
1633          * driver has yet to bring up the EVB port. See bug 56147. In this case,
1634          * retry the request several times after waiting a while. The wait time
1635          * between retries starts small (10ms) and exponentially increases.
1636          * Total wait time is a little over two seconds. Retry logic in the
1637          * client driver may mean this whole loop is repeated if it continues to
1638          * fail.
1639          */
1640         retry = 0;
1641         delay_us = 10000;
1642         while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) {
1643                 if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) ||
1644                     (rc != ENOENT)) {
1645                         /*
1646                          * Do not retry alloc for PF, or for other errors on
1647                          * a VF.
1648                          */
1649                         goto fail5;
1650                 }
1651
1652                 /* VF startup before PF is ready. Retry allocation. */
1653                 if (retry > 5) {
1654                         /* Too many attempts */
1655                         rc = EINVAL;
1656                         goto fail6;
1657                 }
1658                 EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry);
1659                 EFSYS_SLEEP(delay_us);
1660                 retry++;
1661                 if (delay_us < 500000)
1662                         delay_us <<= 2;
1663         }
1664
1665         enp->en_vport_id = EVB_PORT_ID_ASSIGNED;
1666         enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2;
1667
1668         return (0);
1669
1670 fail6:
1671         EFSYS_PROBE(fail6);
1672 fail5:
1673         EFSYS_PROBE(fail5);
1674 fail4:
1675         EFSYS_PROBE(fail4);
1676 fail3:
1677         EFSYS_PROBE(fail3);
1678 fail2:
1679         EFSYS_PROBE(fail2);
1680
1681         ef10_nic_free_piobufs(enp);
1682
1683 fail1:
1684         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1685
1686         return (rc);
1687 }
1688
1689         __checkReturn   efx_rc_t
1690 ef10_nic_get_vi_pool(
1691         __in            efx_nic_t *enp,
1692         __out           uint32_t *vi_countp)
1693 {
1694         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1695                     enp->en_family == EFX_FAMILY_MEDFORD);
1696
1697         /*
1698          * Report VIs that the client driver can use.
1699          * Do not include VIs used for PIO buffer writes.
1700          */
1701         *vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base;
1702
1703         return (0);
1704 }
1705
1706         __checkReturn   efx_rc_t
1707 ef10_nic_get_bar_region(
1708         __in            efx_nic_t *enp,
1709         __in            efx_nic_region_t region,
1710         __out           uint32_t *offsetp,
1711         __out           size_t *sizep)
1712 {
1713         efx_rc_t rc;
1714
1715         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1716                     enp->en_family == EFX_FAMILY_MEDFORD);
1717
1718         /*
1719          * TODO: Specify host memory mapping alignment and granularity
1720          * in efx_drv_limits_t so that they can be taken into account
1721          * when allocating extra VIs for PIO writes.
1722          */
1723         switch (region) {
1724         case EFX_REGION_VI:
1725                 /* UC mapped memory BAR region for VI registers */
1726                 *offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset;
1727                 *sizep = enp->en_arch.ef10.ena_uc_mem_map_size;
1728                 break;
1729
1730         case EFX_REGION_PIO_WRITE_VI:
1731                 /* WC mapped memory BAR region for piobuf writes */
1732                 *offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset;
1733                 *sizep = enp->en_arch.ef10.ena_wc_mem_map_size;
1734                 break;
1735
1736         default:
1737                 rc = EINVAL;
1738                 goto fail1;
1739         }
1740
1741         return (0);
1742
1743 fail1:
1744         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1745
1746         return (rc);
1747 }
1748
1749                         void
1750 ef10_nic_fini(
1751         __in            efx_nic_t *enp)
1752 {
1753         uint32_t i;
1754         efx_rc_t rc;
1755
1756         (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id);
1757         enp->en_vport_id = 0;
1758
1759         /* Unlink piobufs from extra VIs in WC mapping */
1760         if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1761                 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1762                         rc = efx_mcdi_unlink_piobuf(enp,
1763                             enp->en_arch.ef10.ena_pio_write_vi_base + i);
1764                         if (rc != 0)
1765                                 break;
1766                 }
1767         }
1768
1769         ef10_nic_free_piobufs(enp);
1770
1771         (void) efx_mcdi_free_vis(enp);
1772         enp->en_arch.ef10.ena_vi_count = 0;
1773 }
1774
1775                         void
1776 ef10_nic_unprobe(
1777         __in            efx_nic_t *enp)
1778 {
1779 #if EFSYS_OPT_MON_STATS
1780         mcdi_mon_cfg_free(enp);
1781 #endif /* EFSYS_OPT_MON_STATS */
1782         (void) efx_mcdi_drv_attach(enp, B_FALSE);
1783 }
1784
1785 #if EFSYS_OPT_DIAG
1786
1787         __checkReturn   efx_rc_t
1788 ef10_nic_register_test(
1789         __in            efx_nic_t *enp)
1790 {
1791         efx_rc_t rc;
1792
1793         /* FIXME */
1794         _NOTE(ARGUNUSED(enp))
1795         _NOTE(CONSTANTCONDITION)
1796         if (B_FALSE) {
1797                 rc = ENOTSUP;
1798                 goto fail1;
1799         }
1800         /* FIXME */
1801
1802         return (0);
1803
1804 fail1:
1805         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1806
1807         return (rc);
1808 }
1809
1810 #endif  /* EFSYS_OPT_DIAG */
1811
1812
1813 #endif  /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */