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