]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/sfxge/common/ef10_nic.c
Update compiler-rt to release_39 branch r288513. Since this contains a
[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 {
502         efx_mcdi_req_t req;
503         uint8_t payload[MAX(MC_CMD_GET_CAPABILITIES_IN_LEN,
504                             MC_CMD_GET_CAPABILITIES_V2_OUT_LEN)];
505         efx_rc_t rc;
506
507         (void) memset(payload, 0, sizeof (payload));
508         req.emr_cmd = MC_CMD_GET_CAPABILITIES;
509         req.emr_in_buf = payload;
510         req.emr_in_length = MC_CMD_GET_CAPABILITIES_IN_LEN;
511         req.emr_out_buf = payload;
512         req.emr_out_length = MC_CMD_GET_CAPABILITIES_V2_OUT_LEN;
513
514         efx_mcdi_execute(enp, &req);
515
516         if (req.emr_rc != 0) {
517                 rc = req.emr_rc;
518                 goto fail1;
519         }
520
521         if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_OUT_LEN) {
522                 rc = EMSGSIZE;
523                 goto fail2;
524         }
525
526         *flagsp = MCDI_OUT_DWORD(req, GET_CAPABILITIES_OUT_FLAGS1);
527
528         if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_V2_OUT_LEN)
529                 *flags2p = 0;
530         else
531                 *flags2p = MCDI_OUT_DWORD(req, GET_CAPABILITIES_V2_OUT_FLAGS2);
532
533         return (0);
534
535 fail2:
536         EFSYS_PROBE(fail2);
537 fail1:
538         EFSYS_PROBE1(fail1, efx_rc_t, rc);
539
540         return (rc);
541 }
542
543
544 static  __checkReturn   efx_rc_t
545 efx_mcdi_alloc_vis(
546         __in            efx_nic_t *enp,
547         __in            uint32_t min_vi_count,
548         __in            uint32_t max_vi_count,
549         __out           uint32_t *vi_basep,
550         __out           uint32_t *vi_countp,
551         __out           uint32_t *vi_shiftp)
552 {
553         efx_mcdi_req_t req;
554         uint8_t payload[MAX(MC_CMD_ALLOC_VIS_IN_LEN,
555                             MC_CMD_ALLOC_VIS_OUT_LEN)];
556         efx_rc_t rc;
557
558         if (vi_countp == NULL) {
559                 rc = EINVAL;
560                 goto fail1;
561         }
562
563         (void) memset(payload, 0, sizeof (payload));
564         req.emr_cmd = MC_CMD_ALLOC_VIS;
565         req.emr_in_buf = payload;
566         req.emr_in_length = MC_CMD_ALLOC_VIS_IN_LEN;
567         req.emr_out_buf = payload;
568         req.emr_out_length = MC_CMD_ALLOC_VIS_OUT_LEN;
569
570         MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MIN_VI_COUNT, min_vi_count);
571         MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MAX_VI_COUNT, max_vi_count);
572
573         efx_mcdi_execute(enp, &req);
574
575         if (req.emr_rc != 0) {
576                 rc = req.emr_rc;
577                 goto fail2;
578         }
579
580         if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_OUT_LEN) {
581                 rc = EMSGSIZE;
582                 goto fail3;
583         }
584
585         *vi_basep = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_BASE);
586         *vi_countp = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_COUNT);
587
588         /* Report VI_SHIFT if available (always zero for Huntington) */
589         if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_EXT_OUT_LEN)
590                 *vi_shiftp = 0;
591         else
592                 *vi_shiftp = MCDI_OUT_DWORD(req, ALLOC_VIS_EXT_OUT_VI_SHIFT);
593
594         return (0);
595
596 fail3:
597         EFSYS_PROBE(fail3);
598 fail2:
599         EFSYS_PROBE(fail2);
600 fail1:
601         EFSYS_PROBE1(fail1, efx_rc_t, rc);
602
603         return (rc);
604 }
605
606
607 static  __checkReturn   efx_rc_t
608 efx_mcdi_free_vis(
609         __in            efx_nic_t *enp)
610 {
611         efx_mcdi_req_t req;
612         efx_rc_t rc;
613
614         EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_IN_LEN == 0);
615         EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_OUT_LEN == 0);
616
617         req.emr_cmd = MC_CMD_FREE_VIS;
618         req.emr_in_buf = NULL;
619         req.emr_in_length = 0;
620         req.emr_out_buf = NULL;
621         req.emr_out_length = 0;
622
623         efx_mcdi_execute_quiet(enp, &req);
624
625         /* Ignore ELREADY (no allocated VIs, so nothing to free) */
626         if ((req.emr_rc != 0) && (req.emr_rc != EALREADY)) {
627                 rc = req.emr_rc;
628                 goto fail1;
629         }
630
631         return (0);
632
633 fail1:
634         EFSYS_PROBE1(fail1, efx_rc_t, rc);
635
636         return (rc);
637 }
638
639
640 static  __checkReturn   efx_rc_t
641 efx_mcdi_alloc_piobuf(
642         __in            efx_nic_t *enp,
643         __out           efx_piobuf_handle_t *handlep)
644 {
645         efx_mcdi_req_t req;
646         uint8_t payload[MAX(MC_CMD_ALLOC_PIOBUF_IN_LEN,
647                             MC_CMD_ALLOC_PIOBUF_OUT_LEN)];
648         efx_rc_t rc;
649
650         if (handlep == NULL) {
651                 rc = EINVAL;
652                 goto fail1;
653         }
654
655         (void) memset(payload, 0, sizeof (payload));
656         req.emr_cmd = MC_CMD_ALLOC_PIOBUF;
657         req.emr_in_buf = payload;
658         req.emr_in_length = MC_CMD_ALLOC_PIOBUF_IN_LEN;
659         req.emr_out_buf = payload;
660         req.emr_out_length = MC_CMD_ALLOC_PIOBUF_OUT_LEN;
661
662         efx_mcdi_execute_quiet(enp, &req);
663
664         if (req.emr_rc != 0) {
665                 rc = req.emr_rc;
666                 goto fail2;
667         }
668
669         if (req.emr_out_length_used < MC_CMD_ALLOC_PIOBUF_OUT_LEN) {
670                 rc = EMSGSIZE;
671                 goto fail3;
672         }
673
674         *handlep = MCDI_OUT_DWORD(req, ALLOC_PIOBUF_OUT_PIOBUF_HANDLE);
675
676         return (0);
677
678 fail3:
679         EFSYS_PROBE(fail3);
680 fail2:
681         EFSYS_PROBE(fail2);
682 fail1:
683         EFSYS_PROBE1(fail1, efx_rc_t, rc);
684
685         return (rc);
686 }
687
688 static  __checkReturn   efx_rc_t
689 efx_mcdi_free_piobuf(
690         __in            efx_nic_t *enp,
691         __in            efx_piobuf_handle_t handle)
692 {
693         efx_mcdi_req_t req;
694         uint8_t payload[MAX(MC_CMD_FREE_PIOBUF_IN_LEN,
695                             MC_CMD_FREE_PIOBUF_OUT_LEN)];
696         efx_rc_t rc;
697
698         (void) memset(payload, 0, sizeof (payload));
699         req.emr_cmd = MC_CMD_FREE_PIOBUF;
700         req.emr_in_buf = payload;
701         req.emr_in_length = MC_CMD_FREE_PIOBUF_IN_LEN;
702         req.emr_out_buf = payload;
703         req.emr_out_length = MC_CMD_FREE_PIOBUF_OUT_LEN;
704
705         MCDI_IN_SET_DWORD(req, FREE_PIOBUF_IN_PIOBUF_HANDLE, handle);
706
707         efx_mcdi_execute_quiet(enp, &req);
708
709         if (req.emr_rc != 0) {
710                 rc = req.emr_rc;
711                 goto fail1;
712         }
713
714         return (0);
715
716 fail1:
717         EFSYS_PROBE1(fail1, efx_rc_t, rc);
718
719         return (rc);
720 }
721
722 static  __checkReturn   efx_rc_t
723 efx_mcdi_link_piobuf(
724         __in            efx_nic_t *enp,
725         __in            uint32_t vi_index,
726         __in            efx_piobuf_handle_t handle)
727 {
728         efx_mcdi_req_t req;
729         uint8_t payload[MAX(MC_CMD_LINK_PIOBUF_IN_LEN,
730                             MC_CMD_LINK_PIOBUF_OUT_LEN)];
731         efx_rc_t rc;
732
733         (void) memset(payload, 0, sizeof (payload));
734         req.emr_cmd = MC_CMD_LINK_PIOBUF;
735         req.emr_in_buf = payload;
736         req.emr_in_length = MC_CMD_LINK_PIOBUF_IN_LEN;
737         req.emr_out_buf = payload;
738         req.emr_out_length = MC_CMD_LINK_PIOBUF_OUT_LEN;
739
740         MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_PIOBUF_HANDLE, handle);
741         MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_TXQ_INSTANCE, vi_index);
742
743         efx_mcdi_execute(enp, &req);
744
745         if (req.emr_rc != 0) {
746                 rc = req.emr_rc;
747                 goto fail1;
748         }
749
750         return (0);
751
752 fail1:
753         EFSYS_PROBE1(fail1, efx_rc_t, rc);
754
755         return (rc);
756 }
757
758 static  __checkReturn   efx_rc_t
759 efx_mcdi_unlink_piobuf(
760         __in            efx_nic_t *enp,
761         __in            uint32_t vi_index)
762 {
763         efx_mcdi_req_t req;
764         uint8_t payload[MAX(MC_CMD_UNLINK_PIOBUF_IN_LEN,
765                             MC_CMD_UNLINK_PIOBUF_OUT_LEN)];
766         efx_rc_t rc;
767
768         (void) memset(payload, 0, sizeof (payload));
769         req.emr_cmd = MC_CMD_UNLINK_PIOBUF;
770         req.emr_in_buf = payload;
771         req.emr_in_length = MC_CMD_UNLINK_PIOBUF_IN_LEN;
772         req.emr_out_buf = payload;
773         req.emr_out_length = MC_CMD_UNLINK_PIOBUF_OUT_LEN;
774
775         MCDI_IN_SET_DWORD(req, UNLINK_PIOBUF_IN_TXQ_INSTANCE, vi_index);
776
777         efx_mcdi_execute_quiet(enp, &req);
778
779         if (req.emr_rc != 0) {
780                 rc = req.emr_rc;
781                 goto fail1;
782         }
783
784         return (0);
785
786 fail1:
787         EFSYS_PROBE1(fail1, efx_rc_t, rc);
788
789         return (rc);
790 }
791
792 static                  void
793 ef10_nic_alloc_piobufs(
794         __in            efx_nic_t *enp,
795         __in            uint32_t max_piobuf_count)
796 {
797         efx_piobuf_handle_t *handlep;
798         unsigned int i;
799
800         EFSYS_ASSERT3U(max_piobuf_count, <=,
801             EFX_ARRAY_SIZE(enp->en_arch.ef10.ena_piobuf_handle));
802
803         enp->en_arch.ef10.ena_piobuf_count = 0;
804
805         for (i = 0; i < max_piobuf_count; i++) {
806                 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
807
808                 if (efx_mcdi_alloc_piobuf(enp, handlep) != 0)
809                         goto fail1;
810
811                 enp->en_arch.ef10.ena_pio_alloc_map[i] = 0;
812                 enp->en_arch.ef10.ena_piobuf_count++;
813         }
814
815         return;
816
817 fail1:
818         for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
819                 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
820
821                 efx_mcdi_free_piobuf(enp, *handlep);
822                 *handlep = EFX_PIOBUF_HANDLE_INVALID;
823         }
824         enp->en_arch.ef10.ena_piobuf_count = 0;
825 }
826
827
828 static                  void
829 ef10_nic_free_piobufs(
830         __in            efx_nic_t *enp)
831 {
832         efx_piobuf_handle_t *handlep;
833         unsigned int i;
834
835         for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
836                 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
837
838                 efx_mcdi_free_piobuf(enp, *handlep);
839                 *handlep = EFX_PIOBUF_HANDLE_INVALID;
840         }
841         enp->en_arch.ef10.ena_piobuf_count = 0;
842 }
843
844 /* Sub-allocate a block from a piobuf */
845         __checkReturn   efx_rc_t
846 ef10_nic_pio_alloc(
847         __inout         efx_nic_t *enp,
848         __out           uint32_t *bufnump,
849         __out           efx_piobuf_handle_t *handlep,
850         __out           uint32_t *blknump,
851         __out           uint32_t *offsetp,
852         __out           size_t *sizep)
853 {
854         efx_nic_cfg_t *encp = &enp->en_nic_cfg;
855         efx_drv_cfg_t *edcp = &enp->en_drv_cfg;
856         uint32_t blk_per_buf;
857         uint32_t buf, blk;
858         efx_rc_t rc;
859
860         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
861                     enp->en_family == EFX_FAMILY_MEDFORD);
862         EFSYS_ASSERT(bufnump);
863         EFSYS_ASSERT(handlep);
864         EFSYS_ASSERT(blknump);
865         EFSYS_ASSERT(offsetp);
866         EFSYS_ASSERT(sizep);
867
868         if ((edcp->edc_pio_alloc_size == 0) ||
869             (enp->en_arch.ef10.ena_piobuf_count == 0)) {
870                 rc = ENOMEM;
871                 goto fail1;
872         }
873         blk_per_buf = encp->enc_piobuf_size / edcp->edc_pio_alloc_size;
874
875         for (buf = 0; buf < enp->en_arch.ef10.ena_piobuf_count; buf++) {
876                 uint32_t *map = &enp->en_arch.ef10.ena_pio_alloc_map[buf];
877
878                 if (~(*map) == 0)
879                         continue;
880
881                 EFSYS_ASSERT3U(blk_per_buf, <=, (8 * sizeof (*map)));
882                 for (blk = 0; blk < blk_per_buf; blk++) {
883                         if ((*map & (1u << blk)) == 0) {
884                                 *map |= (1u << blk);
885                                 goto done;
886                         }
887                 }
888         }
889         rc = ENOMEM;
890         goto fail2;
891
892 done:
893         *handlep = enp->en_arch.ef10.ena_piobuf_handle[buf];
894         *bufnump = buf;
895         *blknump = blk;
896         *sizep = edcp->edc_pio_alloc_size;
897         *offsetp = blk * (*sizep);
898
899         return (0);
900
901 fail2:
902         EFSYS_PROBE(fail2);
903 fail1:
904         EFSYS_PROBE1(fail1, efx_rc_t, rc);
905
906         return (rc);
907 }
908
909 /* Free a piobuf sub-allocated block */
910         __checkReturn   efx_rc_t
911 ef10_nic_pio_free(
912         __inout         efx_nic_t *enp,
913         __in            uint32_t bufnum,
914         __in            uint32_t blknum)
915 {
916         uint32_t *map;
917         efx_rc_t rc;
918
919         if ((bufnum >= enp->en_arch.ef10.ena_piobuf_count) ||
920             (blknum >= (8 * sizeof (*map)))) {
921                 rc = EINVAL;
922                 goto fail1;
923         }
924
925         map = &enp->en_arch.ef10.ena_pio_alloc_map[bufnum];
926         if ((*map & (1u << blknum)) == 0) {
927                 rc = ENOENT;
928                 goto fail2;
929         }
930         *map &= ~(1u << blknum);
931
932         return (0);
933
934 fail2:
935         EFSYS_PROBE(fail2);
936 fail1:
937         EFSYS_PROBE1(fail1, efx_rc_t, rc);
938
939         return (rc);
940 }
941
942         __checkReturn   efx_rc_t
943 ef10_nic_pio_link(
944         __inout         efx_nic_t *enp,
945         __in            uint32_t vi_index,
946         __in            efx_piobuf_handle_t handle)
947 {
948         return (efx_mcdi_link_piobuf(enp, vi_index, handle));
949 }
950
951         __checkReturn   efx_rc_t
952 ef10_nic_pio_unlink(
953         __inout         efx_nic_t *enp,
954         __in            uint32_t vi_index)
955 {
956         return (efx_mcdi_unlink_piobuf(enp, vi_index));
957 }
958
959         __checkReturn   efx_rc_t
960 ef10_get_datapath_caps(
961         __in            efx_nic_t *enp)
962 {
963         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
964         uint32_t flags;
965         uint32_t flags2;
966         efx_rc_t rc;
967
968         if ((rc = efx_mcdi_get_capabilities(enp, &flags, &flags2)) != 0)
969                 goto fail1;
970
971 #define CAP_FLAG(flags1, field)         \
972         ((flags1) & (1 << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## field ## _LBN)))
973
974 #define CAP_FLAG2(flags2, field)        \
975         ((flags2) & (1 << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## field ## _LBN)))
976
977         /*
978          * Huntington RXDP firmware inserts a 0 or 14 byte prefix.
979          * We only support the 14 byte prefix here.
980          */
981         if (CAP_FLAG(flags, RX_PREFIX_LEN_14) == 0) {
982                 rc = ENOTSUP;
983                 goto fail2;
984         }
985         encp->enc_rx_prefix_size = 14;
986
987         /* Check if the firmware supports TSO */
988         encp->enc_fw_assisted_tso_enabled =
989             CAP_FLAG(flags, TX_TSO) ? B_TRUE : B_FALSE;
990
991         /* Check if the firmware supports FATSOv2 */
992         encp->enc_fw_assisted_tso_v2_enabled =
993             CAP_FLAG2(flags2, TX_TSO_V2) ? B_TRUE : B_FALSE;
994
995         /* Check if the firmware has vadapter/vport/vswitch support */
996         encp->enc_datapath_cap_evb =
997             CAP_FLAG(flags, EVB) ? B_TRUE : B_FALSE;
998
999         /* Check if the firmware supports VLAN insertion */
1000         encp->enc_hw_tx_insert_vlan_enabled =
1001             CAP_FLAG(flags, TX_VLAN_INSERTION) ? B_TRUE : B_FALSE;
1002
1003         /* Check if the firmware supports RX event batching */
1004         encp->enc_rx_batching_enabled =
1005             CAP_FLAG(flags, RX_BATCHING) ? B_TRUE : B_FALSE;
1006
1007         /*
1008          * Even if batching isn't reported as supported, we may still get
1009          * batched events.
1010          */
1011         encp->enc_rx_batch_max = 16;
1012
1013         /* Check if the firmware supports disabling scatter on RXQs */
1014         encp->enc_rx_disable_scatter_supported =
1015             CAP_FLAG(flags, RX_DISABLE_SCATTER) ? B_TRUE : B_FALSE;
1016
1017         /* Check if the firmware supports set mac with running filters */
1018         encp->enc_allow_set_mac_with_installed_filters =
1019             CAP_FLAG(flags, VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED) ?
1020             B_TRUE : B_FALSE;
1021
1022         /*
1023          * Check if firmware supports the extended MC_CMD_SET_MAC, which allows
1024          * specifying which parameters to configure.
1025          */
1026         encp->enc_enhanced_set_mac_supported =
1027                 CAP_FLAG(flags, SET_MAC_ENHANCED) ? B_TRUE : B_FALSE;
1028
1029         /*
1030          * Check if firmware supports version 2 of MC_CMD_INIT_EVQ, which allows
1031          * us to let the firmware choose the settings to use on an EVQ.
1032          */
1033         encp->enc_init_evq_v2_supported =
1034                 CAP_FLAG2(flags2, INIT_EVQ_V2) ? B_TRUE : B_FALSE;
1035
1036 #undef CAP_FLAG
1037 #undef CAP_FLAG2
1038
1039         return (0);
1040
1041 fail2:
1042         EFSYS_PROBE(fail2);
1043 fail1:
1044         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1045
1046         return (rc);
1047 }
1048
1049
1050 #define EF10_LEGACY_PF_PRIVILEGE_MASK                                   \
1051         (MC_CMD_PRIVILEGE_MASK_IN_GRP_ADMIN                     |       \
1052         MC_CMD_PRIVILEGE_MASK_IN_GRP_LINK                       |       \
1053         MC_CMD_PRIVILEGE_MASK_IN_GRP_ONLOAD                     |       \
1054         MC_CMD_PRIVILEGE_MASK_IN_GRP_PTP                        |       \
1055         MC_CMD_PRIVILEGE_MASK_IN_GRP_INSECURE_FILTERS           |       \
1056         MC_CMD_PRIVILEGE_MASK_IN_GRP_MAC_SPOOFING               |       \
1057         MC_CMD_PRIVILEGE_MASK_IN_GRP_UNICAST                    |       \
1058         MC_CMD_PRIVILEGE_MASK_IN_GRP_MULTICAST                  |       \
1059         MC_CMD_PRIVILEGE_MASK_IN_GRP_BROADCAST                  |       \
1060         MC_CMD_PRIVILEGE_MASK_IN_GRP_ALL_MULTICAST              |       \
1061         MC_CMD_PRIVILEGE_MASK_IN_GRP_PROMISCUOUS)
1062
1063 #define EF10_LEGACY_VF_PRIVILEGE_MASK   0
1064
1065
1066         __checkReturn           efx_rc_t
1067 ef10_get_privilege_mask(
1068         __in                    efx_nic_t *enp,
1069         __out                   uint32_t *maskp)
1070 {
1071         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1072         uint32_t mask;
1073         efx_rc_t rc;
1074
1075         if ((rc = efx_mcdi_privilege_mask(enp, encp->enc_pf, encp->enc_vf,
1076                                             &mask)) != 0) {
1077                 if (rc != ENOTSUP)
1078                         goto fail1;
1079
1080                 /* Fallback for old firmware without privilege mask support */
1081                 if (EFX_PCI_FUNCTION_IS_PF(encp)) {
1082                         /* Assume PF has admin privilege */
1083                         mask = EF10_LEGACY_PF_PRIVILEGE_MASK;
1084                 } else {
1085                         /* VF is always unprivileged by default */
1086                         mask = EF10_LEGACY_VF_PRIVILEGE_MASK;
1087                 }
1088         }
1089
1090         *maskp = mask;
1091
1092         return (0);
1093
1094 fail1:
1095         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1096
1097         return (rc);
1098 }
1099
1100
1101 /*
1102  * Table of mapping schemes from port number to the number of the external
1103  * connector on the board. The external numbering does not distinguish
1104  * off-board separated outputs such as from multi-headed cables.
1105  *
1106  * The count of adjacent port numbers that map to each external port
1107  * and the offset in the numbering, is determined by the chip family and
1108  * current port mode.
1109  *
1110  * For the Huntington family, the current port mode cannot be discovered,
1111  * so the mapping used is instead the last match in the table to the full
1112  * set of port modes to which the NIC can be configured. Therefore the
1113  * ordering of entries in the the mapping table is significant.
1114  */
1115 static struct {
1116         efx_family_t    family;
1117         uint32_t        modes_mask;
1118         int32_t         count;
1119         int32_t         offset;
1120 }       __ef10_external_port_mappings[] = {
1121         /* Supported modes with 1 output per external port */
1122         {
1123                 EFX_FAMILY_HUNTINGTON,
1124                 (1 << TLV_PORT_MODE_10G) |
1125                 (1 << TLV_PORT_MODE_10G_10G) |
1126                 (1 << TLV_PORT_MODE_10G_10G_10G_10G),
1127                 1,
1128                 1
1129         },
1130         {
1131                 EFX_FAMILY_MEDFORD,
1132                 (1 << TLV_PORT_MODE_10G) |
1133                 (1 << TLV_PORT_MODE_10G_10G),
1134                 1,
1135                 1
1136         },
1137         /* Supported modes with 2 outputs per external port */
1138         {
1139                 EFX_FAMILY_HUNTINGTON,
1140                 (1 << TLV_PORT_MODE_40G) |
1141                 (1 << TLV_PORT_MODE_40G_40G) |
1142                 (1 << TLV_PORT_MODE_40G_10G_10G) |
1143                 (1 << TLV_PORT_MODE_10G_10G_40G),
1144                 2,
1145                 1
1146         },
1147         {
1148                 EFX_FAMILY_MEDFORD,
1149                 (1 << TLV_PORT_MODE_40G) |
1150                 (1 << TLV_PORT_MODE_40G_40G) |
1151                 (1 << TLV_PORT_MODE_40G_10G_10G) |
1152                 (1 << TLV_PORT_MODE_10G_10G_40G) |
1153                 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2),
1154                 2,
1155                 1
1156         },
1157         /* Supported modes with 4 outputs per external port */
1158         {
1159                 EFX_FAMILY_MEDFORD,
1160                 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q) |
1161                 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q1),
1162                 4,
1163                 1,
1164         },
1165         {
1166                 EFX_FAMILY_MEDFORD,
1167                 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q2),
1168                 4,
1169                 2
1170         },
1171 };
1172
1173         __checkReturn   efx_rc_t
1174 ef10_external_port_mapping(
1175         __in            efx_nic_t *enp,
1176         __in            uint32_t port,
1177         __out           uint8_t *external_portp)
1178 {
1179         efx_rc_t rc;
1180         int i;
1181         uint32_t port_modes;
1182         uint32_t matches;
1183         uint32_t current;
1184         int32_t count = 1; /* Default 1-1 mapping */
1185         int32_t offset = 1; /* Default starting external port number */
1186
1187         if ((rc = efx_mcdi_get_port_modes(enp, &port_modes, &current)) != 0) {
1188                 /*
1189                  * No current port mode information
1190                  * - infer mapping from available modes
1191                  */
1192                 if ((rc = efx_mcdi_get_port_modes(enp,
1193                             &port_modes, NULL)) != 0) {
1194                         /*
1195                          * No port mode information available
1196                          * - use default mapping
1197                          */
1198                         goto out;
1199                 }
1200         } else {
1201                 /* Only need to scan the current mode */
1202                 port_modes = 1 << current;
1203         }
1204
1205         /*
1206          * Infer the internal port -> external port mapping from
1207          * the possible port modes for this NIC.
1208          */
1209         for (i = 0; i < EFX_ARRAY_SIZE(__ef10_external_port_mappings); ++i) {
1210                 if (__ef10_external_port_mappings[i].family !=
1211                     enp->en_family)
1212                         continue;
1213                 matches = (__ef10_external_port_mappings[i].modes_mask &
1214                     port_modes);
1215                 if (matches != 0) {
1216                         count = __ef10_external_port_mappings[i].count;
1217                         offset = __ef10_external_port_mappings[i].offset;
1218                         port_modes &= ~matches;
1219                 }
1220         }
1221
1222         if (port_modes != 0) {
1223                 /* Some advertised modes are not supported */
1224                 rc = ENOTSUP;
1225                 goto fail1;
1226         }
1227
1228 out:
1229         /*
1230          * Scale as required by last matched mode and then convert to
1231          * correctly offset numbering
1232          */
1233         *external_portp = (uint8_t)((port / count) + offset);
1234         return (0);
1235
1236 fail1:
1237         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1238
1239         return (rc);
1240 }
1241
1242
1243         __checkReturn   efx_rc_t
1244 ef10_nic_probe(
1245         __in            efx_nic_t *enp)
1246 {
1247         const efx_nic_ops_t *enop = enp->en_enop;
1248         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1249         efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1250         efx_rc_t rc;
1251
1252         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1253                     enp->en_family == EFX_FAMILY_MEDFORD);
1254
1255         /* Read and clear any assertion state */
1256         if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1257                 goto fail1;
1258
1259         /* Exit the assertion handler */
1260         if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1261                 if (rc != EACCES)
1262                         goto fail2;
1263
1264         if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
1265                 goto fail3;
1266
1267         if ((rc = enop->eno_board_cfg(enp)) != 0)
1268                 if (rc != EACCES)
1269                         goto fail4;
1270
1271         /*
1272          * Set default driver config limits (based on board config).
1273          *
1274          * FIXME: For now allocate a fixed number of VIs which is likely to be
1275          * sufficient and small enough to allow multiple functions on the same
1276          * port.
1277          */
1278         edcp->edc_min_vi_count = edcp->edc_max_vi_count =
1279             MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit));
1280
1281         /* The client driver must configure and enable PIO buffer support */
1282         edcp->edc_max_piobuf_count = 0;
1283         edcp->edc_pio_alloc_size = 0;
1284
1285 #if EFSYS_OPT_MAC_STATS
1286         /* Wipe the MAC statistics */
1287         if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
1288                 goto fail5;
1289 #endif
1290
1291 #if EFSYS_OPT_LOOPBACK
1292         if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
1293                 goto fail6;
1294 #endif
1295
1296 #if EFSYS_OPT_MON_STATS
1297         if ((rc = mcdi_mon_cfg_build(enp)) != 0) {
1298                 /* Unprivileged functions do not have access to sensors */
1299                 if (rc != EACCES)
1300                         goto fail7;
1301         }
1302 #endif
1303
1304         encp->enc_features = enp->en_features;
1305
1306         return (0);
1307
1308 #if EFSYS_OPT_MON_STATS
1309 fail7:
1310         EFSYS_PROBE(fail7);
1311 #endif
1312 #if EFSYS_OPT_LOOPBACK
1313 fail6:
1314         EFSYS_PROBE(fail6);
1315 #endif
1316 #if EFSYS_OPT_MAC_STATS
1317 fail5:
1318         EFSYS_PROBE(fail5);
1319 #endif
1320 fail4:
1321         EFSYS_PROBE(fail4);
1322 fail3:
1323         EFSYS_PROBE(fail3);
1324 fail2:
1325         EFSYS_PROBE(fail2);
1326 fail1:
1327         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1328
1329         return (rc);
1330 }
1331
1332         __checkReturn   efx_rc_t
1333 ef10_nic_set_drv_limits(
1334         __inout         efx_nic_t *enp,
1335         __in            efx_drv_limits_t *edlp)
1336 {
1337         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1338         efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1339         uint32_t min_evq_count, max_evq_count;
1340         uint32_t min_rxq_count, max_rxq_count;
1341         uint32_t min_txq_count, max_txq_count;
1342         efx_rc_t rc;
1343
1344         if (edlp == NULL) {
1345                 rc = EINVAL;
1346                 goto fail1;
1347         }
1348
1349         /* Get minimum required and maximum usable VI limits */
1350         min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit);
1351         min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit);
1352         min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit);
1353
1354         edcp->edc_min_vi_count =
1355             MAX(min_evq_count, MAX(min_rxq_count, min_txq_count));
1356
1357         max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit);
1358         max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit);
1359         max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit);
1360
1361         edcp->edc_max_vi_count =
1362             MAX(max_evq_count, MAX(max_rxq_count, max_txq_count));
1363
1364         /*
1365          * Check limits for sub-allocated piobuf blocks.
1366          * PIO is optional, so don't fail if the limits are incorrect.
1367          */
1368         if ((encp->enc_piobuf_size == 0) ||
1369             (encp->enc_piobuf_limit == 0) ||
1370             (edlp->edl_min_pio_alloc_size == 0) ||
1371             (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) {
1372                 /* Disable PIO */
1373                 edcp->edc_max_piobuf_count = 0;
1374                 edcp->edc_pio_alloc_size = 0;
1375         } else {
1376                 uint32_t blk_size, blk_count, blks_per_piobuf;
1377
1378                 blk_size =
1379                     MAX(edlp->edl_min_pio_alloc_size,
1380                             encp->enc_piobuf_min_alloc_size);
1381
1382                 blks_per_piobuf = encp->enc_piobuf_size / blk_size;
1383                 EFSYS_ASSERT3U(blks_per_piobuf, <=, 32);
1384
1385                 blk_count = (encp->enc_piobuf_limit * blks_per_piobuf);
1386
1387                 /* A zero max pio alloc count means unlimited */
1388                 if ((edlp->edl_max_pio_alloc_count > 0) &&
1389                     (edlp->edl_max_pio_alloc_count < blk_count)) {
1390                         blk_count = edlp->edl_max_pio_alloc_count;
1391                 }
1392
1393                 edcp->edc_pio_alloc_size = blk_size;
1394                 edcp->edc_max_piobuf_count =
1395                     (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf;
1396         }
1397
1398         return (0);
1399
1400 fail1:
1401         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1402
1403         return (rc);
1404 }
1405
1406
1407         __checkReturn   efx_rc_t
1408 ef10_nic_reset(
1409         __in            efx_nic_t *enp)
1410 {
1411         efx_mcdi_req_t req;
1412         uint8_t payload[MAX(MC_CMD_ENTITY_RESET_IN_LEN,
1413                             MC_CMD_ENTITY_RESET_OUT_LEN)];
1414         efx_rc_t rc;
1415
1416         /* ef10_nic_reset() is called to recover from BADASSERT failures. */
1417         if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1418                 goto fail1;
1419         if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1420                 goto fail2;
1421
1422         (void) memset(payload, 0, sizeof (payload));
1423         req.emr_cmd = MC_CMD_ENTITY_RESET;
1424         req.emr_in_buf = payload;
1425         req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN;
1426         req.emr_out_buf = payload;
1427         req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN;
1428
1429         MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG,
1430             ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1);
1431
1432         efx_mcdi_execute(enp, &req);
1433
1434         if (req.emr_rc != 0) {
1435                 rc = req.emr_rc;
1436                 goto fail3;
1437         }
1438
1439         /* Clear RX/TX DMA queue errors */
1440         enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR);
1441
1442         return (0);
1443
1444 fail3:
1445         EFSYS_PROBE(fail3);
1446 fail2:
1447         EFSYS_PROBE(fail2);
1448 fail1:
1449         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1450
1451         return (rc);
1452 }
1453
1454         __checkReturn   efx_rc_t
1455 ef10_nic_init(
1456         __in            efx_nic_t *enp)
1457 {
1458         efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1459         uint32_t min_vi_count, max_vi_count;
1460         uint32_t vi_count, vi_base, vi_shift;
1461         uint32_t i;
1462         uint32_t retry;
1463         uint32_t delay_us;
1464         efx_rc_t rc;
1465
1466         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1467                     enp->en_family == EFX_FAMILY_MEDFORD);
1468
1469         /* Enable reporting of some events (e.g. link change) */
1470         if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
1471                 goto fail1;
1472
1473         /* Allocate (optional) on-chip PIO buffers */
1474         ef10_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count);
1475
1476         /*
1477          * For best performance, PIO writes should use a write-combined
1478          * (WC) memory mapping. Using a separate WC mapping for the PIO
1479          * aperture of each VI would be a burden to drivers (and not
1480          * possible if the host page size is >4Kbyte).
1481          *
1482          * To avoid this we use a single uncached (UC) mapping for VI
1483          * register access, and a single WC mapping for extra VIs used
1484          * for PIO writes.
1485          *
1486          * Each piobuf must be linked to a VI in the WC mapping, and to
1487          * each VI that is using a sub-allocated block from the piobuf.
1488          */
1489         min_vi_count = edcp->edc_min_vi_count;
1490         max_vi_count =
1491             edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count;
1492
1493         /* Ensure that the previously attached driver's VIs are freed */
1494         if ((rc = efx_mcdi_free_vis(enp)) != 0)
1495                 goto fail2;
1496
1497         /*
1498          * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this
1499          * fails then retrying the request for fewer VI resources may succeed.
1500          */
1501         vi_count = 0;
1502         if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count,
1503                     &vi_base, &vi_count, &vi_shift)) != 0)
1504                 goto fail3;
1505
1506         EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count);
1507
1508         if (vi_count < min_vi_count) {
1509                 rc = ENOMEM;
1510                 goto fail4;
1511         }
1512
1513         enp->en_arch.ef10.ena_vi_base = vi_base;
1514         enp->en_arch.ef10.ena_vi_count = vi_count;
1515         enp->en_arch.ef10.ena_vi_shift = vi_shift;
1516
1517         if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) {
1518                 /* Not enough extra VIs to map piobufs */
1519                 ef10_nic_free_piobufs(enp);
1520         }
1521
1522         enp->en_arch.ef10.ena_pio_write_vi_base =
1523             vi_count - enp->en_arch.ef10.ena_piobuf_count;
1524
1525         /* Save UC memory mapping details */
1526         enp->en_arch.ef10.ena_uc_mem_map_offset = 0;
1527         if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1528                 enp->en_arch.ef10.ena_uc_mem_map_size =
1529                     (ER_DZ_TX_PIOBUF_STEP *
1530                     enp->en_arch.ef10.ena_pio_write_vi_base);
1531         } else {
1532                 enp->en_arch.ef10.ena_uc_mem_map_size =
1533                     (ER_DZ_TX_PIOBUF_STEP *
1534                     enp->en_arch.ef10.ena_vi_count);
1535         }
1536
1537         /* Save WC memory mapping details */
1538         enp->en_arch.ef10.ena_wc_mem_map_offset =
1539             enp->en_arch.ef10.ena_uc_mem_map_offset +
1540             enp->en_arch.ef10.ena_uc_mem_map_size;
1541
1542         enp->en_arch.ef10.ena_wc_mem_map_size =
1543             (ER_DZ_TX_PIOBUF_STEP *
1544             enp->en_arch.ef10.ena_piobuf_count);
1545
1546         /* Link piobufs to extra VIs in WC mapping */
1547         if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1548                 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1549                         rc = efx_mcdi_link_piobuf(enp,
1550                             enp->en_arch.ef10.ena_pio_write_vi_base + i,
1551                             enp->en_arch.ef10.ena_piobuf_handle[i]);
1552                         if (rc != 0)
1553                                 break;
1554                 }
1555         }
1556
1557         /*
1558          * Allocate a vAdaptor attached to our upstream vPort/pPort.
1559          *
1560          * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF
1561          * driver has yet to bring up the EVB port. See bug 56147. In this case,
1562          * retry the request several times after waiting a while. The wait time
1563          * between retries starts small (10ms) and exponentially increases.
1564          * Total wait time is a little over two seconds. Retry logic in the
1565          * client driver may mean this whole loop is repeated if it continues to
1566          * fail.
1567          */
1568         retry = 0;
1569         delay_us = 10000;
1570         while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) {
1571                 if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) ||
1572                     (rc != ENOENT)) {
1573                         /*
1574                          * Do not retry alloc for PF, or for other errors on
1575                          * a VF.
1576                          */
1577                         goto fail5;
1578                 }
1579
1580                 /* VF startup before PF is ready. Retry allocation. */
1581                 if (retry > 5) {
1582                         /* Too many attempts */
1583                         rc = EINVAL;
1584                         goto fail6;
1585                 }
1586                 EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry);
1587                 EFSYS_SLEEP(delay_us);
1588                 retry++;
1589                 if (delay_us < 500000)
1590                         delay_us <<= 2;
1591         }
1592
1593         enp->en_vport_id = EVB_PORT_ID_ASSIGNED;
1594         enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2;
1595
1596         return (0);
1597
1598 fail6:
1599         EFSYS_PROBE(fail6);
1600 fail5:
1601         EFSYS_PROBE(fail5);
1602 fail4:
1603         EFSYS_PROBE(fail4);
1604 fail3:
1605         EFSYS_PROBE(fail3);
1606 fail2:
1607         EFSYS_PROBE(fail2);
1608
1609         ef10_nic_free_piobufs(enp);
1610
1611 fail1:
1612         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1613
1614         return (rc);
1615 }
1616
1617         __checkReturn   efx_rc_t
1618 ef10_nic_get_vi_pool(
1619         __in            efx_nic_t *enp,
1620         __out           uint32_t *vi_countp)
1621 {
1622         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1623                     enp->en_family == EFX_FAMILY_MEDFORD);
1624
1625         /*
1626          * Report VIs that the client driver can use.
1627          * Do not include VIs used for PIO buffer writes.
1628          */
1629         *vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base;
1630
1631         return (0);
1632 }
1633
1634         __checkReturn   efx_rc_t
1635 ef10_nic_get_bar_region(
1636         __in            efx_nic_t *enp,
1637         __in            efx_nic_region_t region,
1638         __out           uint32_t *offsetp,
1639         __out           size_t *sizep)
1640 {
1641         efx_rc_t rc;
1642
1643         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1644                     enp->en_family == EFX_FAMILY_MEDFORD);
1645
1646         /*
1647          * TODO: Specify host memory mapping alignment and granularity
1648          * in efx_drv_limits_t so that they can be taken into account
1649          * when allocating extra VIs for PIO writes.
1650          */
1651         switch (region) {
1652         case EFX_REGION_VI:
1653                 /* UC mapped memory BAR region for VI registers */
1654                 *offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset;
1655                 *sizep = enp->en_arch.ef10.ena_uc_mem_map_size;
1656                 break;
1657
1658         case EFX_REGION_PIO_WRITE_VI:
1659                 /* WC mapped memory BAR region for piobuf writes */
1660                 *offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset;
1661                 *sizep = enp->en_arch.ef10.ena_wc_mem_map_size;
1662                 break;
1663
1664         default:
1665                 rc = EINVAL;
1666                 goto fail1;
1667         }
1668
1669         return (0);
1670
1671 fail1:
1672         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1673
1674         return (rc);
1675 }
1676
1677                         void
1678 ef10_nic_fini(
1679         __in            efx_nic_t *enp)
1680 {
1681         uint32_t i;
1682         efx_rc_t rc;
1683
1684         (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id);
1685         enp->en_vport_id = 0;
1686
1687         /* Unlink piobufs from extra VIs in WC mapping */
1688         if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1689                 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1690                         rc = efx_mcdi_unlink_piobuf(enp,
1691                             enp->en_arch.ef10.ena_pio_write_vi_base + i);
1692                         if (rc != 0)
1693                                 break;
1694                 }
1695         }
1696
1697         ef10_nic_free_piobufs(enp);
1698
1699         (void) efx_mcdi_free_vis(enp);
1700         enp->en_arch.ef10.ena_vi_count = 0;
1701 }
1702
1703                         void
1704 ef10_nic_unprobe(
1705         __in            efx_nic_t *enp)
1706 {
1707 #if EFSYS_OPT_MON_STATS
1708         mcdi_mon_cfg_free(enp);
1709 #endif /* EFSYS_OPT_MON_STATS */
1710         (void) efx_mcdi_drv_attach(enp, B_FALSE);
1711 }
1712
1713 #if EFSYS_OPT_DIAG
1714
1715         __checkReturn   efx_rc_t
1716 ef10_nic_register_test(
1717         __in            efx_nic_t *enp)
1718 {
1719         efx_rc_t rc;
1720
1721         /* FIXME */
1722         _NOTE(ARGUNUSED(enp))
1723         _NOTE(CONSTANTCONDITION)
1724         if (B_FALSE) {
1725                 rc = ENOTSUP;
1726                 goto fail1;
1727         }
1728         /* FIXME */
1729
1730         return (0);
1731
1732 fail1:
1733         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1734
1735         return (rc);
1736 }
1737
1738 #endif  /* EFSYS_OPT_DIAG */
1739
1740
1741 #endif  /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */