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