]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/dev/sfxge/common/hunt_nic.c
MFC r294091
[FreeBSD/stable/10.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 #undef CAP_FLAG
955 #undef CAP_FLAG2
956
957         return (0);
958
959 fail2:
960         EFSYS_PROBE(fail2);
961 fail1:
962         EFSYS_PROBE1(fail1, efx_rc_t, rc);
963
964         return (rc);
965 }
966
967
968         __checkReturn           efx_rc_t
969 ef10_get_privilege_mask(
970         __in                    efx_nic_t *enp,
971         __out                   uint32_t *maskp)
972 {
973         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
974         uint32_t mask;
975         efx_rc_t rc;
976
977         if ((rc = efx_mcdi_privilege_mask(enp, encp->enc_pf, encp->enc_vf,
978                                             &mask)) != 0) {
979                 if (rc != ENOTSUP)
980                         goto fail1;
981
982                 /* Fallback for old firmware without privilege mask support */
983                 if (EFX_PCI_FUNCTION_IS_PF(encp)) {
984                         /* Assume PF has admin privilege */
985                         mask = EF10_LEGACY_PF_PRIVILEGE_MASK;
986                 } else {
987                         /* VF is always unprivileged by default */
988                         mask = EF10_LEGACY_VF_PRIVILEGE_MASK;
989                 }
990         }
991
992         *maskp = mask;
993
994         return (0);
995
996 fail1:
997         EFSYS_PROBE1(fail1, efx_rc_t, rc);
998
999         return (rc);
1000 }
1001
1002
1003 /*
1004  * The external port mapping is a one-based numbering of the external
1005  * connectors on the board. It does not distinguish off-board separated
1006  * outputs such as multi-headed cables.
1007  * The number of ports that map to each external port connector
1008  * on the board is determined by the chip family and the port modes to
1009  * which the NIC can be configured. The mapping table lists modes with
1010  * port numbering requirements in increasing order.
1011  */
1012 static struct {
1013         efx_family_t    family;
1014         uint32_t        modes_mask;
1015         uint32_t        stride;
1016 }       __ef10_external_port_mappings[] = {
1017         /* Supported modes requiring 1 output per port */
1018         {
1019                 EFX_FAMILY_HUNTINGTON,
1020                 (1 << TLV_PORT_MODE_10G) |
1021                 (1 << TLV_PORT_MODE_10G_10G) |
1022                 (1 << TLV_PORT_MODE_10G_10G_10G_10G),
1023                 1
1024         },
1025         {
1026                 EFX_FAMILY_MEDFORD,
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         /* Supported modes requiring 2 outputs per port */
1033         {
1034                 EFX_FAMILY_HUNTINGTON,
1035                 (1 << TLV_PORT_MODE_40G) |
1036                 (1 << TLV_PORT_MODE_40G_40G) |
1037                 (1 << TLV_PORT_MODE_40G_10G_10G) |
1038                 (1 << TLV_PORT_MODE_10G_10G_40G),
1039                 2
1040         },
1041         {
1042                 EFX_FAMILY_MEDFORD,
1043                 (1 << TLV_PORT_MODE_40G) |
1044                 (1 << TLV_PORT_MODE_40G_40G) |
1045                 (1 << TLV_PORT_MODE_40G_10G_10G) |
1046                 (1 << TLV_PORT_MODE_10G_10G_40G),
1047                 2
1048         },
1049         /* Supported modes requiring 4 outputs per port */
1050         {
1051                 EFX_FAMILY_MEDFORD,
1052                 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q) |
1053                 (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q2),
1054                 4
1055         },
1056 };
1057
1058         __checkReturn   efx_rc_t
1059 ef10_external_port_mapping(
1060         __in            efx_nic_t *enp,
1061         __in            uint32_t port,
1062         __out           uint8_t *external_portp)
1063 {
1064         efx_rc_t rc;
1065         int i;
1066         uint32_t port_modes;
1067         uint32_t matches;
1068         uint32_t stride = 1; /* default 1-1 mapping */
1069
1070         if ((rc = efx_mcdi_get_port_modes(enp, &port_modes)) != 0) {
1071                 /* No port mode information available - use default mapping */
1072                 goto out;
1073         }
1074
1075         /*
1076          * Infer the internal port -> external port mapping from
1077          * the possible port modes for this NIC.
1078          */
1079         for (i = 0; i < EFX_ARRAY_SIZE(__ef10_external_port_mappings); ++i) {
1080                 if (__ef10_external_port_mappings[i].family !=
1081                     enp->en_family)
1082                         continue;
1083                 matches = (__ef10_external_port_mappings[i].modes_mask &
1084                     port_modes);
1085                 if (matches != 0) {
1086                         stride = __ef10_external_port_mappings[i].stride;
1087                         port_modes &= ~matches;
1088                 }
1089         }
1090
1091         if (port_modes != 0) {
1092                 /* Some advertised modes are not supported */
1093                 rc = ENOTSUP;
1094                 goto fail1;
1095         }
1096
1097 out:
1098         /*
1099          * Scale as required by last matched mode and then convert to
1100          * one-based numbering
1101          */
1102         *external_portp = (uint8_t)(port / stride) + 1;
1103         return (0);
1104
1105 fail1:
1106         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1107
1108         return (rc);
1109 }
1110
1111         __checkReturn   efx_rc_t
1112 hunt_board_cfg(
1113         __in            efx_nic_t *enp)
1114 {
1115         efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
1116         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1117         uint8_t mac_addr[6];
1118         uint32_t board_type = 0;
1119         ef10_link_state_t els;
1120         efx_port_t *epp = &(enp->en_port);
1121         uint32_t port;
1122         uint32_t pf;
1123         uint32_t vf;
1124         uint32_t mask;
1125         uint32_t flags;
1126         uint32_t sysclk;
1127         uint32_t base, nvec;
1128         efx_rc_t rc;
1129
1130         if ((rc = efx_mcdi_get_port_assignment(enp, &port)) != 0)
1131                 goto fail1;
1132
1133         /*
1134          * NOTE: The MCDI protocol numbers ports from zero.
1135          * The common code MCDI interface numbers ports from one.
1136          */
1137         emip->emi_port = port + 1;
1138
1139         if ((rc = ef10_external_port_mapping(enp, port,
1140                     &encp->enc_external_port)) != 0)
1141                 goto fail2;
1142
1143         /*
1144          * Get PCIe function number from firmware (used for
1145          * per-function privilege and dynamic config info).
1146          *  - PCIe PF: pf = PF number, vf = 0xffff.
1147          *  - PCIe VF: pf = parent PF, vf = VF number.
1148          */
1149         if ((rc = efx_mcdi_get_function_info(enp, &pf, &vf)) != 0)
1150                 goto fail3;
1151
1152         encp->enc_pf = pf;
1153         encp->enc_vf = vf;
1154
1155         /* MAC address for this function */
1156         if (EFX_PCI_FUNCTION_IS_PF(encp)) {
1157                 rc = efx_mcdi_get_mac_address_pf(enp, mac_addr);
1158                 if ((rc == 0) && (mac_addr[0] & 0x02)) {
1159                         /*
1160                          * If the static config does not include a global MAC
1161                          * address pool then the board may return a locally
1162                          * administered MAC address (this should only happen on
1163                          * incorrectly programmed boards).
1164                          */
1165                         rc = EINVAL;
1166                 }
1167         } else {
1168                 rc = efx_mcdi_get_mac_address_vf(enp, mac_addr);
1169         }
1170         if (rc != 0)
1171                 goto fail4;
1172
1173         EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
1174
1175         /* Board configuration */
1176         rc = efx_mcdi_get_board_cfg(enp, &board_type, NULL, NULL);
1177         if (rc != 0) {
1178                 /* Unprivileged functions may not be able to read board cfg */
1179                 if (rc == EACCES)
1180                         board_type = 0;
1181                 else
1182                         goto fail5;
1183         }
1184
1185         encp->enc_board_type = board_type;
1186         encp->enc_clk_mult = 1; /* not used for Huntington */
1187
1188         /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
1189         if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
1190                 goto fail6;
1191
1192         /* Obtain the default PHY advertised capabilities */
1193         if ((rc = ef10_phy_get_link(enp, &els)) != 0)
1194                 goto fail7;
1195         epp->ep_default_adv_cap_mask = els.els_adv_cap_mask;
1196         epp->ep_adv_cap_mask = els.els_adv_cap_mask;
1197
1198         /*
1199          * Enable firmware workarounds for hardware errata.
1200          * Expected responses are:
1201          *  - 0 (zero):
1202          *      Success: workaround enabled or disabled as requested.
1203          *  - MC_CMD_ERR_ENOSYS (reported as ENOTSUP):
1204          *      Firmware does not support the MC_CMD_WORKAROUND request.
1205          *      (assume that the workaround is not supported).
1206          *  - MC_CMD_ERR_ENOENT (reported as ENOENT):
1207          *      Firmware does not support the requested workaround.
1208          *  - MC_CMD_ERR_EPERM  (reported as EACCES):
1209          *      Unprivileged function cannot enable/disable workarounds.
1210          *
1211          * See efx_mcdi_request_errcode() for MCDI error translations.
1212          */
1213
1214         /*
1215          * If the bug35388 workaround is enabled, then use an indirect access
1216          * method to avoid unsafe EVQ writes.
1217          */
1218         rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG35388, B_TRUE,
1219             NULL);
1220         if ((rc == 0) || (rc == EACCES))
1221                 encp->enc_bug35388_workaround = B_TRUE;
1222         else if ((rc == ENOTSUP) || (rc == ENOENT))
1223                 encp->enc_bug35388_workaround = B_FALSE;
1224         else
1225                 goto fail8;
1226
1227         /*
1228          * If the bug41750 workaround is enabled, then do not test interrupts,
1229          * as the test will fail (seen with Greenport controllers).
1230          */
1231         rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG41750, B_TRUE,
1232             NULL);
1233         if (rc == 0) {
1234                 encp->enc_bug41750_workaround = B_TRUE;
1235         } else if (rc == EACCES) {
1236                 /* Assume a controller with 40G ports needs the workaround. */
1237                 if (epp->ep_default_adv_cap_mask & EFX_PHY_CAP_40000FDX)
1238                         encp->enc_bug41750_workaround = B_TRUE;
1239                 else
1240                         encp->enc_bug41750_workaround = B_FALSE;
1241         } else if ((rc == ENOTSUP) || (rc == ENOENT)) {
1242                 encp->enc_bug41750_workaround = B_FALSE;
1243         } else {
1244                 goto fail9;
1245         }
1246         if (EFX_PCI_FUNCTION_IS_VF(encp)) {
1247                 /* Interrupt testing does not work for VFs. See bug50084. */
1248                 encp->enc_bug41750_workaround = B_TRUE;
1249         }
1250
1251         /*
1252          * If the bug26807 workaround is enabled, then firmware has enabled
1253          * support for chained multicast filters. Firmware will reset (FLR)
1254          * functions which have filters in the hardware filter table when the
1255          * workaround is enabled/disabled.
1256          *
1257          * We must recheck if the workaround is enabled after inserting the
1258          * first hardware filter, in case it has been changed since this check.
1259          */
1260         rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG26807,
1261             B_TRUE, &flags);
1262         if (rc == 0) {
1263                 encp->enc_bug26807_workaround = B_TRUE;
1264                 if (flags & (1 << MC_CMD_WORKAROUND_EXT_OUT_FLR_DONE_LBN)) {
1265                         /*
1266                          * Other functions had installed filters before the
1267                          * workaround was enabled, and they have been reset
1268                          * by firmware.
1269                          */
1270                         EFSYS_PROBE(bug26807_workaround_flr_done);
1271                         /* FIXME: bump MC warm boot count ? */
1272                 }
1273         } else if (rc == EACCES) {
1274                 /*
1275                  * Unprivileged functions cannot enable the workaround in older
1276                  * firmware.
1277                  */
1278                 encp->enc_bug26807_workaround = B_FALSE;
1279         } else if ((rc == ENOTSUP) || (rc == ENOENT)) {
1280                 encp->enc_bug26807_workaround = B_FALSE;
1281         } else {
1282                 goto fail10;
1283         }
1284
1285         /* Get sysclk frequency (in MHz). */
1286         if ((rc = efx_mcdi_get_clock(enp, &sysclk)) != 0)
1287                 goto fail11;
1288
1289         /*
1290          * The timer quantum is 1536 sysclk cycles, documented for the
1291          * EV_TMR_VAL field of EV_TIMER_TBL. Scale for MHz and ns units.
1292          */
1293         encp->enc_evq_timer_quantum_ns = 1536000UL / sysclk; /* 1536 cycles */
1294         if (encp->enc_bug35388_workaround) {
1295                 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
1296                 ERF_DD_EVQ_IND_TIMER_VAL_WIDTH) / 1000;
1297         } else {
1298                 encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
1299                 FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
1300         }
1301
1302         /* Check capabilities of running datapath firmware */
1303         if ((rc = ef10_get_datapath_caps(enp)) != 0)
1304             goto fail12;
1305
1306         /* Alignment for receive packet DMA buffers */
1307         encp->enc_rx_buf_align_start = 1;
1308         encp->enc_rx_buf_align_end = 64; /* RX DMA end padding */
1309
1310         /* Alignment for WPTR updates */
1311         encp->enc_rx_push_align = EF10_RX_WPTR_ALIGN;
1312
1313         /*
1314          * Set resource limits for MC_CMD_ALLOC_VIS. Note that we cannot use
1315          * MC_CMD_GET_RESOURCE_LIMITS here as that reports the available
1316          * resources (allocated to this PCIe function), which is zero until
1317          * after we have allocated VIs.
1318          */
1319         encp->enc_evq_limit = 1024;
1320         encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
1321         encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
1322
1323         encp->enc_buftbl_limit = 0xFFFFFFFF;
1324
1325         encp->enc_piobuf_limit = HUNT_PIOBUF_NBUFS;
1326         encp->enc_piobuf_size = HUNT_PIOBUF_SIZE;
1327         encp->enc_piobuf_min_alloc_size = HUNT_MIN_PIO_ALLOC_SIZE;
1328
1329         /*
1330          * Get the current privilege mask. Note that this may be modified
1331          * dynamically, so this value is informational only. DO NOT use
1332          * the privilege mask to check for sufficient privileges, as that
1333          * can result in time-of-check/time-of-use bugs.
1334          */
1335         if ((rc = ef10_get_privilege_mask(enp, &mask)) != 0)
1336                 goto fail13;
1337         encp->enc_privilege_mask = mask;
1338
1339         /* Get interrupt vector limits */
1340         if ((rc = efx_mcdi_get_vector_cfg(enp, &base, &nvec, NULL)) != 0) {
1341                 if (EFX_PCI_FUNCTION_IS_PF(encp))
1342                         goto fail14;
1343
1344                 /* Ignore error (cannot query vector limits from a VF). */
1345                 base = 0;
1346                 nvec = 1024;
1347         }
1348         encp->enc_intr_vec_base = base;
1349         encp->enc_intr_limit = nvec;
1350
1351         /*
1352          * Maximum number of bytes into the frame the TCP header can start for
1353          * firmware assisted TSO to work.
1354          */
1355         encp->enc_tx_tso_tcp_header_offset_limit = EF10_TCP_HEADER_OFFSET_LIMIT;
1356
1357         return (0);
1358
1359 fail14:
1360         EFSYS_PROBE(fail14);
1361 fail13:
1362         EFSYS_PROBE(fail13);
1363 fail12:
1364         EFSYS_PROBE(fail12);
1365 fail11:
1366         EFSYS_PROBE(fail11);
1367 fail10:
1368         EFSYS_PROBE(fail10);
1369 fail9:
1370         EFSYS_PROBE(fail9);
1371 fail8:
1372         EFSYS_PROBE(fail8);
1373 fail7:
1374         EFSYS_PROBE(fail7);
1375 fail6:
1376         EFSYS_PROBE(fail6);
1377 fail5:
1378         EFSYS_PROBE(fail5);
1379 fail4:
1380         EFSYS_PROBE(fail4);
1381 fail3:
1382         EFSYS_PROBE(fail3);
1383 fail2:
1384         EFSYS_PROBE(fail2);
1385 fail1:
1386         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1387
1388         return (rc);
1389 }
1390
1391
1392         __checkReturn   efx_rc_t
1393 ef10_nic_probe(
1394         __in            efx_nic_t *enp)
1395 {
1396         efx_nic_ops_t *enop = enp->en_enop;
1397         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1398         efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1399         efx_rc_t rc;
1400
1401         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1402                     enp->en_family == EFX_FAMILY_MEDFORD);
1403
1404         /* Read and clear any assertion state */
1405         if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1406                 goto fail1;
1407
1408         /* Exit the assertion handler */
1409         if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1410                 if (rc != EACCES)
1411                         goto fail2;
1412
1413         if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
1414                 goto fail3;
1415
1416         if ((rc = enop->eno_board_cfg(enp)) != 0)
1417                 if (rc != EACCES)
1418                         goto fail4;
1419
1420         /*
1421          * Set default driver config limits (based on board config).
1422          *
1423          * FIXME: For now allocate a fixed number of VIs which is likely to be
1424          * sufficient and small enough to allow multiple functions on the same
1425          * port.
1426          */
1427         edcp->edc_min_vi_count = edcp->edc_max_vi_count =
1428             MIN(128, MAX(encp->enc_rxq_limit, encp->enc_txq_limit));
1429
1430         /* The client driver must configure and enable PIO buffer support */
1431         edcp->edc_max_piobuf_count = 0;
1432         edcp->edc_pio_alloc_size = 0;
1433
1434 #if EFSYS_OPT_MAC_STATS
1435         /* Wipe the MAC statistics */
1436         if ((rc = efx_mcdi_mac_stats_clear(enp)) != 0)
1437                 goto fail5;
1438 #endif
1439
1440 #if EFSYS_OPT_LOOPBACK
1441         if ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)
1442                 goto fail6;
1443 #endif
1444
1445 #if EFSYS_OPT_MON_STATS
1446         if ((rc = mcdi_mon_cfg_build(enp)) != 0) {
1447                 /* Unprivileged functions do not have access to sensors */
1448                 if (rc != EACCES)
1449                         goto fail7;
1450         }
1451 #endif
1452
1453         encp->enc_features = enp->en_features;
1454
1455         return (0);
1456
1457 #if EFSYS_OPT_MON_STATS
1458 fail7:
1459         EFSYS_PROBE(fail7);
1460 #endif
1461 #if EFSYS_OPT_LOOPBACK
1462 fail6:
1463         EFSYS_PROBE(fail6);
1464 #endif
1465 #if EFSYS_OPT_MAC_STATS
1466 fail5:
1467         EFSYS_PROBE(fail5);
1468 #endif
1469 fail4:
1470         EFSYS_PROBE(fail4);
1471 fail3:
1472         EFSYS_PROBE(fail3);
1473 fail2:
1474         EFSYS_PROBE(fail2);
1475 fail1:
1476         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1477
1478         return (rc);
1479 }
1480
1481         __checkReturn   efx_rc_t
1482 ef10_nic_set_drv_limits(
1483         __inout         efx_nic_t *enp,
1484         __in            efx_drv_limits_t *edlp)
1485 {
1486         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1487         efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1488         uint32_t min_evq_count, max_evq_count;
1489         uint32_t min_rxq_count, max_rxq_count;
1490         uint32_t min_txq_count, max_txq_count;
1491         efx_rc_t rc;
1492
1493         if (edlp == NULL) {
1494                 rc = EINVAL;
1495                 goto fail1;
1496         }
1497
1498         /* Get minimum required and maximum usable VI limits */
1499         min_evq_count = MIN(edlp->edl_min_evq_count, encp->enc_evq_limit);
1500         min_rxq_count = MIN(edlp->edl_min_rxq_count, encp->enc_rxq_limit);
1501         min_txq_count = MIN(edlp->edl_min_txq_count, encp->enc_txq_limit);
1502
1503         edcp->edc_min_vi_count =
1504             MAX(min_evq_count, MAX(min_rxq_count, min_txq_count));
1505
1506         max_evq_count = MIN(edlp->edl_max_evq_count, encp->enc_evq_limit);
1507         max_rxq_count = MIN(edlp->edl_max_rxq_count, encp->enc_rxq_limit);
1508         max_txq_count = MIN(edlp->edl_max_txq_count, encp->enc_txq_limit);
1509
1510         edcp->edc_max_vi_count =
1511             MAX(max_evq_count, MAX(max_rxq_count, max_txq_count));
1512
1513         /*
1514          * Check limits for sub-allocated piobuf blocks.
1515          * PIO is optional, so don't fail if the limits are incorrect.
1516          */
1517         if ((encp->enc_piobuf_size == 0) ||
1518             (encp->enc_piobuf_limit == 0) ||
1519             (edlp->edl_min_pio_alloc_size == 0) ||
1520             (edlp->edl_min_pio_alloc_size > encp->enc_piobuf_size)) {
1521                 /* Disable PIO */
1522                 edcp->edc_max_piobuf_count = 0;
1523                 edcp->edc_pio_alloc_size = 0;
1524         } else {
1525                 uint32_t blk_size, blk_count, blks_per_piobuf;
1526
1527                 blk_size =
1528                     MAX(edlp->edl_min_pio_alloc_size,
1529                             encp->enc_piobuf_min_alloc_size);
1530
1531                 blks_per_piobuf = encp->enc_piobuf_size / blk_size;
1532                 EFSYS_ASSERT3U(blks_per_piobuf, <=, 32);
1533
1534                 blk_count = (encp->enc_piobuf_limit * blks_per_piobuf);
1535
1536                 /* A zero max pio alloc count means unlimited */
1537                 if ((edlp->edl_max_pio_alloc_count > 0) &&
1538                     (edlp->edl_max_pio_alloc_count < blk_count)) {
1539                         blk_count = edlp->edl_max_pio_alloc_count;
1540                 }
1541
1542                 edcp->edc_pio_alloc_size = blk_size;
1543                 edcp->edc_max_piobuf_count =
1544                     (blk_count + (blks_per_piobuf - 1)) / blks_per_piobuf;
1545         }
1546
1547         return (0);
1548
1549 fail1:
1550         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1551
1552         return (rc);
1553 }
1554
1555
1556         __checkReturn   efx_rc_t
1557 ef10_nic_reset(
1558         __in            efx_nic_t *enp)
1559 {
1560         efx_mcdi_req_t req;
1561         uint8_t payload[MAX(MC_CMD_ENTITY_RESET_IN_LEN,
1562                             MC_CMD_ENTITY_RESET_OUT_LEN)];
1563         efx_rc_t rc;
1564
1565         /* ef10_nic_reset() is called to recover from BADASSERT failures. */
1566         if ((rc = efx_mcdi_read_assertion(enp)) != 0)
1567                 goto fail1;
1568         if ((rc = efx_mcdi_exit_assertion_handler(enp)) != 0)
1569                 goto fail2;
1570
1571         (void) memset(payload, 0, sizeof (payload));
1572         req.emr_cmd = MC_CMD_ENTITY_RESET;
1573         req.emr_in_buf = payload;
1574         req.emr_in_length = MC_CMD_ENTITY_RESET_IN_LEN;
1575         req.emr_out_buf = payload;
1576         req.emr_out_length = MC_CMD_ENTITY_RESET_OUT_LEN;
1577
1578         MCDI_IN_POPULATE_DWORD_1(req, ENTITY_RESET_IN_FLAG,
1579             ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1);
1580
1581         efx_mcdi_execute(enp, &req);
1582
1583         if (req.emr_rc != 0) {
1584                 rc = req.emr_rc;
1585                 goto fail3;
1586         }
1587
1588         /* Clear RX/TX DMA queue errors */
1589         enp->en_reset_flags &= ~(EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR);
1590
1591         return (0);
1592
1593 fail3:
1594         EFSYS_PROBE(fail3);
1595 fail2:
1596         EFSYS_PROBE(fail2);
1597 fail1:
1598         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1599
1600         return (rc);
1601 }
1602
1603         __checkReturn   efx_rc_t
1604 ef10_nic_init(
1605         __in            efx_nic_t *enp)
1606 {
1607         efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
1608         uint32_t min_vi_count, max_vi_count;
1609         uint32_t vi_count, vi_base, vi_shift;
1610         uint32_t i;
1611         uint32_t retry;
1612         uint32_t delay_us;
1613         efx_rc_t rc;
1614
1615         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1616                     enp->en_family == EFX_FAMILY_MEDFORD);
1617
1618         /* Enable reporting of some events (e.g. link change) */
1619         if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
1620                 goto fail1;
1621
1622         /* Allocate (optional) on-chip PIO buffers */
1623         ef10_nic_alloc_piobufs(enp, edcp->edc_max_piobuf_count);
1624
1625         /*
1626          * For best performance, PIO writes should use a write-combined
1627          * (WC) memory mapping. Using a separate WC mapping for the PIO
1628          * aperture of each VI would be a burden to drivers (and not
1629          * possible if the host page size is >4Kbyte).
1630          *
1631          * To avoid this we use a single uncached (UC) mapping for VI
1632          * register access, and a single WC mapping for extra VIs used
1633          * for PIO writes.
1634          *
1635          * Each piobuf must be linked to a VI in the WC mapping, and to
1636          * each VI that is using a sub-allocated block from the piobuf.
1637          */
1638         min_vi_count = edcp->edc_min_vi_count;
1639         max_vi_count =
1640             edcp->edc_max_vi_count + enp->en_arch.ef10.ena_piobuf_count;
1641
1642         /* Ensure that the previously attached driver's VIs are freed */
1643         if ((rc = efx_mcdi_free_vis(enp)) != 0)
1644                 goto fail2;
1645
1646         /*
1647          * Reserve VI resources (EVQ+RXQ+TXQ) for this PCIe function. If this
1648          * fails then retrying the request for fewer VI resources may succeed.
1649          */
1650         vi_count = 0;
1651         if ((rc = efx_mcdi_alloc_vis(enp, min_vi_count, max_vi_count,
1652                     &vi_base, &vi_count, &vi_shift)) != 0)
1653                 goto fail3;
1654
1655         EFSYS_PROBE2(vi_alloc, uint32_t, vi_base, uint32_t, vi_count);
1656
1657         if (vi_count < min_vi_count) {
1658                 rc = ENOMEM;
1659                 goto fail4;
1660         }
1661
1662         enp->en_arch.ef10.ena_vi_base = vi_base;
1663         enp->en_arch.ef10.ena_vi_count = vi_count;
1664         enp->en_arch.ef10.ena_vi_shift = vi_shift;
1665
1666         if (vi_count < min_vi_count + enp->en_arch.ef10.ena_piobuf_count) {
1667                 /* Not enough extra VIs to map piobufs */
1668                 ef10_nic_free_piobufs(enp);
1669         }
1670
1671         enp->en_arch.ef10.ena_pio_write_vi_base =
1672             vi_count - enp->en_arch.ef10.ena_piobuf_count;
1673
1674         /* Save UC memory mapping details */
1675         enp->en_arch.ef10.ena_uc_mem_map_offset = 0;
1676         if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1677                 enp->en_arch.ef10.ena_uc_mem_map_size =
1678                     (ER_DZ_TX_PIOBUF_STEP *
1679                     enp->en_arch.ef10.ena_pio_write_vi_base);
1680         } else {
1681                 enp->en_arch.ef10.ena_uc_mem_map_size =
1682                     (ER_DZ_TX_PIOBUF_STEP *
1683                     enp->en_arch.ef10.ena_vi_count);
1684         }
1685
1686         /* Save WC memory mapping details */
1687         enp->en_arch.ef10.ena_wc_mem_map_offset =
1688             enp->en_arch.ef10.ena_uc_mem_map_offset +
1689             enp->en_arch.ef10.ena_uc_mem_map_size;
1690
1691         enp->en_arch.ef10.ena_wc_mem_map_size =
1692             (ER_DZ_TX_PIOBUF_STEP *
1693             enp->en_arch.ef10.ena_piobuf_count);
1694
1695         /* Link piobufs to extra VIs in WC mapping */
1696         if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1697                 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1698                         rc = efx_mcdi_link_piobuf(enp,
1699                             enp->en_arch.ef10.ena_pio_write_vi_base + i,
1700                             enp->en_arch.ef10.ena_piobuf_handle[i]);
1701                         if (rc != 0)
1702                                 break;
1703                 }
1704         }
1705
1706         /*
1707          * Allocate a vAdaptor attached to our upstream vPort/pPort.
1708          *
1709          * On a VF, this may fail with MC_CMD_ERR_NO_EVB_PORT (ENOENT) if the PF
1710          * driver has yet to bring up the EVB port. See bug 56147. In this case,
1711          * retry the request several times after waiting a while. The wait time
1712          * between retries starts small (10ms) and exponentially increases.
1713          * Total wait time is a little over two seconds. Retry logic in the
1714          * client driver may mean this whole loop is repeated if it continues to
1715          * fail.
1716          */
1717         retry = 0;
1718         delay_us = 10000;
1719         while ((rc = efx_mcdi_vadaptor_alloc(enp, EVB_PORT_ID_ASSIGNED)) != 0) {
1720                 if (EFX_PCI_FUNCTION_IS_PF(&enp->en_nic_cfg) ||
1721                     (rc != ENOENT)) {
1722                         /*
1723                          * Do not retry alloc for PF, or for other errors on
1724                          * a VF.
1725                          */
1726                         goto fail5;
1727                 }
1728
1729                 /* VF startup before PF is ready. Retry allocation. */
1730                 if (retry > 5) {
1731                         /* Too many attempts */
1732                         rc = EINVAL;
1733                         goto fail6;
1734                 }
1735                 EFSYS_PROBE1(mcdi_no_evb_port_retry, int, retry);
1736                 EFSYS_SLEEP(delay_us);
1737                 retry++;
1738                 if (delay_us < 500000)
1739                         delay_us <<= 2;
1740         }
1741
1742         enp->en_vport_id = EVB_PORT_ID_ASSIGNED;
1743         enp->en_nic_cfg.enc_mcdi_max_payload_length = MCDI_CTL_SDU_LEN_MAX_V2;
1744
1745         return (0);
1746
1747 fail6:
1748         EFSYS_PROBE(fail6);
1749 fail5:
1750         EFSYS_PROBE(fail5);
1751 fail4:
1752         EFSYS_PROBE(fail4);
1753 fail3:
1754         EFSYS_PROBE(fail3);
1755 fail2:
1756         EFSYS_PROBE(fail2);
1757
1758         ef10_nic_free_piobufs(enp);
1759
1760 fail1:
1761         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1762
1763         return (rc);
1764 }
1765
1766         __checkReturn   efx_rc_t
1767 ef10_nic_get_vi_pool(
1768         __in            efx_nic_t *enp,
1769         __out           uint32_t *vi_countp)
1770 {
1771         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1772                     enp->en_family == EFX_FAMILY_MEDFORD);
1773
1774         /*
1775          * Report VIs that the client driver can use.
1776          * Do not include VIs used for PIO buffer writes.
1777          */
1778         *vi_countp = enp->en_arch.ef10.ena_pio_write_vi_base;
1779
1780         return (0);
1781 }
1782
1783         __checkReturn   efx_rc_t
1784 ef10_nic_get_bar_region(
1785         __in            efx_nic_t *enp,
1786         __in            efx_nic_region_t region,
1787         __out           uint32_t *offsetp,
1788         __out           size_t *sizep)
1789 {
1790         efx_rc_t rc;
1791
1792         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
1793                     enp->en_family == EFX_FAMILY_MEDFORD);
1794
1795         /*
1796          * TODO: Specify host memory mapping alignment and granularity
1797          * in efx_drv_limits_t so that they can be taken into account
1798          * when allocating extra VIs for PIO writes.
1799          */
1800         switch (region) {
1801         case EFX_REGION_VI:
1802                 /* UC mapped memory BAR region for VI registers */
1803                 *offsetp = enp->en_arch.ef10.ena_uc_mem_map_offset;
1804                 *sizep = enp->en_arch.ef10.ena_uc_mem_map_size;
1805                 break;
1806
1807         case EFX_REGION_PIO_WRITE_VI:
1808                 /* WC mapped memory BAR region for piobuf writes */
1809                 *offsetp = enp->en_arch.ef10.ena_wc_mem_map_offset;
1810                 *sizep = enp->en_arch.ef10.ena_wc_mem_map_size;
1811                 break;
1812
1813         default:
1814                 rc = EINVAL;
1815                 goto fail1;
1816         }
1817
1818         return (0);
1819
1820 fail1:
1821         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1822
1823         return (rc);
1824 }
1825
1826                         void
1827 ef10_nic_fini(
1828         __in            efx_nic_t *enp)
1829 {
1830         uint32_t i;
1831         efx_rc_t rc;
1832
1833         (void) efx_mcdi_vadaptor_free(enp, enp->en_vport_id);
1834         enp->en_vport_id = 0;
1835
1836         /* Unlink piobufs from extra VIs in WC mapping */
1837         if (enp->en_arch.ef10.ena_piobuf_count > 0) {
1838                 for (i = 0; i < enp->en_arch.ef10.ena_piobuf_count; i++) {
1839                         rc = efx_mcdi_unlink_piobuf(enp,
1840                             enp->en_arch.ef10.ena_pio_write_vi_base + i);
1841                         if (rc != 0)
1842                                 break;
1843                 }
1844         }
1845
1846         ef10_nic_free_piobufs(enp);
1847
1848         (void) efx_mcdi_free_vis(enp);
1849         enp->en_arch.ef10.ena_vi_count = 0;
1850 }
1851
1852                         void
1853 ef10_nic_unprobe(
1854         __in            efx_nic_t *enp)
1855 {
1856 #if EFSYS_OPT_MON_STATS
1857         mcdi_mon_cfg_free(enp);
1858 #endif /* EFSYS_OPT_MON_STATS */
1859         (void) efx_mcdi_drv_attach(enp, B_FALSE);
1860 }
1861
1862 #if EFSYS_OPT_DIAG
1863
1864         __checkReturn   efx_rc_t
1865 ef10_nic_register_test(
1866         __in            efx_nic_t *enp)
1867 {
1868         efx_rc_t rc;
1869
1870         /* FIXME */
1871         _NOTE(ARGUNUSED(enp))
1872         if (B_FALSE) {
1873                 rc = ENOTSUP;
1874                 goto fail1;
1875         }
1876         /* FIXME */
1877
1878         return (0);
1879
1880 fail1:
1881         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1882
1883         return (rc);
1884 }
1885
1886 #endif  /* EFSYS_OPT_DIAG */
1887
1888
1889
1890 #endif  /* EFSYS_OPT_HUNTINGTON */