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