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