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