]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/sfxge/common/ef10_nic.c
sfxge(4): add accessor for default port mode
[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 || EFSYS_OPT_MEDFORD2
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             enp->en_family == EFX_FAMILY_MEDFORD2);
57
58         (void) memset(payload, 0, sizeof (payload));
59         req.emr_cmd = MC_CMD_GET_PORT_ASSIGNMENT;
60         req.emr_in_buf = payload;
61         req.emr_in_length = MC_CMD_GET_PORT_ASSIGNMENT_IN_LEN;
62         req.emr_out_buf = payload;
63         req.emr_out_length = MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN;
64
65         efx_mcdi_execute(enp, &req);
66
67         if (req.emr_rc != 0) {
68                 rc = req.emr_rc;
69                 goto fail1;
70         }
71
72         if (req.emr_out_length_used < MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN) {
73                 rc = EMSGSIZE;
74                 goto fail2;
75         }
76
77         *portp = MCDI_OUT_DWORD(req, GET_PORT_ASSIGNMENT_OUT_PORT);
78
79         return (0);
80
81 fail2:
82         EFSYS_PROBE(fail2);
83 fail1:
84         EFSYS_PROBE1(fail1, efx_rc_t, rc);
85
86         return (rc);
87 }
88
89         __checkReturn   efx_rc_t
90 efx_mcdi_get_port_modes(
91         __in            efx_nic_t *enp,
92         __out           uint32_t *modesp,
93         __out_opt       uint32_t *current_modep,
94         __out_opt       uint32_t *default_modep)
95 {
96         efx_mcdi_req_t req;
97         uint8_t payload[MAX(MC_CMD_GET_PORT_MODES_IN_LEN,
98                             MC_CMD_GET_PORT_MODES_OUT_LEN)];
99         efx_rc_t rc;
100
101         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
102             enp->en_family == EFX_FAMILY_MEDFORD ||
103             enp->en_family == EFX_FAMILY_MEDFORD2);
104
105         (void) memset(payload, 0, sizeof (payload));
106         req.emr_cmd = MC_CMD_GET_PORT_MODES;
107         req.emr_in_buf = payload;
108         req.emr_in_length = MC_CMD_GET_PORT_MODES_IN_LEN;
109         req.emr_out_buf = payload;
110         req.emr_out_length = MC_CMD_GET_PORT_MODES_OUT_LEN;
111
112         efx_mcdi_execute(enp, &req);
113
114         if (req.emr_rc != 0) {
115                 rc = req.emr_rc;
116                 goto fail1;
117         }
118
119         /*
120          * Require only Modes and DefaultMode fields, unless the current mode
121          * was requested (CurrentMode field was added for Medford).
122          */
123         if (req.emr_out_length_used <
124             MC_CMD_GET_PORT_MODES_OUT_CURRENT_MODE_OFST) {
125                 rc = EMSGSIZE;
126                 goto fail2;
127         }
128         if ((current_modep != NULL) && (req.emr_out_length_used <
129             MC_CMD_GET_PORT_MODES_OUT_CURRENT_MODE_OFST + 4)) {
130                 rc = EMSGSIZE;
131                 goto fail3;
132         }
133
134         *modesp = MCDI_OUT_DWORD(req, GET_PORT_MODES_OUT_MODES);
135
136         if (current_modep != NULL) {
137                 *current_modep = MCDI_OUT_DWORD(req,
138                                             GET_PORT_MODES_OUT_CURRENT_MODE);
139         }
140
141         if (default_modep != NULL) {
142                 *default_modep = MCDI_OUT_DWORD(req,
143                                             GET_PORT_MODES_OUT_DEFAULT_MODE);
144         }
145
146         return (0);
147
148 fail3:
149         EFSYS_PROBE(fail3);
150 fail2:
151         EFSYS_PROBE(fail2);
152 fail1:
153         EFSYS_PROBE1(fail1, efx_rc_t, rc);
154
155         return (rc);
156 }
157
158         __checkReturn   efx_rc_t
159 ef10_nic_get_port_mode_bandwidth(
160         __in            uint32_t port_mode,
161         __out           uint32_t *bandwidth_mbpsp)
162 {
163         uint32_t bandwidth;
164         efx_rc_t rc;
165
166         switch (port_mode) {
167         case TLV_PORT_MODE_10G:
168                 bandwidth = 10000;
169                 break;
170         case TLV_PORT_MODE_10G_10G:
171                 bandwidth = 10000 * 2;
172                 break;
173         case TLV_PORT_MODE_10G_10G_10G_10G:
174         case TLV_PORT_MODE_10G_10G_10G_10G_Q:
175         case TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2:
176         case TLV_PORT_MODE_10G_10G_10G_10G_Q2:
177                 bandwidth = 10000 * 4;
178                 break;
179         case TLV_PORT_MODE_40G:
180                 bandwidth = 40000;
181                 break;
182         case TLV_PORT_MODE_40G_40G:
183                 bandwidth = 40000 * 2;
184                 break;
185         case TLV_PORT_MODE_40G_10G_10G:
186         case TLV_PORT_MODE_10G_10G_40G:
187                 bandwidth = 40000 + (10000 * 2);
188                 break;
189         default:
190                 rc = EINVAL;
191                 goto fail1;
192         }
193
194         *bandwidth_mbpsp = bandwidth;
195
196         return (0);
197
198 fail1:
199         EFSYS_PROBE1(fail1, efx_rc_t, rc);
200
201         return (rc);
202 }
203
204 static  __checkReturn           efx_rc_t
205 efx_mcdi_vadaptor_alloc(
206         __in                    efx_nic_t *enp,
207         __in                    uint32_t port_id)
208 {
209         efx_mcdi_req_t req;
210         uint8_t payload[MAX(MC_CMD_VADAPTOR_ALLOC_IN_LEN,
211                             MC_CMD_VADAPTOR_ALLOC_OUT_LEN)];
212         efx_rc_t rc;
213
214         EFSYS_ASSERT3U(enp->en_vport_id, ==, EVB_PORT_ID_NULL);
215
216         (void) memset(payload, 0, sizeof (payload));
217         req.emr_cmd = MC_CMD_VADAPTOR_ALLOC;
218         req.emr_in_buf = payload;
219         req.emr_in_length = MC_CMD_VADAPTOR_ALLOC_IN_LEN;
220         req.emr_out_buf = payload;
221         req.emr_out_length = MC_CMD_VADAPTOR_ALLOC_OUT_LEN;
222
223         MCDI_IN_SET_DWORD(req, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
224         MCDI_IN_POPULATE_DWORD_1(req, VADAPTOR_ALLOC_IN_FLAGS,
225             VADAPTOR_ALLOC_IN_FLAG_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED,
226             enp->en_nic_cfg.enc_allow_set_mac_with_installed_filters ? 1 : 0);
227
228         efx_mcdi_execute(enp, &req);
229
230         if (req.emr_rc != 0) {
231                 rc = req.emr_rc;
232                 goto fail1;
233         }
234
235         return (0);
236
237 fail1:
238         EFSYS_PROBE1(fail1, efx_rc_t, rc);
239
240         return (rc);
241 }
242
243 static  __checkReturn           efx_rc_t
244 efx_mcdi_vadaptor_free(
245         __in                    efx_nic_t *enp,
246         __in                    uint32_t port_id)
247 {
248         efx_mcdi_req_t req;
249         uint8_t payload[MAX(MC_CMD_VADAPTOR_FREE_IN_LEN,
250                             MC_CMD_VADAPTOR_FREE_OUT_LEN)];
251         efx_rc_t rc;
252
253         (void) memset(payload, 0, sizeof (payload));
254         req.emr_cmd = MC_CMD_VADAPTOR_FREE;
255         req.emr_in_buf = payload;
256         req.emr_in_length = MC_CMD_VADAPTOR_FREE_IN_LEN;
257         req.emr_out_buf = payload;
258         req.emr_out_length = MC_CMD_VADAPTOR_FREE_OUT_LEN;
259
260         MCDI_IN_SET_DWORD(req, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id);
261
262         efx_mcdi_execute(enp, &req);
263
264         if (req.emr_rc != 0) {
265                 rc = req.emr_rc;
266                 goto fail1;
267         }
268
269         return (0);
270
271 fail1:
272         EFSYS_PROBE1(fail1, efx_rc_t, rc);
273
274         return (rc);
275 }
276
277         __checkReturn   efx_rc_t
278 efx_mcdi_get_mac_address_pf(
279         __in                    efx_nic_t *enp,
280         __out_ecount_opt(6)     uint8_t mac_addrp[6])
281 {
282         efx_mcdi_req_t req;
283         uint8_t payload[MAX(MC_CMD_GET_MAC_ADDRESSES_IN_LEN,
284                             MC_CMD_GET_MAC_ADDRESSES_OUT_LEN)];
285         efx_rc_t rc;
286
287         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
288             enp->en_family == EFX_FAMILY_MEDFORD ||
289             enp->en_family == EFX_FAMILY_MEDFORD2);
290
291         (void) memset(payload, 0, sizeof (payload));
292         req.emr_cmd = MC_CMD_GET_MAC_ADDRESSES;
293         req.emr_in_buf = payload;
294         req.emr_in_length = MC_CMD_GET_MAC_ADDRESSES_IN_LEN;
295         req.emr_out_buf = payload;
296         req.emr_out_length = MC_CMD_GET_MAC_ADDRESSES_OUT_LEN;
297
298         efx_mcdi_execute(enp, &req);
299
300         if (req.emr_rc != 0) {
301                 rc = req.emr_rc;
302                 goto fail1;
303         }
304
305         if (req.emr_out_length_used < MC_CMD_GET_MAC_ADDRESSES_OUT_LEN) {
306                 rc = EMSGSIZE;
307                 goto fail2;
308         }
309
310         if (MCDI_OUT_DWORD(req, GET_MAC_ADDRESSES_OUT_MAC_COUNT) < 1) {
311                 rc = ENOENT;
312                 goto fail3;
313         }
314
315         if (mac_addrp != NULL) {
316                 uint8_t *addrp;
317
318                 addrp = MCDI_OUT2(req, uint8_t,
319                     GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE);
320
321                 EFX_MAC_ADDR_COPY(mac_addrp, addrp);
322         }
323
324         return (0);
325
326 fail3:
327         EFSYS_PROBE(fail3);
328 fail2:
329         EFSYS_PROBE(fail2);
330 fail1:
331         EFSYS_PROBE1(fail1, efx_rc_t, rc);
332
333         return (rc);
334 }
335
336         __checkReturn   efx_rc_t
337 efx_mcdi_get_mac_address_vf(
338         __in                    efx_nic_t *enp,
339         __out_ecount_opt(6)     uint8_t mac_addrp[6])
340 {
341         efx_mcdi_req_t req;
342         uint8_t payload[MAX(MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN,
343                             MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX)];
344         efx_rc_t rc;
345
346         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
347             enp->en_family == EFX_FAMILY_MEDFORD ||
348             enp->en_family == EFX_FAMILY_MEDFORD2);
349
350         (void) memset(payload, 0, sizeof (payload));
351         req.emr_cmd = MC_CMD_VPORT_GET_MAC_ADDRESSES;
352         req.emr_in_buf = payload;
353         req.emr_in_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN;
354         req.emr_out_buf = payload;
355         req.emr_out_length = MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX;
356
357         MCDI_IN_SET_DWORD(req, VPORT_GET_MAC_ADDRESSES_IN_VPORT_ID,
358             EVB_PORT_ID_ASSIGNED);
359
360         efx_mcdi_execute(enp, &req);
361
362         if (req.emr_rc != 0) {
363                 rc = req.emr_rc;
364                 goto fail1;
365         }
366
367         if (req.emr_out_length_used <
368             MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMIN) {
369                 rc = EMSGSIZE;
370                 goto fail2;
371         }
372
373         if (MCDI_OUT_DWORD(req,
374                 VPORT_GET_MAC_ADDRESSES_OUT_MACADDR_COUNT) < 1) {
375                 rc = ENOENT;
376                 goto fail3;
377         }
378
379         if (mac_addrp != NULL) {
380                 uint8_t *addrp;
381
382                 addrp = MCDI_OUT2(req, uint8_t,
383                     VPORT_GET_MAC_ADDRESSES_OUT_MACADDR);
384
385                 EFX_MAC_ADDR_COPY(mac_addrp, addrp);
386         }
387
388         return (0);
389
390 fail3:
391         EFSYS_PROBE(fail3);
392 fail2:
393         EFSYS_PROBE(fail2);
394 fail1:
395         EFSYS_PROBE1(fail1, efx_rc_t, rc);
396
397         return (rc);
398 }
399
400         __checkReturn   efx_rc_t
401 efx_mcdi_get_clock(
402         __in            efx_nic_t *enp,
403         __out           uint32_t *sys_freqp,
404         __out           uint32_t *dpcpu_freqp)
405 {
406         efx_mcdi_req_t req;
407         uint8_t payload[MAX(MC_CMD_GET_CLOCK_IN_LEN,
408                             MC_CMD_GET_CLOCK_OUT_LEN)];
409         efx_rc_t rc;
410
411         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
412             enp->en_family == EFX_FAMILY_MEDFORD ||
413             enp->en_family == EFX_FAMILY_MEDFORD2);
414
415         (void) memset(payload, 0, sizeof (payload));
416         req.emr_cmd = MC_CMD_GET_CLOCK;
417         req.emr_in_buf = payload;
418         req.emr_in_length = MC_CMD_GET_CLOCK_IN_LEN;
419         req.emr_out_buf = payload;
420         req.emr_out_length = MC_CMD_GET_CLOCK_OUT_LEN;
421
422         efx_mcdi_execute(enp, &req);
423
424         if (req.emr_rc != 0) {
425                 rc = req.emr_rc;
426                 goto fail1;
427         }
428
429         if (req.emr_out_length_used < MC_CMD_GET_CLOCK_OUT_LEN) {
430                 rc = EMSGSIZE;
431                 goto fail2;
432         }
433
434         *sys_freqp = MCDI_OUT_DWORD(req, GET_CLOCK_OUT_SYS_FREQ);
435         if (*sys_freqp == 0) {
436                 rc = EINVAL;
437                 goto fail3;
438         }
439         *dpcpu_freqp = MCDI_OUT_DWORD(req, GET_CLOCK_OUT_DPCPU_FREQ);
440         if (*dpcpu_freqp == 0) {
441                 rc = EINVAL;
442                 goto fail4;
443         }
444
445         return (0);
446
447 fail4:
448         EFSYS_PROBE(fail4);
449 fail3:
450         EFSYS_PROBE(fail3);
451 fail2:
452         EFSYS_PROBE(fail2);
453 fail1:
454         EFSYS_PROBE1(fail1, efx_rc_t, rc);
455
456         return (rc);
457 }
458
459         __checkReturn   efx_rc_t
460 efx_mcdi_get_rxdp_config(
461         __in            efx_nic_t *enp,
462         __out           uint32_t *end_paddingp)
463 {
464         efx_mcdi_req_t req;
465         uint8_t payload[MAX(MC_CMD_GET_RXDP_CONFIG_IN_LEN,
466                             MC_CMD_GET_RXDP_CONFIG_OUT_LEN)];
467         uint32_t end_padding;
468         efx_rc_t rc;
469
470         memset(payload, 0, sizeof (payload));
471         req.emr_cmd = MC_CMD_GET_RXDP_CONFIG;
472         req.emr_in_buf = payload;
473         req.emr_in_length = MC_CMD_GET_RXDP_CONFIG_IN_LEN;
474         req.emr_out_buf = payload;
475         req.emr_out_length = MC_CMD_GET_RXDP_CONFIG_OUT_LEN;
476
477         efx_mcdi_execute(enp, &req);
478         if (req.emr_rc != 0) {
479                 rc = req.emr_rc;
480                 goto fail1;
481         }
482
483         if (MCDI_OUT_DWORD_FIELD(req, GET_RXDP_CONFIG_OUT_DATA,
484                                     GET_RXDP_CONFIG_OUT_PAD_HOST_DMA) == 0) {
485                 /* RX DMA end padding is disabled */
486                 end_padding = 0;
487         } else {
488                 switch (MCDI_OUT_DWORD_FIELD(req, GET_RXDP_CONFIG_OUT_DATA,
489                                             GET_RXDP_CONFIG_OUT_PAD_HOST_LEN)) {
490                 case MC_CMD_SET_RXDP_CONFIG_IN_PAD_HOST_64:
491                         end_padding = 64;
492                         break;
493                 case MC_CMD_SET_RXDP_CONFIG_IN_PAD_HOST_128:
494                         end_padding = 128;
495                         break;
496                 case MC_CMD_SET_RXDP_CONFIG_IN_PAD_HOST_256:
497                         end_padding = 256;
498                         break;
499                 default:
500                         rc = ENOTSUP;
501                         goto fail2;
502                 }
503         }
504
505         *end_paddingp = end_padding;
506
507         return (0);
508
509 fail2:
510         EFSYS_PROBE(fail2);
511 fail1:
512         EFSYS_PROBE1(fail1, efx_rc_t, rc);
513
514         return (rc);
515 }
516
517         __checkReturn   efx_rc_t
518 efx_mcdi_get_vector_cfg(
519         __in            efx_nic_t *enp,
520         __out_opt       uint32_t *vec_basep,
521         __out_opt       uint32_t *pf_nvecp,
522         __out_opt       uint32_t *vf_nvecp)
523 {
524         efx_mcdi_req_t req;
525         uint8_t payload[MAX(MC_CMD_GET_VECTOR_CFG_IN_LEN,
526                             MC_CMD_GET_VECTOR_CFG_OUT_LEN)];
527         efx_rc_t rc;
528
529         (void) memset(payload, 0, sizeof (payload));
530         req.emr_cmd = MC_CMD_GET_VECTOR_CFG;
531         req.emr_in_buf = payload;
532         req.emr_in_length = MC_CMD_GET_VECTOR_CFG_IN_LEN;
533         req.emr_out_buf = payload;
534         req.emr_out_length = MC_CMD_GET_VECTOR_CFG_OUT_LEN;
535
536         efx_mcdi_execute(enp, &req);
537
538         if (req.emr_rc != 0) {
539                 rc = req.emr_rc;
540                 goto fail1;
541         }
542
543         if (req.emr_out_length_used < MC_CMD_GET_VECTOR_CFG_OUT_LEN) {
544                 rc = EMSGSIZE;
545                 goto fail2;
546         }
547
548         if (vec_basep != NULL)
549                 *vec_basep = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VEC_BASE);
550         if (pf_nvecp != NULL)
551                 *pf_nvecp = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VECS_PER_PF);
552         if (vf_nvecp != NULL)
553                 *vf_nvecp = MCDI_OUT_DWORD(req, GET_VECTOR_CFG_OUT_VECS_PER_VF);
554
555         return (0);
556
557 fail2:
558         EFSYS_PROBE(fail2);
559 fail1:
560         EFSYS_PROBE1(fail1, efx_rc_t, rc);
561
562         return (rc);
563 }
564
565 static  __checkReturn   efx_rc_t
566 efx_mcdi_alloc_vis(
567         __in            efx_nic_t *enp,
568         __in            uint32_t min_vi_count,
569         __in            uint32_t max_vi_count,
570         __out           uint32_t *vi_basep,
571         __out           uint32_t *vi_countp,
572         __out           uint32_t *vi_shiftp)
573 {
574         efx_mcdi_req_t req;
575         uint8_t payload[MAX(MC_CMD_ALLOC_VIS_IN_LEN,
576                             MC_CMD_ALLOC_VIS_EXT_OUT_LEN)];
577         efx_rc_t rc;
578
579         if (vi_countp == NULL) {
580                 rc = EINVAL;
581                 goto fail1;
582         }
583
584         (void) memset(payload, 0, sizeof (payload));
585         req.emr_cmd = MC_CMD_ALLOC_VIS;
586         req.emr_in_buf = payload;
587         req.emr_in_length = MC_CMD_ALLOC_VIS_IN_LEN;
588         req.emr_out_buf = payload;
589         req.emr_out_length = MC_CMD_ALLOC_VIS_EXT_OUT_LEN;
590
591         MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MIN_VI_COUNT, min_vi_count);
592         MCDI_IN_SET_DWORD(req, ALLOC_VIS_IN_MAX_VI_COUNT, max_vi_count);
593
594         efx_mcdi_execute(enp, &req);
595
596         if (req.emr_rc != 0) {
597                 rc = req.emr_rc;
598                 goto fail2;
599         }
600
601         if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_OUT_LEN) {
602                 rc = EMSGSIZE;
603                 goto fail3;
604         }
605
606         *vi_basep = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_BASE);
607         *vi_countp = MCDI_OUT_DWORD(req, ALLOC_VIS_OUT_VI_COUNT);
608
609         /* Report VI_SHIFT if available (always zero for Huntington) */
610         if (req.emr_out_length_used < MC_CMD_ALLOC_VIS_EXT_OUT_LEN)
611                 *vi_shiftp = 0;
612         else
613                 *vi_shiftp = MCDI_OUT_DWORD(req, ALLOC_VIS_EXT_OUT_VI_SHIFT);
614
615         return (0);
616
617 fail3:
618         EFSYS_PROBE(fail3);
619 fail2:
620         EFSYS_PROBE(fail2);
621 fail1:
622         EFSYS_PROBE1(fail1, efx_rc_t, rc);
623
624         return (rc);
625 }
626
627
628 static  __checkReturn   efx_rc_t
629 efx_mcdi_free_vis(
630         __in            efx_nic_t *enp)
631 {
632         efx_mcdi_req_t req;
633         efx_rc_t rc;
634
635         EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_IN_LEN == 0);
636         EFX_STATIC_ASSERT(MC_CMD_FREE_VIS_OUT_LEN == 0);
637
638         req.emr_cmd = MC_CMD_FREE_VIS;
639         req.emr_in_buf = NULL;
640         req.emr_in_length = 0;
641         req.emr_out_buf = NULL;
642         req.emr_out_length = 0;
643
644         efx_mcdi_execute_quiet(enp, &req);
645
646         /* Ignore ELREADY (no allocated VIs, so nothing to free) */
647         if ((req.emr_rc != 0) && (req.emr_rc != EALREADY)) {
648                 rc = req.emr_rc;
649                 goto fail1;
650         }
651
652         return (0);
653
654 fail1:
655         EFSYS_PROBE1(fail1, efx_rc_t, rc);
656
657         return (rc);
658 }
659
660
661 static  __checkReturn   efx_rc_t
662 efx_mcdi_alloc_piobuf(
663         __in            efx_nic_t *enp,
664         __out           efx_piobuf_handle_t *handlep)
665 {
666         efx_mcdi_req_t req;
667         uint8_t payload[MAX(MC_CMD_ALLOC_PIOBUF_IN_LEN,
668                             MC_CMD_ALLOC_PIOBUF_OUT_LEN)];
669         efx_rc_t rc;
670
671         if (handlep == NULL) {
672                 rc = EINVAL;
673                 goto fail1;
674         }
675
676         (void) memset(payload, 0, sizeof (payload));
677         req.emr_cmd = MC_CMD_ALLOC_PIOBUF;
678         req.emr_in_buf = payload;
679         req.emr_in_length = MC_CMD_ALLOC_PIOBUF_IN_LEN;
680         req.emr_out_buf = payload;
681         req.emr_out_length = MC_CMD_ALLOC_PIOBUF_OUT_LEN;
682
683         efx_mcdi_execute_quiet(enp, &req);
684
685         if (req.emr_rc != 0) {
686                 rc = req.emr_rc;
687                 goto fail2;
688         }
689
690         if (req.emr_out_length_used < MC_CMD_ALLOC_PIOBUF_OUT_LEN) {
691                 rc = EMSGSIZE;
692                 goto fail3;
693         }
694
695         *handlep = MCDI_OUT_DWORD(req, ALLOC_PIOBUF_OUT_PIOBUF_HANDLE);
696
697         return (0);
698
699 fail3:
700         EFSYS_PROBE(fail3);
701 fail2:
702         EFSYS_PROBE(fail2);
703 fail1:
704         EFSYS_PROBE1(fail1, efx_rc_t, rc);
705
706         return (rc);
707 }
708
709 static  __checkReturn   efx_rc_t
710 efx_mcdi_free_piobuf(
711         __in            efx_nic_t *enp,
712         __in            efx_piobuf_handle_t handle)
713 {
714         efx_mcdi_req_t req;
715         uint8_t payload[MAX(MC_CMD_FREE_PIOBUF_IN_LEN,
716                             MC_CMD_FREE_PIOBUF_OUT_LEN)];
717         efx_rc_t rc;
718
719         (void) memset(payload, 0, sizeof (payload));
720         req.emr_cmd = MC_CMD_FREE_PIOBUF;
721         req.emr_in_buf = payload;
722         req.emr_in_length = MC_CMD_FREE_PIOBUF_IN_LEN;
723         req.emr_out_buf = payload;
724         req.emr_out_length = MC_CMD_FREE_PIOBUF_OUT_LEN;
725
726         MCDI_IN_SET_DWORD(req, FREE_PIOBUF_IN_PIOBUF_HANDLE, handle);
727
728         efx_mcdi_execute_quiet(enp, &req);
729
730         if (req.emr_rc != 0) {
731                 rc = req.emr_rc;
732                 goto fail1;
733         }
734
735         return (0);
736
737 fail1:
738         EFSYS_PROBE1(fail1, efx_rc_t, rc);
739
740         return (rc);
741 }
742
743 static  __checkReturn   efx_rc_t
744 efx_mcdi_link_piobuf(
745         __in            efx_nic_t *enp,
746         __in            uint32_t vi_index,
747         __in            efx_piobuf_handle_t handle)
748 {
749         efx_mcdi_req_t req;
750         uint8_t payload[MAX(MC_CMD_LINK_PIOBUF_IN_LEN,
751                             MC_CMD_LINK_PIOBUF_OUT_LEN)];
752         efx_rc_t rc;
753
754         (void) memset(payload, 0, sizeof (payload));
755         req.emr_cmd = MC_CMD_LINK_PIOBUF;
756         req.emr_in_buf = payload;
757         req.emr_in_length = MC_CMD_LINK_PIOBUF_IN_LEN;
758         req.emr_out_buf = payload;
759         req.emr_out_length = MC_CMD_LINK_PIOBUF_OUT_LEN;
760
761         MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_PIOBUF_HANDLE, handle);
762         MCDI_IN_SET_DWORD(req, LINK_PIOBUF_IN_TXQ_INSTANCE, vi_index);
763
764         efx_mcdi_execute(enp, &req);
765
766         if (req.emr_rc != 0) {
767                 rc = req.emr_rc;
768                 goto fail1;
769         }
770
771         return (0);
772
773 fail1:
774         EFSYS_PROBE1(fail1, efx_rc_t, rc);
775
776         return (rc);
777 }
778
779 static  __checkReturn   efx_rc_t
780 efx_mcdi_unlink_piobuf(
781         __in            efx_nic_t *enp,
782         __in            uint32_t vi_index)
783 {
784         efx_mcdi_req_t req;
785         uint8_t payload[MAX(MC_CMD_UNLINK_PIOBUF_IN_LEN,
786                             MC_CMD_UNLINK_PIOBUF_OUT_LEN)];
787         efx_rc_t rc;
788
789         (void) memset(payload, 0, sizeof (payload));
790         req.emr_cmd = MC_CMD_UNLINK_PIOBUF;
791         req.emr_in_buf = payload;
792         req.emr_in_length = MC_CMD_UNLINK_PIOBUF_IN_LEN;
793         req.emr_out_buf = payload;
794         req.emr_out_length = MC_CMD_UNLINK_PIOBUF_OUT_LEN;
795
796         MCDI_IN_SET_DWORD(req, UNLINK_PIOBUF_IN_TXQ_INSTANCE, vi_index);
797
798         efx_mcdi_execute_quiet(enp, &req);
799
800         if (req.emr_rc != 0) {
801                 rc = req.emr_rc;
802                 goto fail1;
803         }
804
805         return (0);
806
807 fail1:
808         EFSYS_PROBE1(fail1, efx_rc_t, rc);
809
810         return (rc);
811 }
812
813 static                  void
814 ef10_nic_alloc_piobufs(
815         __in            efx_nic_t *enp,
816         __in            uint32_t max_piobuf_count)
817 {
818         efx_piobuf_handle_t *handlep;
819         unsigned int i;
820
821         EFSYS_ASSERT3U(max_piobuf_count, <=,
822             EFX_ARRAY_SIZE(enp->en_arch.ef10.ena_piobuf_handle));
823
824         enp->en_arch.ef10.ena_piobuf_count = 0;
825
826         for (i = 0; i < max_piobuf_count; i++) {
827                 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
828
829                 if (efx_mcdi_alloc_piobuf(enp, handlep) != 0)
830                         goto fail1;
831
832                 enp->en_arch.ef10.ena_pio_alloc_map[i] = 0;
833                 enp->en_arch.ef10.ena_piobuf_count++;
834         }
835
836         return;
837
838 fail1:
839         for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
840                 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
841
842                 (void) efx_mcdi_free_piobuf(enp, *handlep);
843                 *handlep = EFX_PIOBUF_HANDLE_INVALID;
844         }
845         enp->en_arch.ef10.ena_piobuf_count = 0;
846 }
847
848
849 static                  void
850 ef10_nic_free_piobufs(
851         __in            efx_nic_t *enp)
852 {
853         efx_piobuf_handle_t *handlep;
854         unsigned int i;
855
856         for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
857                 handlep = &enp->en_arch.ef10.ena_piobuf_handle[i];
858
859                 (void) efx_mcdi_free_piobuf(enp, *handlep);
860                 *handlep = EFX_PIOBUF_HANDLE_INVALID;
861         }
862         enp->en_arch.ef10.ena_piobuf_count = 0;
863 }
864
865 /* Sub-allocate a block from a piobuf */
866         __checkReturn   efx_rc_t
867 ef10_nic_pio_alloc(
868         __inout         efx_nic_t *enp,
869         __out           uint32_t *bufnump,
870         __out           efx_piobuf_handle_t *handlep,
871         __out           uint32_t *blknump,
872         __out           uint32_t *offsetp,
873         __out           size_t *sizep)
874 {
875         efx_nic_cfg_t *encp = &enp->en_nic_cfg;
876         efx_drv_cfg_t *edcp = &enp->en_drv_cfg;
877         uint32_t blk_per_buf;
878         uint32_t buf, blk;
879         efx_rc_t rc;
880
881         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
882             enp->en_family == EFX_FAMILY_MEDFORD ||
883             enp->en_family == EFX_FAMILY_MEDFORD2);
884         EFSYS_ASSERT(bufnump);
885         EFSYS_ASSERT(handlep);
886         EFSYS_ASSERT(blknump);
887         EFSYS_ASSERT(offsetp);
888         EFSYS_ASSERT(sizep);
889
890         if ((edcp->edc_pio_alloc_size == 0) ||
891             (enp->en_arch.ef10.ena_piobuf_count == 0)) {
892                 rc = ENOMEM;
893                 goto fail1;
894         }
895         blk_per_buf = encp->enc_piobuf_size / edcp->edc_pio_alloc_size;
896
897         for (buf = 0; buf < enp->en_arch.ef10.ena_piobuf_count; buf++) {
898                 uint32_t *map = &enp->en_arch.ef10.ena_pio_alloc_map[buf];
899
900                 if (~(*map) == 0)
901                         continue;
902
903                 EFSYS_ASSERT3U(blk_per_buf, <=, (8 * sizeof (*map)));
904                 for (blk = 0; blk < blk_per_buf; blk++) {
905                         if ((*map & (1u << blk)) == 0) {
906                                 *map |= (1u << blk);
907                                 goto done;
908                         }
909                 }
910         }
911         rc = ENOMEM;
912         goto fail2;
913
914 done:
915         *handlep = enp->en_arch.ef10.ena_piobuf_handle[buf];
916         *bufnump = buf;
917         *blknump = blk;
918         *sizep = edcp->edc_pio_alloc_size;
919         *offsetp = blk * (*sizep);
920
921         return (0);
922
923 fail2:
924         EFSYS_PROBE(fail2);
925 fail1:
926         EFSYS_PROBE1(fail1, efx_rc_t, rc);
927
928         return (rc);
929 }
930
931 /* Free a piobuf sub-allocated block */
932         __checkReturn   efx_rc_t
933 ef10_nic_pio_free(
934         __inout         efx_nic_t *enp,
935         __in            uint32_t bufnum,
936         __in            uint32_t blknum)
937 {
938         uint32_t *map;
939         efx_rc_t rc;
940
941         if ((bufnum >= enp->en_arch.ef10.ena_piobuf_count) ||
942             (blknum >= (8 * sizeof (*map)))) {
943                 rc = EINVAL;
944                 goto fail1;
945         }
946
947         map = &enp->en_arch.ef10.ena_pio_alloc_map[bufnum];
948         if ((*map & (1u << blknum)) == 0) {
949                 rc = ENOENT;
950                 goto fail2;
951         }
952         *map &= ~(1u << blknum);
953
954         return (0);
955
956 fail2:
957         EFSYS_PROBE(fail2);
958 fail1:
959         EFSYS_PROBE1(fail1, efx_rc_t, rc);
960
961         return (rc);
962 }
963
964         __checkReturn   efx_rc_t
965 ef10_nic_pio_link(
966         __inout         efx_nic_t *enp,
967         __in            uint32_t vi_index,
968         __in            efx_piobuf_handle_t handle)
969 {
970         return (efx_mcdi_link_piobuf(enp, vi_index, handle));
971 }
972
973         __checkReturn   efx_rc_t
974 ef10_nic_pio_unlink(
975         __inout         efx_nic_t *enp,
976         __in            uint32_t vi_index)
977 {
978         return (efx_mcdi_unlink_piobuf(enp, vi_index));
979 }
980
981 static  __checkReturn   efx_rc_t
982 ef10_mcdi_get_pf_count(
983         __in            efx_nic_t *enp,
984         __out           uint32_t *pf_countp)
985 {
986         efx_mcdi_req_t req;
987         uint8_t payload[MAX(MC_CMD_GET_PF_COUNT_IN_LEN,
988                             MC_CMD_GET_PF_COUNT_OUT_LEN)];
989         efx_rc_t rc;
990
991         (void) memset(payload, 0, sizeof (payload));
992         req.emr_cmd = MC_CMD_GET_PF_COUNT;
993         req.emr_in_buf = payload;
994         req.emr_in_length = MC_CMD_GET_PF_COUNT_IN_LEN;
995         req.emr_out_buf = payload;
996         req.emr_out_length = MC_CMD_GET_PF_COUNT_OUT_LEN;
997
998         efx_mcdi_execute(enp, &req);
999
1000         if (req.emr_rc != 0) {
1001                 rc = req.emr_rc;
1002                 goto fail1;
1003         }
1004
1005         if (req.emr_out_length_used < MC_CMD_GET_PF_COUNT_OUT_LEN) {
1006                 rc = EMSGSIZE;
1007                 goto fail2;
1008         }
1009
1010         *pf_countp = *MCDI_OUT(req, uint8_t,
1011                                 MC_CMD_GET_PF_COUNT_OUT_PF_COUNT_OFST);
1012
1013         EFSYS_ASSERT(*pf_countp != 0);
1014
1015         return (0);
1016
1017 fail2:
1018         EFSYS_PROBE(fail2);
1019 fail1:
1020         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1021
1022         return (rc);
1023 }
1024
1025 static  __checkReturn   efx_rc_t
1026 ef10_get_datapath_caps(
1027         __in            efx_nic_t *enp)
1028 {
1029         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1030         efx_mcdi_req_t req;
1031         uint8_t payload[MAX(MC_CMD_GET_CAPABILITIES_IN_LEN,
1032                             MC_CMD_GET_CAPABILITIES_V5_OUT_LEN)];
1033         efx_rc_t rc;
1034
1035         if ((rc = ef10_mcdi_get_pf_count(enp, &encp->enc_hw_pf_count)) != 0)
1036                 goto fail1;
1037
1038
1039         (void) memset(payload, 0, sizeof (payload));
1040         req.emr_cmd = MC_CMD_GET_CAPABILITIES;
1041         req.emr_in_buf = payload;
1042         req.emr_in_length = MC_CMD_GET_CAPABILITIES_IN_LEN;
1043         req.emr_out_buf = payload;
1044         req.emr_out_length = MC_CMD_GET_CAPABILITIES_V5_OUT_LEN;
1045
1046         efx_mcdi_execute_quiet(enp, &req);
1047
1048         if (req.emr_rc != 0) {
1049                 rc = req.emr_rc;
1050                 goto fail2;
1051         }
1052
1053         if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_OUT_LEN) {
1054                 rc = EMSGSIZE;
1055                 goto fail3;
1056         }
1057
1058 #define CAP_FLAGS1(_req, _flag)                                         \
1059         (MCDI_OUT_DWORD((_req), GET_CAPABILITIES_OUT_FLAGS1) &          \
1060         (1u << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## _flag ## _LBN)))
1061
1062 #define CAP_FLAGS2(_req, _flag)                                         \
1063         (((_req).emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V2_OUT_LEN) && \
1064             (MCDI_OUT_DWORD((_req), GET_CAPABILITIES_V2_OUT_FLAGS2) &   \
1065             (1u << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## _flag ## _LBN))))
1066
1067         /*
1068          * Huntington RXDP firmware inserts a 0 or 14 byte prefix.
1069          * We only support the 14 byte prefix here.
1070          */
1071         if (CAP_FLAGS1(req, RX_PREFIX_LEN_14) == 0) {
1072                 rc = ENOTSUP;
1073                 goto fail4;
1074         }
1075         encp->enc_rx_prefix_size = 14;
1076
1077         /* Check if the firmware supports additional RSS modes */
1078         if (CAP_FLAGS1(req, ADDITIONAL_RSS_MODES))
1079                 encp->enc_rx_scale_additional_modes_supported = B_TRUE;
1080         else
1081                 encp->enc_rx_scale_additional_modes_supported = B_FALSE;
1082
1083         /* Check if the firmware supports TSO */
1084         if (CAP_FLAGS1(req, TX_TSO))
1085                 encp->enc_fw_assisted_tso_enabled = B_TRUE;
1086         else
1087                 encp->enc_fw_assisted_tso_enabled = B_FALSE;
1088
1089         /* Check if the firmware supports FATSOv2 */
1090         if (CAP_FLAGS2(req, TX_TSO_V2)) {
1091                 encp->enc_fw_assisted_tso_v2_enabled = B_TRUE;
1092                 encp->enc_fw_assisted_tso_v2_n_contexts = MCDI_OUT_WORD(req,
1093                     GET_CAPABILITIES_V2_OUT_TX_TSO_V2_N_CONTEXTS);
1094         } else {
1095                 encp->enc_fw_assisted_tso_v2_enabled = B_FALSE;
1096                 encp->enc_fw_assisted_tso_v2_n_contexts = 0;
1097         }
1098
1099         /* Check if the firmware supports FATSOv2 encap */
1100         if (CAP_FLAGS2(req, TX_TSO_V2_ENCAP))
1101                 encp->enc_fw_assisted_tso_v2_encap_enabled = B_TRUE;
1102         else
1103                 encp->enc_fw_assisted_tso_v2_encap_enabled = B_FALSE;
1104
1105         /* Check if the firmware has vadapter/vport/vswitch support */
1106         if (CAP_FLAGS1(req, EVB))
1107                 encp->enc_datapath_cap_evb = B_TRUE;
1108         else
1109                 encp->enc_datapath_cap_evb = B_FALSE;
1110
1111         /* Check if the firmware supports VLAN insertion */
1112         if (CAP_FLAGS1(req, TX_VLAN_INSERTION))
1113                 encp->enc_hw_tx_insert_vlan_enabled = B_TRUE;
1114         else
1115                 encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
1116
1117         /* Check if the firmware supports RX event batching */
1118         if (CAP_FLAGS1(req, RX_BATCHING))
1119                 encp->enc_rx_batching_enabled = B_TRUE;
1120         else
1121                 encp->enc_rx_batching_enabled = B_FALSE;
1122
1123         /*
1124          * Even if batching isn't reported as supported, we may still get
1125          * batched events.
1126          */
1127         encp->enc_rx_batch_max = 16;
1128
1129         /* Check if the firmware supports disabling scatter on RXQs */
1130         if (CAP_FLAGS1(req, RX_DISABLE_SCATTER))
1131                 encp->enc_rx_disable_scatter_supported = B_TRUE;
1132         else
1133                 encp->enc_rx_disable_scatter_supported = B_FALSE;
1134
1135         /* Check if the firmware supports packed stream mode */
1136         if (CAP_FLAGS1(req, RX_PACKED_STREAM))
1137                 encp->enc_rx_packed_stream_supported = B_TRUE;
1138         else
1139                 encp->enc_rx_packed_stream_supported = B_FALSE;
1140
1141         /*
1142          * Check if the firmware supports configurable buffer sizes
1143          * for packed stream mode (otherwise buffer size is 1Mbyte)
1144          */
1145         if (CAP_FLAGS1(req, RX_PACKED_STREAM_VAR_BUFFERS))
1146                 encp->enc_rx_var_packed_stream_supported = B_TRUE;
1147         else
1148                 encp->enc_rx_var_packed_stream_supported = B_FALSE;
1149
1150         /* Check if the firmware supports equal stride super-buffer mode */
1151         if (CAP_FLAGS2(req, EQUAL_STRIDE_SUPER_BUFFER))
1152                 encp->enc_rx_es_super_buffer_supported = B_TRUE;
1153         else
1154                 encp->enc_rx_es_super_buffer_supported = B_FALSE;
1155
1156         /* Check if the firmware supports FW subvariant w/o Tx checksumming */
1157         if (CAP_FLAGS2(req, FW_SUBVARIANT_NO_TX_CSUM))
1158                 encp->enc_fw_subvariant_no_tx_csum_supported = B_TRUE;
1159         else
1160                 encp->enc_fw_subvariant_no_tx_csum_supported = B_FALSE;
1161
1162         /* Check if the firmware supports set mac with running filters */
1163         if (CAP_FLAGS1(req, VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED))
1164                 encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
1165         else
1166                 encp->enc_allow_set_mac_with_installed_filters = B_FALSE;
1167
1168         /*
1169          * Check if firmware supports the extended MC_CMD_SET_MAC, which allows
1170          * specifying which parameters to configure.
1171          */
1172         if (CAP_FLAGS1(req, SET_MAC_ENHANCED))
1173                 encp->enc_enhanced_set_mac_supported = B_TRUE;
1174         else
1175                 encp->enc_enhanced_set_mac_supported = B_FALSE;
1176
1177         /*
1178          * Check if firmware supports version 2 of MC_CMD_INIT_EVQ, which allows
1179          * us to let the firmware choose the settings to use on an EVQ.
1180          */
1181         if (CAP_FLAGS2(req, INIT_EVQ_V2))
1182                 encp->enc_init_evq_v2_supported = B_TRUE;
1183         else
1184                 encp->enc_init_evq_v2_supported = B_FALSE;
1185
1186         /*
1187          * Check if firmware-verified NVRAM updates must be used.
1188          *
1189          * The firmware trusted installer requires all NVRAM updates to use
1190          * version 2 of MC_CMD_NVRAM_UPDATE_START (to enable verified update)
1191          * and version 2 of MC_CMD_NVRAM_UPDATE_FINISH (to verify the updated
1192          * partition and report the result).
1193          */
1194         if (CAP_FLAGS2(req, NVRAM_UPDATE_REPORT_VERIFY_RESULT))
1195                 encp->enc_nvram_update_verify_result_supported = B_TRUE;
1196         else
1197                 encp->enc_nvram_update_verify_result_supported = B_FALSE;
1198
1199         /*
1200          * Check if firmware provides packet memory and Rx datapath
1201          * counters.
1202          */
1203         if (CAP_FLAGS1(req, PM_AND_RXDP_COUNTERS))
1204                 encp->enc_pm_and_rxdp_counters = B_TRUE;
1205         else
1206                 encp->enc_pm_and_rxdp_counters = B_FALSE;
1207
1208         /*
1209          * Check if the 40G MAC hardware is capable of reporting
1210          * statistics for Tx size bins.
1211          */
1212         if (CAP_FLAGS2(req, MAC_STATS_40G_TX_SIZE_BINS))
1213                 encp->enc_mac_stats_40g_tx_size_bins = B_TRUE;
1214         else
1215                 encp->enc_mac_stats_40g_tx_size_bins = B_FALSE;
1216
1217         /*
1218          * Check if firmware supports VXLAN and NVGRE tunnels.
1219          * The capability indicates Geneve protocol support as well.
1220          */
1221         if (CAP_FLAGS1(req, VXLAN_NVGRE)) {
1222                 encp->enc_tunnel_encapsulations_supported =
1223                     (1u << EFX_TUNNEL_PROTOCOL_VXLAN) |
1224                     (1u << EFX_TUNNEL_PROTOCOL_GENEVE) |
1225                     (1u << EFX_TUNNEL_PROTOCOL_NVGRE);
1226
1227                 EFX_STATIC_ASSERT(EFX_TUNNEL_MAXNENTRIES ==
1228                     MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_ENTRIES_MAXNUM);
1229                 encp->enc_tunnel_config_udp_entries_max =
1230                     EFX_TUNNEL_MAXNENTRIES;
1231         } else {
1232                 encp->enc_tunnel_config_udp_entries_max = 0;
1233         }
1234
1235         /*
1236          * Check if firmware reports the VI window mode.
1237          * Medford2 has a variable VI window size (8K, 16K or 64K).
1238          * Medford and Huntington have a fixed 8K VI window size.
1239          */
1240         if (req.emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V3_OUT_LEN) {
1241                 uint8_t mode =
1242                     MCDI_OUT_BYTE(req, GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE);
1243
1244                 switch (mode) {
1245                 case MC_CMD_GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE_8K:
1246                         encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_8K;
1247                         break;
1248                 case MC_CMD_GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE_16K:
1249                         encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_16K;
1250                         break;
1251                 case MC_CMD_GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE_64K:
1252                         encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_64K;
1253                         break;
1254                 default:
1255                         encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_INVALID;
1256                         break;
1257                 }
1258         } else if ((enp->en_family == EFX_FAMILY_HUNTINGTON) ||
1259                     (enp->en_family == EFX_FAMILY_MEDFORD)) {
1260                 /* Huntington and Medford have fixed 8K window size */
1261                 encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_8K;
1262         } else {
1263                 encp->enc_vi_window_shift = EFX_VI_WINDOW_SHIFT_INVALID;
1264         }
1265
1266         /* Check if firmware supports extended MAC stats. */
1267         if (req.emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V4_OUT_LEN) {
1268                 /* Extended stats buffer supported */
1269                 encp->enc_mac_stats_nstats = MCDI_OUT_WORD(req,
1270                     GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS);
1271         } else {
1272                 /* Use Siena-compatible legacy MAC stats */
1273                 encp->enc_mac_stats_nstats = MC_CMD_MAC_NSTATS;
1274         }
1275
1276         if (encp->enc_mac_stats_nstats >= MC_CMD_MAC_NSTATS_V2)
1277                 encp->enc_fec_counters = B_TRUE;
1278         else
1279                 encp->enc_fec_counters = B_FALSE;
1280
1281         /* Check if the firmware provides head-of-line blocking counters */
1282         if (CAP_FLAGS2(req, RXDP_HLB_IDLE))
1283                 encp->enc_hlb_counters = B_TRUE;
1284         else
1285                 encp->enc_hlb_counters = B_FALSE;
1286
1287         if (CAP_FLAGS1(req, RX_RSS_LIMITED)) {
1288                 /* Only one exclusive RSS context is available per port. */
1289                 encp->enc_rx_scale_max_exclusive_contexts = 1;
1290
1291                 switch (enp->en_family) {
1292                 case EFX_FAMILY_MEDFORD2:
1293                         encp->enc_rx_scale_hash_alg_mask =
1294                             (1U << EFX_RX_HASHALG_TOEPLITZ);
1295                         break;
1296
1297                 case EFX_FAMILY_MEDFORD:
1298                 case EFX_FAMILY_HUNTINGTON:
1299                         /*
1300                          * Packed stream firmware variant maintains a
1301                          * non-standard algorithm for hash computation.
1302                          * It implies explicit XORing together
1303                          * source + destination IP addresses (or last
1304                          * four bytes in the case of IPv6) and using the
1305                          * resulting value as the input to a Toeplitz hash.
1306                          */
1307                         encp->enc_rx_scale_hash_alg_mask =
1308                             (1U << EFX_RX_HASHALG_PACKED_STREAM);
1309                         break;
1310
1311                 default:
1312                         rc = EINVAL;
1313                         goto fail5;
1314                 }
1315
1316                 /* Port numbers cannot contribute to the hash value */
1317                 encp->enc_rx_scale_l4_hash_supported = B_FALSE;
1318         } else {
1319                 /*
1320                  * Maximum number of exclusive RSS contexts.
1321                  * EF10 hardware supports 64 in total, but 6 are reserved
1322                  * for shared contexts. They are a global resource so
1323                  * not all may be available.
1324                  */
1325                 encp->enc_rx_scale_max_exclusive_contexts = 64 - 6;
1326
1327                 encp->enc_rx_scale_hash_alg_mask =
1328                     (1U << EFX_RX_HASHALG_TOEPLITZ);
1329
1330                 /*
1331                  * It is possible to use port numbers as
1332                  * the input data for hash computation.
1333                  */
1334                 encp->enc_rx_scale_l4_hash_supported = B_TRUE;
1335         }
1336         /* Check if the firmware supports "FLAG" and "MARK" filter actions */
1337         if (CAP_FLAGS2(req, FILTER_ACTION_FLAG))
1338                 encp->enc_filter_action_flag_supported = B_TRUE;
1339         else
1340                 encp->enc_filter_action_flag_supported = B_FALSE;
1341
1342         if (CAP_FLAGS2(req, FILTER_ACTION_MARK))
1343                 encp->enc_filter_action_mark_supported = B_TRUE;
1344         else
1345                 encp->enc_filter_action_mark_supported = B_FALSE;
1346
1347         /* Get maximum supported value for "MARK" filter action */
1348         if (req.emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V5_OUT_LEN)
1349                 encp->enc_filter_action_mark_max = MCDI_OUT_DWORD(req,
1350                     GET_CAPABILITIES_V5_OUT_FILTER_ACTION_MARK_MAX);
1351         else
1352                 encp->enc_filter_action_mark_max = 0;
1353
1354 #undef CAP_FLAGS1
1355 #undef CAP_FLAGS2
1356
1357         return (0);
1358
1359 fail5:
1360         EFSYS_PROBE(fail5);
1361 fail4:
1362         EFSYS_PROBE(fail4);
1363 fail3:
1364         EFSYS_PROBE(fail3);
1365 fail2:
1366         EFSYS_PROBE(fail2);
1367 fail1:
1368         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1369
1370         return (rc);
1371 }
1372
1373
1374 #define EF10_LEGACY_PF_PRIVILEGE_MASK                                   \
1375         (MC_CMD_PRIVILEGE_MASK_IN_GRP_ADMIN                     |       \
1376         MC_CMD_PRIVILEGE_MASK_IN_GRP_LINK                       |       \
1377         MC_CMD_PRIVILEGE_MASK_IN_GRP_ONLOAD                     |       \
1378         MC_CMD_PRIVILEGE_MASK_IN_GRP_PTP                        |       \
1379         MC_CMD_PRIVILEGE_MASK_IN_GRP_INSECURE_FILTERS           |       \
1380         MC_CMD_PRIVILEGE_MASK_IN_GRP_MAC_SPOOFING               |       \
1381         MC_CMD_PRIVILEGE_MASK_IN_GRP_UNICAST                    |       \
1382         MC_CMD_PRIVILEGE_MASK_IN_GRP_MULTICAST                  |       \
1383         MC_CMD_PRIVILEGE_MASK_IN_GRP_BROADCAST                  |       \
1384         MC_CMD_PRIVILEGE_MASK_IN_GRP_ALL_MULTICAST              |       \
1385         MC_CMD_PRIVILEGE_MASK_IN_GRP_PROMISCUOUS)
1386
1387 #define EF10_LEGACY_VF_PRIVILEGE_MASK   0
1388
1389
1390         __checkReturn           efx_rc_t
1391 ef10_get_privilege_mask(
1392         __in                    efx_nic_t *enp,
1393         __out                   uint32_t *maskp)
1394 {
1395         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1396         uint32_t mask;
1397         efx_rc_t rc;
1398
1399         if ((rc = efx_mcdi_privilege_mask(enp, encp->enc_pf, encp->enc_vf,
1400                                             &mask)) != 0) {
1401                 if (rc != ENOTSUP)
1402                         goto fail1;
1403
1404                 /* Fallback for old firmware without privilege mask support */
1405                 if (EFX_PCI_FUNCTION_IS_PF(encp)) {
1406                         /* Assume PF has admin privilege */
1407                         mask = EF10_LEGACY_PF_PRIVILEGE_MASK;
1408                 } else {
1409                         /* VF is always unprivileged by default */
1410                         mask = EF10_LEGACY_VF_PRIVILEGE_MASK;
1411                 }
1412         }
1413
1414         *maskp = mask;
1415
1416         return (0);
1417
1418 fail1:
1419         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1420
1421         return (rc);
1422 }
1423
1424
1425 /*
1426  * Table of mapping schemes from port number to external number.
1427  *
1428  * Each port number ultimately corresponds to a connector: either as part of
1429  * a cable assembly attached to a module inserted in an SFP+/QSFP+ cage on
1430  * the board, or fixed to the board (e.g. 10GBASE-T magjack on SFN5121T
1431  * "Salina"). In general:
1432  *
1433  * Port number (0-based)
1434  *     |
1435  *   port mapping (n:1)
1436  *     |
1437  *     v
1438  * External port number (normally 1-based)
1439  *     |
1440  *   fixed (1:1) or cable assembly (1:m)
1441  *     |
1442  *     v
1443  * Connector
1444  *
1445  * The external numbering refers to the cages or magjacks on the board,
1446  * as visibly annotated on the board or back panel. This table describes
1447  * how to determine which external cage/magjack corresponds to the port
1448  * numbers used by the driver.
1449  *
1450  * The count of adjacent port numbers that map to each external number,
1451  * and the offset in the numbering, is determined by the chip family and
1452  * current port mode.
1453  *
1454  * For the Huntington family, the current port mode cannot be discovered,
1455  * but a single mapping is used by all modes for a given chip variant,
1456  * so the mapping used is instead the last match in the table to the full
1457  * set of port modes to which the NIC can be configured. Therefore the
1458  * ordering of entries in the mapping table is significant.
1459  */
1460 static struct ef10_external_port_map_s {
1461         efx_family_t    family;
1462         uint32_t        modes_mask;
1463         int32_t         count;
1464         int32_t         offset;
1465 }       __ef10_external_port_mappings[] = {
1466         /*
1467          * Modes used by Huntington family controllers where each port
1468          * number maps to a separate cage.
1469          * SFN7x22F (Torino):
1470          *      port 0 -> cage 1
1471          *      port 1 -> cage 2
1472          * SFN7xx4F (Pavia):
1473          *      port 0 -> cage 1
1474          *      port 1 -> cage 2
1475          *      port 2 -> cage 3
1476          *      port 3 -> cage 4
1477          */
1478         {
1479                 EFX_FAMILY_HUNTINGTON,
1480                 (1U << TLV_PORT_MODE_10G) |                     /* mode 0 */
1481                 (1U << TLV_PORT_MODE_10G_10G) |                 /* mode 2 */
1482                 (1U << TLV_PORT_MODE_10G_10G_10G_10G),          /* mode 4 */
1483                 1,      /* ports per cage */
1484                 1       /* first cage */
1485         },
1486         /*
1487          * Modes which for Huntington identify a chip variant where 2
1488          * adjacent port numbers map to each cage.
1489          * SFN7x42Q (Monza):
1490          *      port 0 -> cage 1
1491          *      port 1 -> cage 1
1492          *      port 2 -> cage 2
1493          *      port 3 -> cage 2
1494          */
1495         {
1496                 EFX_FAMILY_HUNTINGTON,
1497                 (1U << TLV_PORT_MODE_40G) |                     /* mode 1 */
1498                 (1U << TLV_PORT_MODE_40G_40G) |                 /* mode 3 */
1499                 (1U << TLV_PORT_MODE_40G_10G_10G) |             /* mode 6 */
1500                 (1U << TLV_PORT_MODE_10G_10G_40G),              /* mode 7 */
1501                 2,      /* ports per cage */
1502                 1       /* first cage */
1503         },
1504         /*
1505          * Modes that on Medford allocate each port number to a separate
1506          * cage.
1507          *      port 0 -> cage 1
1508          *      port 1 -> cage 2
1509          *      port 2 -> cage 3
1510          *      port 3 -> cage 4
1511          */
1512         {
1513                 EFX_FAMILY_MEDFORD,
1514                 (1U << TLV_PORT_MODE_10G) |                     /* mode 0 */
1515                 (1U << TLV_PORT_MODE_10G_10G),                  /* mode 2 */
1516                 1,      /* ports per cage */
1517                 1       /* first cage */
1518         },
1519         /*
1520          * Modes that on Medford allocate 2 adjacent port numbers to each
1521          * cage.
1522          *      port 0 -> cage 1
1523          *      port 1 -> cage 1
1524          *      port 2 -> cage 2
1525          *      port 3 -> cage 2
1526          */
1527         {
1528                 EFX_FAMILY_MEDFORD,
1529                 (1U << TLV_PORT_MODE_40G) |                     /* mode 1 */
1530                 (1U << TLV_PORT_MODE_40G_40G) |                 /* mode 3 */
1531                 (1U << TLV_PORT_MODE_40G_10G_10G) |             /* mode 6 */
1532                 (1U << TLV_PORT_MODE_10G_10G_40G) |             /* mode 7 */
1533                 /* Do not use 10G_10G_10G_10G_Q1_Q2 (see bug63270) */
1534                 (1U << TLV_PORT_MODE_10G_10G_10G_10G_Q1_Q2),    /* mode 9 */
1535                 2,      /* ports per cage */
1536                 1       /* first cage */
1537         },
1538         /*
1539          * Modes that on Medford allocate 4 adjacent port numbers to each
1540          * connector, starting on cage 1.
1541          *      port 0 -> cage 1
1542          *      port 1 -> cage 1
1543          *      port 2 -> cage 1
1544          *      port 3 -> cage 1
1545          */
1546         {
1547                 EFX_FAMILY_MEDFORD,
1548                 (1U << TLV_PORT_MODE_10G_10G_10G_10G_Q) |       /* mode 5 */
1549                 /* Do not use 10G_10G_10G_10G_Q1 (see bug63270) */
1550                 (1U << TLV_PORT_MODE_10G_10G_10G_10G_Q1),       /* mode 4 */
1551                 4,      /* ports per cage */
1552                 1       /* first cage */
1553         },
1554         /*
1555          * Modes that on Medford allocate 4 adjacent port numbers to each
1556          * connector, starting on cage 2.
1557          *      port 0 -> cage 2
1558          *      port 1 -> cage 2
1559          *      port 2 -> cage 2
1560          *      port 3 -> cage 2
1561          */
1562         {
1563                 EFX_FAMILY_MEDFORD,
1564                 (1U << TLV_PORT_MODE_10G_10G_10G_10G_Q2),       /* mode 8 */
1565                 4,      /* ports per cage */
1566                 2       /* first cage */
1567         },
1568         /*
1569          * Modes that on Medford2 allocate each port number to a separate
1570          * cage.
1571          *      port 0 -> cage 1
1572          *      port 1 -> cage 2
1573          *      port 2 -> cage 3
1574          *      port 3 -> cage 4
1575          */
1576         {
1577                 EFX_FAMILY_MEDFORD2,
1578                 (1U << TLV_PORT_MODE_1x1_NA) |                  /* mode 0 */
1579                 (1U << TLV_PORT_MODE_1x4_NA) |                  /* mode 1 */
1580                 (1U << TLV_PORT_MODE_1x1_1x1) |                 /* mode 2 */
1581                 (1U << TLV_PORT_MODE_1x2_NA) |                  /* mode 10 */
1582                 (1U << TLV_PORT_MODE_1x2_1x2) |                 /* mode 12 */
1583                 (1U << TLV_PORT_MODE_1x4_1x2) |                 /* mode 15 */
1584                 (1U << TLV_PORT_MODE_1x2_1x4),                  /* mode 16 */
1585                 1,      /* ports per cage */
1586                 1       /* first cage */
1587         },
1588         /*
1589          * FIXME: Some port modes are not representable in this mapping:
1590          *  - TLV_PORT_MODE_1x2_2x1 (mode 17):
1591          *      port 0 -> cage 1
1592          *      port 1 -> cage 2
1593          *      port 2 -> cage 2
1594          */
1595         /*
1596          * Modes that on Medford2 allocate 2 adjacent port numbers to each
1597          * cage, starting on cage 1.
1598          *      port 0 -> cage 1
1599          *      port 1 -> cage 1
1600          *      port 2 -> cage 2
1601          *      port 3 -> cage 2
1602          */
1603         {
1604                 EFX_FAMILY_MEDFORD2,
1605                 (1U << TLV_PORT_MODE_1x4_1x4) |                 /* mode 3 */
1606                 (1U << TLV_PORT_MODE_2x1_2x1) |                 /* mode 4 */
1607                 (1U << TLV_PORT_MODE_1x4_2x1) |                 /* mode 6 */
1608                 (1U << TLV_PORT_MODE_2x1_1x4) |                 /* mode 7 */
1609                 (1U << TLV_PORT_MODE_2x2_NA) |                  /* mode 13 */
1610                 (1U << TLV_PORT_MODE_2x1_1x2),                  /* mode 18 */
1611                 2,      /* ports per cage */
1612                 1       /* first cage */
1613         },
1614         /*
1615          * Modes that on Medford2 allocate 2 adjacent port numbers to each
1616          * cage, starting on cage 2.
1617          *      port 0 -> cage 2
1618          *      port 1 -> cage 2
1619          */
1620         {
1621                 EFX_FAMILY_MEDFORD2,
1622                 (1U << TLV_PORT_MODE_NA_2x2),                   /* mode 14 */
1623                 2,      /* ports per cage */
1624                 2       /* first cage */
1625         },
1626         /*
1627          * Modes that on Medford2 allocate 4 adjacent port numbers to each
1628          * connector, starting on cage 1.
1629          *      port 0 -> cage 1
1630          *      port 1 -> cage 1
1631          *      port 2 -> cage 1
1632          *      port 3 -> cage 1
1633          */
1634         {
1635                 EFX_FAMILY_MEDFORD2,
1636                 (1U << TLV_PORT_MODE_4x1_NA),                   /* mode 5 */
1637                 4,      /* ports per cage */
1638                 1       /* first cage */
1639         },
1640         /*
1641          * Modes that on Medford2 allocate 4 adjacent port numbers to each
1642          * connector, starting on cage 2.
1643          *      port 0 -> cage 2
1644          *      port 1 -> cage 2
1645          *      port 2 -> cage 2
1646          *      port 3 -> cage 2
1647          */
1648         {
1649                 EFX_FAMILY_MEDFORD2,
1650                 (1U << TLV_PORT_MODE_NA_4x1) |                  /* mode 8 */
1651                 (1U << TLV_PORT_MODE_NA_1x2),                   /* mode 11 */
1652                 4,      /* ports per cage */
1653                 2       /* first cage */
1654         },
1655 };
1656
1657 static  __checkReturn   efx_rc_t
1658 ef10_external_port_mapping(
1659         __in            efx_nic_t *enp,
1660         __in            uint32_t port,
1661         __out           uint8_t *external_portp)
1662 {
1663         efx_rc_t rc;
1664         int i;
1665         uint32_t port_modes;
1666         uint32_t matches;
1667         uint32_t current;
1668         int32_t count = 1; /* Default 1-1 mapping */
1669         int32_t offset = 1; /* Default starting external port number */
1670
1671         if ((rc = efx_mcdi_get_port_modes(enp, &port_modes, &current,
1672                     NULL)) != 0) {
1673                 /*
1674                  * No current port mode information (i.e. Huntington)
1675                  * - infer mapping from available modes
1676                  */
1677                 if ((rc = efx_mcdi_get_port_modes(enp,
1678                             &port_modes, NULL, NULL)) != 0) {
1679                         /*
1680                          * No port mode information available
1681                          * - use default mapping
1682                          */
1683                         goto out;
1684                 }
1685         } else {
1686                 /* Only need to scan the current mode */
1687                 port_modes = 1 << current;
1688         }
1689
1690         /*
1691          * Infer the internal port -> external number mapping from
1692          * the possible port modes for this NIC.
1693          */
1694         for (i = 0; i < EFX_ARRAY_SIZE(__ef10_external_port_mappings); ++i) {
1695                 struct ef10_external_port_map_s *eepmp =
1696                     &__ef10_external_port_mappings[i];
1697                 if (eepmp->family != enp->en_family)
1698                         continue;
1699                 matches = (eepmp->modes_mask & port_modes);
1700                 if (matches != 0) {
1701                         /*
1702                          * Some modes match. For some Huntington boards
1703                          * there will be multiple matches. The mapping on the
1704                          * last match is used.
1705                          */
1706                         count = eepmp->count;
1707                         offset = eepmp->offset;
1708                         port_modes &= ~matches;
1709                 }
1710         }
1711
1712         if (port_modes != 0) {
1713                 /* Some advertised modes are not supported */
1714                 rc = ENOTSUP;
1715                 goto fail1;
1716         }
1717
1718 out:
1719         /*
1720          * Scale as required by last matched mode and then convert to
1721          * correctly offset numbering
1722          */
1723         *external_portp = (uint8_t)((port / count) + offset);
1724         return (0);
1725
1726 fail1:
1727         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1728
1729         return (rc);
1730 }
1731
1732 static  __checkReturn   efx_rc_t
1733 ef10_nic_board_cfg(
1734         __in            efx_nic_t *enp)
1735 {
1736         const efx_nic_ops_t *enop = enp->en_enop;
1737         efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
1738         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1739         ef10_link_state_t els;
1740         efx_port_t *epp = &(enp->en_port);
1741         uint32_t board_type = 0;
1742         uint32_t base, nvec;
1743         uint32_t port;
1744         uint32_t mask;
1745         uint32_t pf;
1746         uint32_t vf;
1747         uint8_t mac_addr[6] = { 0 };
1748         efx_rc_t rc;
1749
1750         /* Get the (zero-based) MCDI port number */
1751         if ((rc = efx_mcdi_get_port_assignment(enp, &port)) != 0)
1752                 goto fail1;
1753
1754         /* EFX MCDI interface uses one-based port numbers */
1755         emip->emi_port = port + 1;
1756
1757         if ((rc = ef10_external_port_mapping(enp, port,
1758                     &encp->enc_external_port)) != 0)
1759                 goto fail2;
1760
1761         /*
1762          * Get PCIe function number from firmware (used for
1763          * per-function privilege and dynamic config info).
1764          *  - PCIe PF: pf = PF number, vf = 0xffff.
1765          *  - PCIe VF: pf = parent PF, vf = VF number.
1766          */
1767         if ((rc = efx_mcdi_get_function_info(enp, &pf, &vf)) != 0)
1768                 goto fail3;
1769
1770         encp->enc_pf = pf;
1771         encp->enc_vf = vf;
1772
1773         /* MAC address for this function */
1774         if (EFX_PCI_FUNCTION_IS_PF(encp)) {
1775                 rc = efx_mcdi_get_mac_address_pf(enp, mac_addr);
1776 #if EFSYS_OPT_ALLOW_UNCONFIGURED_NIC
1777                 /*
1778                  * Disable static config checking, ONLY for manufacturing test
1779                  * and setup at the factory, to allow the static config to be
1780                  * installed.
1781                  */
1782 #else /* EFSYS_OPT_ALLOW_UNCONFIGURED_NIC */
1783                 if ((rc == 0) && (mac_addr[0] & 0x02)) {
1784                         /*
1785                          * If the static config does not include a global MAC
1786                          * address pool then the board may return a locally
1787                          * administered MAC address (this should only happen on
1788                          * incorrectly programmed boards).
1789                          */
1790                         rc = EINVAL;
1791                 }
1792 #endif /* EFSYS_OPT_ALLOW_UNCONFIGURED_NIC */
1793         } else {
1794                 rc = efx_mcdi_get_mac_address_vf(enp, mac_addr);
1795         }
1796         if (rc != 0)
1797                 goto fail4;
1798
1799         EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
1800
1801         /* Board configuration (legacy) */
1802         rc = efx_mcdi_get_board_cfg(enp, &board_type, NULL, NULL);
1803         if (rc != 0) {
1804                 /* Unprivileged functions may not be able to read board cfg */
1805                 if (rc == EACCES)
1806                         board_type = 0;
1807                 else
1808                         goto fail5;
1809         }
1810
1811         encp->enc_board_type = board_type;
1812         encp->enc_clk_mult = 1; /* not used for EF10 */
1813
1814         /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
1815         if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
1816                 goto fail6;
1817
1818         /* Obtain the default PHY advertised capabilities */
1819         if ((rc = ef10_phy_get_link(enp, &els)) != 0)
1820                 goto fail7;
1821         epp->ep_default_adv_cap_mask = els.els_adv_cap_mask;
1822         epp->ep_adv_cap_mask = els.els_adv_cap_mask;
1823
1824         /* Check capabilities of running datapath firmware */
1825         if ((rc = ef10_get_datapath_caps(enp)) != 0)
1826                 goto fail8;
1827
1828         /* Alignment for WPTR updates */
1829         encp->enc_rx_push_align = EF10_RX_WPTR_ALIGN;
1830
1831         encp->enc_tx_dma_desc_size_max = EFX_MASK32(ESF_DZ_RX_KER_BYTE_CNT);
1832         /* No boundary crossing limits */
1833         encp->enc_tx_dma_desc_boundary = 0;
1834
1835         /*
1836          * Maximum number of bytes into the frame the TCP header can start for
1837          * firmware assisted TSO to work.
1838          */
1839         encp->enc_tx_tso_tcp_header_offset_limit = EF10_TCP_HEADER_OFFSET_LIMIT;
1840
1841         /*
1842          * Set resource limits for MC_CMD_ALLOC_VIS. Note that we cannot use
1843          * MC_CMD_GET_RESOURCE_LIMITS here as that reports the available
1844          * resources (allocated to this PCIe function), which is zero until
1845          * after we have allocated VIs.
1846          */
1847         encp->enc_evq_limit = 1024;
1848         encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
1849         encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
1850
1851         encp->enc_buftbl_limit = 0xFFFFFFFF;
1852
1853         /* Get interrupt vector limits */
1854         if ((rc = efx_mcdi_get_vector_cfg(enp, &base, &nvec, NULL)) != 0) {
1855                 if (EFX_PCI_FUNCTION_IS_PF(encp))
1856                         goto fail9;
1857
1858                 /* Ignore error (cannot query vector limits from a VF). */
1859                 base = 0;
1860                 nvec = 1024;
1861         }
1862         encp->enc_intr_vec_base = base;
1863         encp->enc_intr_limit = nvec;
1864
1865         /*
1866          * Get the current privilege mask. Note that this may be modified
1867          * dynamically, so this value is informational only. DO NOT use
1868          * the privilege mask to check for sufficient privileges, as that
1869          * can result in time-of-check/time-of-use bugs.
1870          */
1871         if ((rc = ef10_get_privilege_mask(enp, &mask)) != 0)
1872                 goto fail10;
1873         encp->enc_privilege_mask = mask;
1874
1875         /* Get remaining controller-specific board config */
1876         if ((rc = enop->eno_board_cfg(enp)) != 0)
1877                 if (rc != EACCES)
1878                         goto fail11;
1879
1880         return (0);
1881
1882 fail11:
1883         EFSYS_PROBE(fail11);
1884 fail10:
1885         EFSYS_PROBE(fail10);
1886 fail9:
1887         EFSYS_PROBE(fail9);
1888 fail8:
1889         EFSYS_PROBE(fail8);
1890 fail7:
1891         EFSYS_PROBE(fail7);
1892 fail6:
1893         EFSYS_PROBE(fail6);
1894 fail5:
1895         EFSYS_PROBE(fail5);
1896 fail4:
1897         EFSYS_PROBE(fail4);
1898 fail3:
1899         EFSYS_PROBE(fail3);
1900 fail2:
1901         EFSYS_PROBE(fail2);
1902 fail1:
1903         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1904
1905         return (rc);
1906 }
1907
1908         __checkReturn   efx_rc_t
1909 ef10_nic_probe(
1910         __in            efx_nic_t *enp)
1911 {
1912         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1913         efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1914         efx_rc_t rc;
1915
1916         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1917             enp->en_family == EFX_FAMILY_MEDFORD ||
1918             enp->en_family == EFX_FAMILY_MEDFORD2);
1919
1920         /* Read and clear any assertion state */
1921         if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1922                 goto fail1;
1923
1924         /* Exit the assertion handler */
1925         if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1926                 if (rc != EACCES)
1927                         goto fail2;
1928
1929         if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
1930                 goto fail3;
1931
1932         if ((rc = ef10_nic_board_cfg(enp)) != 0)
1933                 goto fail4;
1934
1935         /*
1936          * Set default driver config limits (based on board config).
1937          *
1938          * FIXME: For now allocate a fixed number of VIs which is likely to be
1939          * sufficient and small enough to allow multiple functions on the same
1940          * port.
1941          */
1942         edcp->edc_min_vi_count = edcp->edc_max_vi_count =
1943             MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit));
1944
1945         /* The client driver must configure and enable PIO buffer support */
1946         edcp->edc_max_piobuf_count = 0;
1947         edcp->edc_pio_alloc_size = 0;
1948
1949 #if EFSYS_OPT_MAC_STATS
1950         /* Wipe the MAC statistics */
1951         if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
1952                 goto fail5;
1953 #endif
1954
1955 #if EFSYS_OPT_LOOPBACK
1956         if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
1957                 goto fail6;
1958 #endif
1959
1960 #if EFSYS_OPT_MON_STATS
1961         if ((rc = mcdi_mon_cfg_build(enp)) != 0) {
1962                 /* Unprivileged functions do not have access to sensors */
1963                 if (rc != EACCES)
1964                         goto fail7;
1965         }
1966 #endif
1967
1968         encp->enc_features = enp->en_features;
1969
1970         return (0);
1971
1972 #if EFSYS_OPT_MON_STATS
1973 fail7:
1974         EFSYS_PROBE(fail7);
1975 #endif
1976 #if EFSYS_OPT_LOOPBACK
1977 fail6:
1978         EFSYS_PROBE(fail6);
1979 #endif
1980 #if EFSYS_OPT_MAC_STATS
1981 fail5:
1982         EFSYS_PROBE(fail5);
1983 #endif
1984 fail4:
1985         EFSYS_PROBE(fail4);
1986 fail3:
1987         EFSYS_PROBE(fail3);
1988 fail2:
1989         EFSYS_PROBE(fail2);
1990 fail1:
1991         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1992
1993         return (rc);
1994 }
1995
1996         __checkReturn   efx_rc_t
1997 ef10_nic_set_drv_limits(
1998         __inout         efx_nic_t *enp,
1999         __in            efx_drv_limits_t *edlp)
2000 {
2001         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
2002         efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
2003         uint32_t min_evq_count, max_evq_count;
2004         uint32_t min_rxq_count, max_rxq_count;
2005         uint32_t min_txq_count, max_txq_count;
2006         efx_rc_t rc;
2007
2008         if (edlp == NULL) {
2009                 rc = EINVAL;
2010                 goto fail1;
2011         }
2012
2013         /* Get minimum required and maximum usable VI limits */
2014         min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit);
2015         min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit);
2016         min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit);
2017
2018         edcp->edc_min_vi_count =
2019             MAX(min_evq_count, MAX(min_rxq_count, min_txq_count));
2020
2021         max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit);
2022         max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit);
2023         max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit);
2024
2025         edcp->edc_max_vi_count =
2026             MAX(max_evq_count, MAX(max_rxq_count, max_txq_count));
2027
2028         /*
2029          * Check limits for sub-allocated piobuf blocks.
2030          * PIO is optional, so don't fail if the limits are incorrect.
2031          */
2032         if ((encp->enc_piobuf_size == 0) ||
2033             (encp->enc_piobuf_limit == 0) ||
2034             (edlp->edl_min_pio_alloc_size == 0) ||
2035             (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) {
2036                 /* Disable PIO */
2037                 edcp->edc_max_piobuf_count = 0;
2038                 edcp->edc_pio_alloc_size = 0;
2039         } else {
2040                 uint32_t blk_size, blk_count, blks_per_piobuf;
2041
2042                 blk_size =
2043                     MAX(edlp->edl_min_pio_alloc_size,
2044                             encp->enc_piobuf_min_alloc_size);
2045
2046                 blks_per_piobuf = encp->enc_piobuf_size / blk_size;
2047                 EFSYS_ASSERT3U(blks_per_piobuf, <=, 32);
2048
2049                 blk_count = (encp->enc_piobuf_limit * blks_per_piobuf);
2050
2051                 /* A zero max pio alloc count means unlimited */
2052                 if ((edlp->edl_max_pio_alloc_count > 0) &&
2053                     (edlp->edl_max_pio_alloc_count < blk_count)) {
2054                         blk_count = edlp->edl_max_pio_alloc_count;
2055                 }
2056
2057                 edcp->edc_pio_alloc_size = blk_size;
2058                 edcp->edc_max_piobuf_count =
2059                     (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf;
2060         }
2061
2062         return (0);
2063
2064 fail1:
2065         EFSYS_PROBE1(fail1, efx_rc_t, rc);
2066
2067         return (rc);
2068 }
2069
2070
2071         __checkReturn   efx_rc_t
2072 ef10_nic_reset(
2073         __in            efx_nic_t *enp)
2074 {
2075         efx_mcdi_req_t req;
2076         uint8_t payload[MAX(MC_CMD_ENTITY_RESET_IN_LEN,
2077                             MC_CMD_ENTITY_RESET_OUT_LEN)];
2078         efx_rc_t rc;
2079
2080         /* ef10_nic_reset() is called to recover from BADASSERT failures. */
2081         if ((rc = efx_mcdi_read_assertion(enp)) != 0)
2082                 goto fail1;
2083         if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
2084                 goto fail2;
2085
2086         (void) memset(payload, 0, sizeof (payload));
2087         req.emr_cmd = MC_CMD_ENTITY_RESET;
2088         req.emr_in_buf = payload;
2089         req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN;
2090         req.emr_out_buf = payload;
2091         req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN;
2092
2093         MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG,
2094             ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1);
2095
2096         efx_mcdi_execute(enp, &req);
2097
2098         if (req.emr_rc != 0) {
2099                 rc = req.emr_rc;
2100                 goto fail3;
2101         }
2102
2103         /* Clear RX/TX DMA queue errors */
2104         enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR);
2105
2106         return (0);
2107
2108 fail3:
2109         EFSYS_PROBE(fail3);
2110 fail2:
2111         EFSYS_PROBE(fail2);
2112 fail1:
2113         EFSYS_PROBE1(fail1, efx_rc_t, rc);
2114
2115         return (rc);
2116 }
2117
2118         __checkReturn   efx_rc_t
2119 ef10_nic_init(
2120         __in            efx_nic_t *enp)
2121 {
2122         efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
2123         uint32_t min_vi_count, max_vi_count;
2124         uint32_t vi_count, vi_base, vi_shift;
2125         uint32_t i;
2126         uint32_t retry;
2127         uint32_t delay_us;
2128         uint32_t vi_window_size;
2129         efx_rc_t rc;
2130
2131         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
2132             enp->en_family == EFX_FAMILY_MEDFORD ||
2133             enp->en_family == EFX_FAMILY_MEDFORD2);
2134
2135         /* Enable reporting of some events (e.g. link change) */
2136         if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
2137                 goto fail1;
2138
2139         /* Allocate (optional) on-chip PIO buffers */
2140         ef10_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count);
2141
2142         /*
2143          * For best performance, PIO writes should use a write-combined
2144          * (WC) memory mapping. Using a separate WC mapping for the PIO
2145          * aperture of each VI would be a burden to drivers (and not
2146          * possible if the host page size is >4Kbyte).
2147          *
2148          * To avoid this we use a single uncached (UC) mapping for VI
2149          * register access, and a single WC mapping for extra VIs used
2150          * for PIO writes.
2151          *
2152          * Each piobuf must be linked to a VI in the WC mapping, and to
2153          * each VI that is using a sub-allocated block from the piobuf.
2154          */
2155         min_vi_count = edcp->edc_min_vi_count;
2156         max_vi_count =
2157             edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count;
2158
2159         /* Ensure that the previously attached driver's VIs are freed */
2160         if ((rc = efx_mcdi_free_vis(enp)) != 0)
2161                 goto fail2;
2162
2163         /*
2164          * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this
2165          * fails then retrying the request for fewer VI resources may succeed.
2166          */
2167         vi_count = 0;
2168         if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count,
2169                     &vi_base, &vi_count, &vi_shift)) != 0)
2170                 goto fail3;
2171
2172         EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count);
2173
2174         if (vi_count < min_vi_count) {
2175                 rc = ENOMEM;
2176                 goto fail4;
2177         }
2178
2179         enp->en_arch.ef10.ena_vi_base = vi_base;
2180         enp->en_arch.ef10.ena_vi_count = vi_count;
2181         enp->en_arch.ef10.ena_vi_shift = vi_shift;
2182
2183         if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) {
2184                 /* Not enough extra VIs to map piobufs */
2185                 ef10_nic_free_piobufs(enp);
2186         }
2187
2188         enp->en_arch.ef10.ena_pio_write_vi_base =
2189             vi_count - enp->en_arch.ef10.ena_piobuf_count;
2190
2191         EFSYS_ASSERT3U(enp->en_nic_cfg.enc_vi_window_shift, !=,
2192             EFX_VI_WINDOW_SHIFT_INVALID);
2193         EFSYS_ASSERT3U(enp->en_nic_cfg.enc_vi_window_shift, <=,
2194             EFX_VI_WINDOW_SHIFT_64K);
2195         vi_window_size = 1U << enp->en_nic_cfg.enc_vi_window_shift;
2196
2197         /* Save UC memory mapping details */
2198         enp->en_arch.ef10.ena_uc_mem_map_offset = 0;
2199         if (enp->en_arch.ef10.ena_piobuf_count > 0) {
2200                 enp->en_arch.ef10.ena_uc_mem_map_size =
2201                     (vi_window_size *
2202                     enp->en_arch.ef10.ena_pio_write_vi_base);
2203         } else {
2204                 enp->en_arch.ef10.ena_uc_mem_map_size =
2205                     (vi_window_size *
2206                     enp->en_arch.ef10.ena_vi_count);
2207         }
2208
2209         /* Save WC memory mapping details */
2210         enp->en_arch.ef10.ena_wc_mem_map_offset =
2211             enp->en_arch.ef10.ena_uc_mem_map_offset +
2212             enp->en_arch.ef10.ena_uc_mem_map_size;
2213
2214         enp->en_arch.ef10.ena_wc_mem_map_size =
2215             (vi_window_size *
2216             enp->en_arch.ef10.ena_piobuf_count);
2217
2218         /* Link piobufs to extra VIs in WC mapping */
2219         if (enp->en_arch.ef10.ena_piobuf_count > 0) {
2220                 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
2221                         rc = efx_mcdi_link_piobuf(enp,
2222                             enp->en_arch.ef10.ena_pio_write_vi_base + i,
2223                             enp->en_arch.ef10.ena_piobuf_handle[i]);
2224                         if (rc != 0)
2225                                 break;
2226                 }
2227         }
2228
2229         /*
2230          * Allocate a vAdaptor attached to our upstream vPort/pPort.
2231          *
2232          * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF
2233          * driver has yet to bring up the EVB port. See bug 56147. In this case,
2234          * retry the request several times after waiting a while. The wait time
2235          * between retries starts small (10ms) and exponentially increases.
2236          * Total wait time is a little over two seconds. Retry logic in the
2237          * client driver may mean this whole loop is repeated if it continues to
2238          * fail.
2239          */
2240         retry = 0;
2241         delay_us = 10000;
2242         while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) {
2243                 if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) ||
2244                     (rc != ENOENT)) {
2245                         /*
2246                          * Do not retry alloc for PF, or for other errors on
2247                          * a VF.
2248                          */
2249                         goto fail5;
2250                 }
2251
2252                 /* VF startup before PF is ready. Retry allocation. */
2253                 if (retry > 5) {
2254                         /* Too many attempts */
2255                         rc = EINVAL;
2256                         goto fail6;
2257                 }
2258                 EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry);
2259                 EFSYS_SLEEP(delay_us);
2260                 retry++;
2261                 if (delay_us < 500000)
2262                         delay_us <<= 2;
2263         }
2264
2265         enp->en_vport_id = EVB_PORT_ID_ASSIGNED;
2266         enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2;
2267
2268         return (0);
2269
2270 fail6:
2271         EFSYS_PROBE(fail6);
2272 fail5:
2273         EFSYS_PROBE(fail5);
2274 fail4:
2275         EFSYS_PROBE(fail4);
2276 fail3:
2277         EFSYS_PROBE(fail3);
2278 fail2:
2279         EFSYS_PROBE(fail2);
2280
2281         ef10_nic_free_piobufs(enp);
2282
2283 fail1:
2284         EFSYS_PROBE1(fail1, efx_rc_t, rc);
2285
2286         return (rc);
2287 }
2288
2289         __checkReturn   efx_rc_t
2290 ef10_nic_get_vi_pool(
2291         __in            efx_nic_t *enp,
2292         __out           uint32_t *vi_countp)
2293 {
2294         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
2295             enp->en_family == EFX_FAMILY_MEDFORD ||
2296             enp->en_family == EFX_FAMILY_MEDFORD2);
2297
2298         /*
2299          * Report VIs that the client driver can use.
2300          * Do not include VIs used for PIO buffer writes.
2301          */
2302         *vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base;
2303
2304         return (0);
2305 }
2306
2307         __checkReturn   efx_rc_t
2308 ef10_nic_get_bar_region(
2309         __in            efx_nic_t *enp,
2310         __in            efx_nic_region_t region,
2311         __out           uint32_t *offsetp,
2312         __out           size_t *sizep)
2313 {
2314         efx_rc_t rc;
2315
2316         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
2317             enp->en_family == EFX_FAMILY_MEDFORD ||
2318             enp->en_family == EFX_FAMILY_MEDFORD2);
2319
2320         /*
2321          * TODO: Specify host memory mapping alignment and granularity
2322          * in efx_drv_limits_t so that they can be taken into account
2323          * when allocating extra VIs for PIO writes.
2324          */
2325         switch (region) {
2326         case EFX_REGION_VI:
2327                 /* UC mapped memory BAR region for VI registers */
2328                 *offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset;
2329                 *sizep = enp->en_arch.ef10.ena_uc_mem_map_size;
2330                 break;
2331
2332         case EFX_REGION_PIO_WRITE_VI:
2333                 /* WC mapped memory BAR region for piobuf writes */
2334                 *offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset;
2335                 *sizep = enp->en_arch.ef10.ena_wc_mem_map_size;
2336                 break;
2337
2338         default:
2339                 rc = EINVAL;
2340                 goto fail1;
2341         }
2342
2343         return (0);
2344
2345 fail1:
2346         EFSYS_PROBE1(fail1, efx_rc_t, rc);
2347
2348         return (rc);
2349 }
2350
2351                         void
2352 ef10_nic_fini(
2353         __in            efx_nic_t *enp)
2354 {
2355         uint32_t i;
2356         efx_rc_t rc;
2357
2358         (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id);
2359         enp->en_vport_id = 0;
2360
2361         /* Unlink piobufs from extra VIs in WC mapping */
2362         if (enp->en_arch.ef10.ena_piobuf_count > 0) {
2363                 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
2364                         rc = efx_mcdi_unlink_piobuf(enp,
2365                             enp->en_arch.ef10.ena_pio_write_vi_base + i);
2366                         if (rc != 0)
2367                                 break;
2368                 }
2369         }
2370
2371         ef10_nic_free_piobufs(enp);
2372
2373         (void) efx_mcdi_free_vis(enp);
2374         enp->en_arch.ef10.ena_vi_count = 0;
2375 }
2376
2377                         void
2378 ef10_nic_unprobe(
2379         __in            efx_nic_t *enp)
2380 {
2381 #if EFSYS_OPT_MON_STATS
2382         mcdi_mon_cfg_free(enp);
2383 #endif /* EFSYS_OPT_MON_STATS */
2384         (void) efx_mcdi_drv_attach(enp, B_FALSE);
2385 }
2386
2387 #if EFSYS_OPT_DIAG
2388
2389         __checkReturn   efx_rc_t
2390 ef10_nic_register_test(
2391         __in            efx_nic_t *enp)
2392 {
2393         efx_rc_t rc;
2394
2395         /* FIXME */
2396         _NOTE(ARGUNUSED(enp))
2397         _NOTE(CONSTANTCONDITION)
2398         if (B_FALSE) {
2399                 rc = ENOTSUP;
2400                 goto fail1;
2401         }
2402         /* FIXME */
2403
2404         return (0);
2405
2406 fail1:
2407         EFSYS_PROBE1(fail1, efx_rc_t, rc);
2408
2409         return (rc);
2410 }
2411
2412 #endif  /* EFSYS_OPT_DIAG */
2413
2414 #if EFSYS_OPT_FW_SUBVARIANT_AWARE
2415
2416         __checkReturn   efx_rc_t
2417 efx_mcdi_get_nic_global(
2418         __in            efx_nic_t *enp,
2419         __in            uint32_t key,
2420         __out           uint32_t *valuep)
2421 {
2422         efx_mcdi_req_t req;
2423         uint8_t payload[MAX(MC_CMD_GET_NIC_GLOBAL_IN_LEN,
2424                             MC_CMD_GET_NIC_GLOBAL_OUT_LEN)];
2425         efx_rc_t rc;
2426
2427         (void) memset(payload, 0, sizeof (payload));
2428         req.emr_cmd = MC_CMD_GET_NIC_GLOBAL;
2429         req.emr_in_buf = payload;
2430         req.emr_in_length = MC_CMD_GET_NIC_GLOBAL_IN_LEN;
2431         req.emr_out_buf = payload;
2432         req.emr_out_length = MC_CMD_GET_NIC_GLOBAL_OUT_LEN;
2433
2434         MCDI_IN_SET_DWORD(req, GET_NIC_GLOBAL_IN_KEY, key);
2435
2436         efx_mcdi_execute(enp, &req);
2437
2438         if (req.emr_rc != 0) {
2439                 rc = req.emr_rc;
2440                 goto fail1;
2441         }
2442
2443         if (req.emr_out_length_used != MC_CMD_GET_NIC_GLOBAL_OUT_LEN) {
2444                 rc = EMSGSIZE;
2445                 goto fail2;
2446         }
2447
2448         *valuep = MCDI_OUT_DWORD(req, GET_NIC_GLOBAL_OUT_VALUE);
2449
2450         return (0);
2451
2452 fail2:
2453         EFSYS_PROBE(fail2);
2454 fail1:
2455         EFSYS_PROBE1(fail1, efx_rc_t, rc);
2456
2457         return (rc);
2458 }
2459
2460         __checkReturn   efx_rc_t
2461 efx_mcdi_set_nic_global(
2462         __in            efx_nic_t *enp,
2463         __in            uint32_t key,
2464         __in            uint32_t value)
2465 {
2466         efx_mcdi_req_t req;
2467         uint8_t payload[MC_CMD_SET_NIC_GLOBAL_IN_LEN];
2468         efx_rc_t rc;
2469
2470         (void) memset(payload, 0, sizeof (payload));
2471         req.emr_cmd = MC_CMD_SET_NIC_GLOBAL;
2472         req.emr_in_buf = payload;
2473         req.emr_in_length = MC_CMD_SET_NIC_GLOBAL_IN_LEN;
2474         req.emr_out_buf = NULL;
2475         req.emr_out_length = 0;
2476
2477         MCDI_IN_SET_DWORD(req, SET_NIC_GLOBAL_IN_KEY, key);
2478         MCDI_IN_SET_DWORD(req, SET_NIC_GLOBAL_IN_VALUE, value);
2479
2480         efx_mcdi_execute(enp, &req);
2481
2482         if (req.emr_rc != 0) {
2483                 rc = req.emr_rc;
2484                 goto fail1;
2485         }
2486
2487         return (0);
2488
2489 fail1:
2490         EFSYS_PROBE1(fail1, efx_rc_t, rc);
2491
2492         return (rc);
2493 }
2494
2495 #endif  /* EFSYS_OPT_FW_SUBVARIANT_AWARE */
2496
2497 #endif  /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */