76caa744c66ea899c249772eb34ebc4fce72ac64
[deb_dpdk.git] / drivers / net / sfc / base / efx_nic.c
1 /*
2  * Copyright (c) 2007-2016 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 "efx.h"
32 #include "efx_impl.h"
33
34         __checkReturn   efx_rc_t
35 efx_family(
36         __in            uint16_t venid,
37         __in            uint16_t devid,
38         __out           efx_family_t *efp)
39 {
40         if (venid == EFX_PCI_VENID_SFC) {
41                 switch (devid) {
42 #if EFSYS_OPT_SIENA
43                 case EFX_PCI_DEVID_SIENA_F1_UNINIT:
44                         /*
45                          * Hardware default for PF0 of uninitialised Siena.
46                          * manftest must be able to cope with this device id.
47                          */
48                         *efp = EFX_FAMILY_SIENA;
49                         return (0);
50
51                 case EFX_PCI_DEVID_BETHPAGE:
52                 case EFX_PCI_DEVID_SIENA:
53                         *efp = EFX_FAMILY_SIENA;
54                         return (0);
55 #endif /* EFSYS_OPT_SIENA */
56
57 #if EFSYS_OPT_HUNTINGTON
58                 case EFX_PCI_DEVID_HUNTINGTON_PF_UNINIT:
59                         /*
60                          * Hardware default for PF0 of uninitialised Huntington.
61                          * manftest must be able to cope with this device id.
62                          */
63                         *efp = EFX_FAMILY_HUNTINGTON;
64                         return (0);
65
66                 case EFX_PCI_DEVID_FARMINGDALE:
67                 case EFX_PCI_DEVID_GREENPORT:
68                         *efp = EFX_FAMILY_HUNTINGTON;
69                         return (0);
70
71                 case EFX_PCI_DEVID_FARMINGDALE_VF:
72                 case EFX_PCI_DEVID_GREENPORT_VF:
73                         *efp = EFX_FAMILY_HUNTINGTON;
74                         return (0);
75 #endif /* EFSYS_OPT_HUNTINGTON */
76
77 #if EFSYS_OPT_MEDFORD
78                 case EFX_PCI_DEVID_MEDFORD_PF_UNINIT:
79                         /*
80                          * Hardware default for PF0 of uninitialised Medford.
81                          * manftest must be able to cope with this device id.
82                          */
83                         *efp = EFX_FAMILY_MEDFORD;
84                         return (0);
85
86                 case EFX_PCI_DEVID_MEDFORD:
87                         *efp = EFX_FAMILY_MEDFORD;
88                         return (0);
89
90                 case EFX_PCI_DEVID_MEDFORD_VF:
91                         *efp = EFX_FAMILY_MEDFORD;
92                         return (0);
93 #endif /* EFSYS_OPT_MEDFORD */
94
95                 case EFX_PCI_DEVID_FALCON:      /* Obsolete, not supported */
96                 default:
97                         break;
98                 }
99         }
100
101         *efp = EFX_FAMILY_INVALID;
102         return (ENOTSUP);
103 }
104
105
106 #define EFX_BIU_MAGIC0  0x01234567
107 #define EFX_BIU_MAGIC1  0xfedcba98
108
109         __checkReturn   efx_rc_t
110 efx_nic_biu_test(
111         __in            efx_nic_t *enp)
112 {
113         efx_oword_t oword;
114         efx_rc_t rc;
115
116         /*
117          * Write magic values to scratch registers 0 and 1, then
118          * verify that the values were written correctly.  Interleave
119          * the accesses to ensure that the BIU is not just reading
120          * back the cached value that was last written.
121          */
122         EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC0);
123         EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE);
124
125         EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC1);
126         EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE);
127
128         EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE);
129         if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC0) {
130                 rc = EIO;
131                 goto fail1;
132         }
133
134         EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE);
135         if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC1) {
136                 rc = EIO;
137                 goto fail2;
138         }
139
140         /*
141          * Perform the same test, with the values swapped.  This
142          * ensures that subsequent tests don't start with the correct
143          * values already written into the scratch registers.
144          */
145         EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC1);
146         EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE);
147
148         EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC0);
149         EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE);
150
151         EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword, B_TRUE);
152         if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC1) {
153                 rc = EIO;
154                 goto fail3;
155         }
156
157         EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword, B_TRUE);
158         if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC0) {
159                 rc = EIO;
160                 goto fail4;
161         }
162
163         return (0);
164
165 fail4:
166         EFSYS_PROBE(fail4);
167 fail3:
168         EFSYS_PROBE(fail3);
169 fail2:
170         EFSYS_PROBE(fail2);
171 fail1:
172         EFSYS_PROBE1(fail1, efx_rc_t, rc);
173
174         return (rc);
175 }
176
177 #if EFSYS_OPT_SIENA
178
179 static const efx_nic_ops_t      __efx_nic_siena_ops = {
180         siena_nic_probe,                /* eno_probe */
181         NULL,                           /* eno_board_cfg */
182         NULL,                           /* eno_set_drv_limits */
183         siena_nic_reset,                /* eno_reset */
184         siena_nic_init,                 /* eno_init */
185         NULL,                           /* eno_get_vi_pool */
186         NULL,                           /* eno_get_bar_region */
187 #if EFSYS_OPT_DIAG
188         siena_nic_register_test,        /* eno_register_test */
189 #endif  /* EFSYS_OPT_DIAG */
190         siena_nic_fini,                 /* eno_fini */
191         siena_nic_unprobe,              /* eno_unprobe */
192 };
193
194 #endif  /* EFSYS_OPT_SIENA */
195
196 #if EFSYS_OPT_HUNTINGTON
197
198 static const efx_nic_ops_t      __efx_nic_hunt_ops = {
199         ef10_nic_probe,                 /* eno_probe */
200         hunt_board_cfg,                 /* eno_board_cfg */
201         ef10_nic_set_drv_limits,        /* eno_set_drv_limits */
202         ef10_nic_reset,                 /* eno_reset */
203         ef10_nic_init,                  /* eno_init */
204         ef10_nic_get_vi_pool,           /* eno_get_vi_pool */
205         ef10_nic_get_bar_region,        /* eno_get_bar_region */
206 #if EFSYS_OPT_DIAG
207         ef10_nic_register_test,         /* eno_register_test */
208 #endif  /* EFSYS_OPT_DIAG */
209         ef10_nic_fini,                  /* eno_fini */
210         ef10_nic_unprobe,               /* eno_unprobe */
211 };
212
213 #endif  /* EFSYS_OPT_HUNTINGTON */
214
215 #if EFSYS_OPT_MEDFORD
216
217 static const efx_nic_ops_t      __efx_nic_medford_ops = {
218         ef10_nic_probe,                 /* eno_probe */
219         medford_board_cfg,              /* eno_board_cfg */
220         ef10_nic_set_drv_limits,        /* eno_set_drv_limits */
221         ef10_nic_reset,                 /* eno_reset */
222         ef10_nic_init,                  /* eno_init */
223         ef10_nic_get_vi_pool,           /* eno_get_vi_pool */
224         ef10_nic_get_bar_region,        /* eno_get_bar_region */
225 #if EFSYS_OPT_DIAG
226         ef10_nic_register_test,         /* eno_register_test */
227 #endif  /* EFSYS_OPT_DIAG */
228         ef10_nic_fini,                  /* eno_fini */
229         ef10_nic_unprobe,               /* eno_unprobe */
230 };
231
232 #endif  /* EFSYS_OPT_MEDFORD */
233
234
235         __checkReturn   efx_rc_t
236 efx_nic_create(
237         __in            efx_family_t family,
238         __in            efsys_identifier_t *esip,
239         __in            efsys_bar_t *esbp,
240         __in            efsys_lock_t *eslp,
241         __deref_out     efx_nic_t **enpp)
242 {
243         efx_nic_t *enp;
244         efx_rc_t rc;
245
246         EFSYS_ASSERT3U(family, >, EFX_FAMILY_INVALID);
247         EFSYS_ASSERT3U(family, <, EFX_FAMILY_NTYPES);
248
249         /* Allocate a NIC object */
250         EFSYS_KMEM_ALLOC(esip, sizeof (efx_nic_t), enp);
251
252         if (enp == NULL) {
253                 rc = ENOMEM;
254                 goto fail1;
255         }
256
257         enp->en_magic = EFX_NIC_MAGIC;
258
259         switch (family) {
260 #if EFSYS_OPT_SIENA
261         case EFX_FAMILY_SIENA:
262                 enp->en_enop = &__efx_nic_siena_ops;
263                 enp->en_features =
264                     EFX_FEATURE_IPV6 |
265                     EFX_FEATURE_LFSR_HASH_INSERT |
266                     EFX_FEATURE_LINK_EVENTS |
267                     EFX_FEATURE_PERIODIC_MAC_STATS |
268                     EFX_FEATURE_MCDI |
269                     EFX_FEATURE_LOOKAHEAD_SPLIT |
270                     EFX_FEATURE_MAC_HEADER_FILTERS |
271                     EFX_FEATURE_TX_SRC_FILTERS;
272                 break;
273 #endif  /* EFSYS_OPT_SIENA */
274
275 #if EFSYS_OPT_HUNTINGTON
276         case EFX_FAMILY_HUNTINGTON:
277                 enp->en_enop = &__efx_nic_hunt_ops;
278                 enp->en_features =
279                     EFX_FEATURE_IPV6 |
280                     EFX_FEATURE_LINK_EVENTS |
281                     EFX_FEATURE_PERIODIC_MAC_STATS |
282                     EFX_FEATURE_MCDI |
283                     EFX_FEATURE_MAC_HEADER_FILTERS |
284                     EFX_FEATURE_MCDI_DMA |
285                     EFX_FEATURE_PIO_BUFFERS |
286                     EFX_FEATURE_FW_ASSISTED_TSO |
287                     EFX_FEATURE_FW_ASSISTED_TSO_V2 |
288                     EFX_FEATURE_PACKED_STREAM;
289                 break;
290 #endif  /* EFSYS_OPT_HUNTINGTON */
291
292 #if EFSYS_OPT_MEDFORD
293         case EFX_FAMILY_MEDFORD:
294                 enp->en_enop = &__efx_nic_medford_ops;
295                 /*
296                  * FW_ASSISTED_TSO omitted as Medford only supports firmware
297                  * assisted TSO version 2, not the v1 scheme used on Huntington.
298                  */
299                 enp->en_features =
300                     EFX_FEATURE_IPV6 |
301                     EFX_FEATURE_LINK_EVENTS |
302                     EFX_FEATURE_PERIODIC_MAC_STATS |
303                     EFX_FEATURE_MCDI |
304                     EFX_FEATURE_MAC_HEADER_FILTERS |
305                     EFX_FEATURE_MCDI_DMA |
306                     EFX_FEATURE_PIO_BUFFERS |
307                     EFX_FEATURE_FW_ASSISTED_TSO_V2 |
308                     EFX_FEATURE_PACKED_STREAM;
309                 break;
310 #endif  /* EFSYS_OPT_MEDFORD */
311
312         default:
313                 rc = ENOTSUP;
314                 goto fail2;
315         }
316
317         enp->en_family = family;
318         enp->en_esip = esip;
319         enp->en_esbp = esbp;
320         enp->en_eslp = eslp;
321
322         *enpp = enp;
323
324         return (0);
325
326 fail2:
327         EFSYS_PROBE(fail2);
328
329         enp->en_magic = 0;
330
331         /* Free the NIC object */
332         EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
333
334 fail1:
335         EFSYS_PROBE1(fail1, efx_rc_t, rc);
336
337         return (rc);
338 }
339
340         __checkReturn   efx_rc_t
341 efx_nic_probe(
342         __in            efx_nic_t *enp)
343 {
344         const efx_nic_ops_t *enop;
345         efx_rc_t rc;
346
347         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
348 #if EFSYS_OPT_MCDI
349         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
350 #endif  /* EFSYS_OPT_MCDI */
351         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_PROBE));
352
353         enop = enp->en_enop;
354         if ((rc = enop->eno_probe(enp)) != 0)
355                 goto fail1;
356
357         if ((rc = efx_phy_probe(enp)) != 0)
358                 goto fail2;
359
360         enp->en_mod_flags |= EFX_MOD_PROBE;
361
362         return (0);
363
364 fail2:
365         EFSYS_PROBE(fail2);
366
367         enop->eno_unprobe(enp);
368
369 fail1:
370         EFSYS_PROBE1(fail1, efx_rc_t, rc);
371
372         return (rc);
373 }
374
375         __checkReturn   efx_rc_t
376 efx_nic_set_drv_limits(
377         __inout         efx_nic_t *enp,
378         __in            efx_drv_limits_t *edlp)
379 {
380         const efx_nic_ops_t *enop = enp->en_enop;
381         efx_rc_t rc;
382
383         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
384         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
385
386         if (enop->eno_set_drv_limits != NULL) {
387                 if ((rc = enop->eno_set_drv_limits(enp, edlp)) != 0)
388                         goto fail1;
389         }
390
391         return (0);
392
393 fail1:
394         EFSYS_PROBE1(fail1, efx_rc_t, rc);
395
396         return (rc);
397 }
398
399         __checkReturn   efx_rc_t
400 efx_nic_get_bar_region(
401         __in            efx_nic_t *enp,
402         __in            efx_nic_region_t region,
403         __out           uint32_t *offsetp,
404         __out           size_t *sizep)
405 {
406         const efx_nic_ops_t *enop = enp->en_enop;
407         efx_rc_t rc;
408
409         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
410         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
411         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
412
413         if (enop->eno_get_bar_region == NULL) {
414                 rc = ENOTSUP;
415                 goto fail1;
416         }
417         if ((rc = (enop->eno_get_bar_region)(enp,
418                     region, offsetp, sizep)) != 0) {
419                 goto fail2;
420         }
421
422         return (0);
423
424 fail2:
425         EFSYS_PROBE(fail2);
426
427 fail1:
428         EFSYS_PROBE1(fail1, efx_rc_t, rc);
429
430         return (rc);
431 }
432
433
434         __checkReturn   efx_rc_t
435 efx_nic_get_vi_pool(
436         __in            efx_nic_t *enp,
437         __out           uint32_t *evq_countp,
438         __out           uint32_t *rxq_countp,
439         __out           uint32_t *txq_countp)
440 {
441         const efx_nic_ops_t *enop = enp->en_enop;
442         efx_nic_cfg_t *encp = &enp->en_nic_cfg;
443         efx_rc_t rc;
444
445         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
446         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
447         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
448
449         if (enop->eno_get_vi_pool != NULL) {
450                 uint32_t vi_count = 0;
451
452                 if ((rc = (enop->eno_get_vi_pool)(enp, &vi_count)) != 0)
453                         goto fail1;
454
455                 *evq_countp = vi_count;
456                 *rxq_countp = vi_count;
457                 *txq_countp = vi_count;
458         } else {
459                 /* Use NIC limits as default value */
460                 *evq_countp = encp->enc_evq_limit;
461                 *rxq_countp = encp->enc_rxq_limit;
462                 *txq_countp = encp->enc_txq_limit;
463         }
464
465         return (0);
466
467 fail1:
468         EFSYS_PROBE1(fail1, efx_rc_t, rc);
469
470         return (rc);
471 }
472
473
474         __checkReturn   efx_rc_t
475 efx_nic_init(
476         __in            efx_nic_t *enp)
477 {
478         const efx_nic_ops_t *enop = enp->en_enop;
479         efx_rc_t rc;
480
481         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
482         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
483
484         if (enp->en_mod_flags & EFX_MOD_NIC) {
485                 rc = EINVAL;
486                 goto fail1;
487         }
488
489         if ((rc = enop->eno_init(enp)) != 0)
490                 goto fail2;
491
492         enp->en_mod_flags |= EFX_MOD_NIC;
493
494         return (0);
495
496 fail2:
497         EFSYS_PROBE(fail2);
498 fail1:
499         EFSYS_PROBE1(fail1, efx_rc_t, rc);
500
501         return (rc);
502 }
503
504                         void
505 efx_nic_fini(
506         __in            efx_nic_t *enp)
507 {
508         const efx_nic_ops_t *enop = enp->en_enop;
509
510         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
511         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
512         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_NIC);
513         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
514         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
515         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
516         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
517
518         enop->eno_fini(enp);
519
520         enp->en_mod_flags &= ~EFX_MOD_NIC;
521 }
522
523                         void
524 efx_nic_unprobe(
525         __in            efx_nic_t *enp)
526 {
527         const efx_nic_ops_t *enop = enp->en_enop;
528
529         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
530 #if EFSYS_OPT_MCDI
531         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
532 #endif  /* EFSYS_OPT_MCDI */
533         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
534         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
535         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
536         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
537         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
538         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
539
540         efx_phy_unprobe(enp);
541
542         enop->eno_unprobe(enp);
543
544         enp->en_mod_flags &= ~EFX_MOD_PROBE;
545 }
546
547                         void
548 efx_nic_destroy(
549         __in    efx_nic_t *enp)
550 {
551         efsys_identifier_t *esip = enp->en_esip;
552
553         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
554         EFSYS_ASSERT3U(enp->en_mod_flags, ==, 0);
555
556         enp->en_family = EFX_FAMILY_INVALID;
557         enp->en_esip = NULL;
558         enp->en_esbp = NULL;
559         enp->en_eslp = NULL;
560
561         enp->en_enop = NULL;
562
563         enp->en_magic = 0;
564
565         /* Free the NIC object */
566         EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
567 }
568
569         __checkReturn   efx_rc_t
570 efx_nic_reset(
571         __in            efx_nic_t *enp)
572 {
573         const efx_nic_ops_t *enop = enp->en_enop;
574         unsigned int mod_flags;
575         efx_rc_t rc;
576
577         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
578         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
579         /*
580          * All modules except the MCDI, PROBE, NVRAM, VPD, MON
581          * (which we do not reset here) must have been shut down or never
582          * initialized.
583          *
584          * A rule of thumb here is: If the controller or MC reboots, is *any*
585          * state lost. If it's lost and needs reapplying, then the module
586          * *must* not be initialised during the reset.
587          */
588         mod_flags = enp->en_mod_flags;
589         mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM |
590                     EFX_MOD_VPD | EFX_MOD_MON);
591         EFSYS_ASSERT3U(mod_flags, ==, 0);
592         if (mod_flags != 0) {
593                 rc = EINVAL;
594                 goto fail1;
595         }
596
597         if ((rc = enop->eno_reset(enp)) != 0)
598                 goto fail2;
599
600         return (0);
601
602 fail2:
603         EFSYS_PROBE(fail2);
604 fail1:
605         EFSYS_PROBE1(fail1, efx_rc_t, rc);
606
607         return (rc);
608 }
609
610                         const efx_nic_cfg_t *
611 efx_nic_cfg_get(
612         __in            efx_nic_t *enp)
613 {
614         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
615
616         return (&(enp->en_nic_cfg));
617 }
618
619         __checkReturn           efx_rc_t
620 efx_nic_get_fw_version(
621         __in                    efx_nic_t *enp,
622         __out                   efx_nic_fw_info_t *enfip)
623 {
624         uint16_t mc_fw_version[4];
625         efx_rc_t rc;
626
627         if (enfip == NULL) {
628                 rc = EINVAL;
629                 goto fail1;
630         }
631
632         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
633         EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
634
635         rc = efx_mcdi_version(enp, mc_fw_version, NULL, NULL);
636         if (rc != 0)
637                 goto fail2;
638
639         rc = efx_mcdi_get_capabilities(enp, NULL,
640                                        &enfip->enfi_rx_dpcpu_fw_id,
641                                        &enfip->enfi_tx_dpcpu_fw_id,
642                                        NULL, NULL);
643         if (rc == 0) {
644                 enfip->enfi_dpcpu_fw_ids_valid = B_TRUE;
645         } else if (rc == ENOTSUP) {
646                 enfip->enfi_dpcpu_fw_ids_valid = B_FALSE;
647                 enfip->enfi_rx_dpcpu_fw_id = 0;
648                 enfip->enfi_tx_dpcpu_fw_id = 0;
649         } else {
650                 goto fail3;
651         }
652
653         memcpy(enfip->enfi_mc_fw_version, mc_fw_version, sizeof(mc_fw_version));
654
655         return (0);
656
657 fail3:
658         EFSYS_PROBE(fail3);
659 fail2:
660         EFSYS_PROBE(fail2);
661 fail1:
662         EFSYS_PROBE1(fail1, efx_rc_t, rc);
663
664         return (rc);
665 }
666
667 #if EFSYS_OPT_DIAG
668
669         __checkReturn   efx_rc_t
670 efx_nic_register_test(
671         __in            efx_nic_t *enp)
672 {
673         const efx_nic_ops_t *enop = enp->en_enop;
674         efx_rc_t rc;
675
676         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
677         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
678         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
679
680         if ((rc = enop->eno_register_test(enp)) != 0)
681                 goto fail1;
682
683         return (0);
684
685 fail1:
686         EFSYS_PROBE1(fail1, efx_rc_t, rc);
687
688         return (rc);
689 }
690
691         __checkReturn   efx_rc_t
692 efx_nic_test_registers(
693         __in            efx_nic_t *enp,
694         __in            efx_register_set_t *rsp,
695         __in            size_t count)
696 {
697         unsigned int bit;
698         efx_oword_t original;
699         efx_oword_t reg;
700         efx_oword_t buf;
701         efx_rc_t rc;
702
703         while (count > 0) {
704                 /* This function is only suitable for registers */
705                 EFSYS_ASSERT(rsp->rows == 1);
706
707                 /* bit sweep on and off */
708                 EFSYS_BAR_READO(enp->en_esbp, rsp->address, &original,
709                             B_TRUE);
710                 for (bit = 0; bit < 128; bit++) {
711                         /* Is this bit in the mask? */
712                         if (~(rsp->mask.eo_u32[bit >> 5]) & (1 << bit))
713                                 continue;
714
715                         /* Test this bit can be set in isolation */
716                         reg = original;
717                         EFX_AND_OWORD(reg, rsp->mask);
718                         EFX_SET_OWORD_BIT(reg, bit);
719
720                         EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &reg,
721                                     B_TRUE);
722                         EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf,
723                                     B_TRUE);
724
725                         EFX_AND_OWORD(buf, rsp->mask);
726                         if (memcmp(&reg, &buf, sizeof (reg))) {
727                                 rc = EIO;
728                                 goto fail1;
729                         }
730
731                         /* Test this bit can be cleared in isolation */
732                         EFX_OR_OWORD(reg, rsp->mask);
733                         EFX_CLEAR_OWORD_BIT(reg, bit);
734
735                         EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &reg,
736                                     B_TRUE);
737                         EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf,
738                                     B_TRUE);
739
740                         EFX_AND_OWORD(buf, rsp->mask);
741                         if (memcmp(&reg, &buf, sizeof (reg))) {
742                                 rc = EIO;
743                                 goto fail2;
744                         }
745                 }
746
747                 /* Restore the old value */
748                 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original,
749                             B_TRUE);
750
751                 --count;
752                 ++rsp;
753         }
754
755         return (0);
756
757 fail2:
758         EFSYS_PROBE(fail2);
759 fail1:
760         EFSYS_PROBE1(fail1, efx_rc_t, rc);
761
762         /* Restore the old value */
763         EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, B_TRUE);
764
765         return (rc);
766 }
767
768         __checkReturn   efx_rc_t
769 efx_nic_test_tables(
770         __in            efx_nic_t *enp,
771         __in            efx_register_set_t *rsp,
772         __in            efx_pattern_type_t pattern,
773         __in            size_t count)
774 {
775         efx_sram_pattern_fn_t func;
776         unsigned int index;
777         unsigned int address;
778         efx_oword_t reg;
779         efx_oword_t buf;
780         efx_rc_t rc;
781
782         EFSYS_ASSERT(pattern < EFX_PATTERN_NTYPES);
783         func = __efx_sram_pattern_fns[pattern];
784
785         while (count > 0) {
786                 /* Write */
787                 address = rsp->address;
788                 for (index = 0; index < rsp->rows; ++index) {
789                         func(2 * index + 0, B_FALSE, &reg.eo_qword[0]);
790                         func(2 * index + 1, B_FALSE, &reg.eo_qword[1]);
791                         EFX_AND_OWORD(reg, rsp->mask);
792                         EFSYS_BAR_WRITEO(enp->en_esbp, address, &reg, B_TRUE);
793
794                         address += rsp->step;
795                 }
796
797                 /* Read */
798                 address = rsp->address;
799                 for (index = 0; index < rsp->rows; ++index) {
800                         func(2 * index + 0, B_FALSE, &reg.eo_qword[0]);
801                         func(2 * index + 1, B_FALSE, &reg.eo_qword[1]);
802                         EFX_AND_OWORD(reg, rsp->mask);
803                         EFSYS_BAR_READO(enp->en_esbp, address, &buf, B_TRUE);
804                         if (memcmp(&reg, &buf, sizeof (reg))) {
805                                 rc = EIO;
806                                 goto fail1;
807                         }
808
809                         address += rsp->step;
810                 }
811
812                 ++rsp;
813                 --count;
814         }
815
816         return (0);
817
818 fail1:
819         EFSYS_PROBE1(fail1, efx_rc_t, rc);
820
821         return (rc);
822 }
823
824 #endif  /* EFSYS_OPT_DIAG */
825
826 #if EFSYS_OPT_LOOPBACK
827
828 extern                  void
829 efx_loopback_mask(
830         __in    efx_loopback_kind_t loopback_kind,
831         __out   efx_qword_t *maskp)
832 {
833         efx_qword_t mask;
834
835         EFSYS_ASSERT3U(loopback_kind, <, EFX_LOOPBACK_NKINDS);
836         EFSYS_ASSERT(maskp != NULL);
837
838         /* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespace agree */
839         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_NONE == EFX_LOOPBACK_OFF);
840         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_DATA == EFX_LOOPBACK_DATA);
841         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMAC == EFX_LOOPBACK_GMAC);
842         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII == EFX_LOOPBACK_XGMII);
843         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGXS == EFX_LOOPBACK_XGXS);
844         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI == EFX_LOOPBACK_XAUI);
845         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII == EFX_LOOPBACK_GMII);
846         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII == EFX_LOOPBACK_SGMII);
847         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGBR == EFX_LOOPBACK_XGBR);
848         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI == EFX_LOOPBACK_XFI);
849         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_FAR == EFX_LOOPBACK_XAUI_FAR);
850         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_FAR == EFX_LOOPBACK_GMII_FAR);
851         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII_FAR == EFX_LOOPBACK_SGMII_FAR);
852         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_FAR == EFX_LOOPBACK_XFI_FAR);
853         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GPHY == EFX_LOOPBACK_GPHY);
854         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS == EFX_LOOPBACK_PHY_XS);
855         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PCS == EFX_LOOPBACK_PCS);
856         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMAPMD == EFX_LOOPBACK_PMA_PMD);
857         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XPORT == EFX_LOOPBACK_XPORT);
858         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII_WS == EFX_LOOPBACK_XGMII_WS);
859         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_WS == EFX_LOOPBACK_XAUI_WS);
860         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_WS_FAR ==
861             EFX_LOOPBACK_XAUI_WS_FAR);
862         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_WS_NEAR ==
863             EFX_LOOPBACK_XAUI_WS_NEAR);
864         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_WS == EFX_LOOPBACK_GMII_WS);
865         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_WS == EFX_LOOPBACK_XFI_WS);
866         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_WS_FAR ==
867             EFX_LOOPBACK_XFI_WS_FAR);
868         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS_WS == EFX_LOOPBACK_PHYXS_WS);
869         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMA_INT == EFX_LOOPBACK_PMA_INT);
870         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_NEAR == EFX_LOOPBACK_SD_NEAR);
871         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FAR == EFX_LOOPBACK_SD_FAR);
872         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMA_INT_WS ==
873             EFX_LOOPBACK_PMA_INT_WS);
874         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FEP2_WS ==
875             EFX_LOOPBACK_SD_FEP2_WS);
876         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FEP1_5_WS ==
877             EFX_LOOPBACK_SD_FEP1_5_WS);
878         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FEP_WS == EFX_LOOPBACK_SD_FEP_WS);
879         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FES_WS == EFX_LOOPBACK_SD_FES_WS);
880
881         /* Build bitmask of possible loopback types */
882         EFX_ZERO_QWORD(mask);
883
884         if ((loopback_kind == EFX_LOOPBACK_KIND_OFF) ||
885             (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
886                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_OFF);
887         }
888
889         if ((loopback_kind == EFX_LOOPBACK_KIND_MAC) ||
890             (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
891                 /*
892                  * The "MAC" grouping has historically been used by drivers to
893                  * mean loopbacks supported by on-chip hardware. Keep that
894                  * meaning here, and include on-chip PHY layer loopbacks.
895                  */
896                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_DATA);
897                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMAC);
898                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGMII);
899                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGXS);
900                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI);
901                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII);
902                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII);
903                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGBR);
904                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI);
905                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI_FAR);
906                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII_FAR);
907                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII_FAR);
908                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI_FAR);
909                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_INT);
910                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_NEAR);
911                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_FAR);
912         }
913
914         if ((loopback_kind == EFX_LOOPBACK_KIND_PHY) ||
915             (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
916                 /*
917                  * The "PHY" grouping has historically been used by drivers to
918                  * mean loopbacks supported by off-chip hardware. Keep that
919                  * meaning here.
920                  */
921                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GPHY);
922                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PHY_XS);
923                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PCS);
924                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_PMD);
925         }
926
927         *maskp = mask;
928 }
929
930         __checkReturn   efx_rc_t
931 efx_mcdi_get_loopback_modes(
932         __in            efx_nic_t *enp)
933 {
934         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
935         efx_mcdi_req_t req;
936         uint8_t payload[MAX(MC_CMD_GET_LOOPBACK_MODES_IN_LEN,
937                             MC_CMD_GET_LOOPBACK_MODES_OUT_LEN)];
938         efx_qword_t mask;
939         efx_qword_t modes;
940         efx_rc_t rc;
941
942         (void) memset(payload, 0, sizeof (payload));
943         req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES;
944         req.emr_in_buf = payload;
945         req.emr_in_length = MC_CMD_GET_LOOPBACK_MODES_IN_LEN;
946         req.emr_out_buf = payload;
947         req.emr_out_length = MC_CMD_GET_LOOPBACK_MODES_OUT_LEN;
948
949         efx_mcdi_execute(enp, &req);
950
951         if (req.emr_rc != 0) {
952                 rc = req.emr_rc;
953                 goto fail1;
954         }
955
956         if (req.emr_out_length_used <
957             MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST +
958             MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN) {
959                 rc = EMSGSIZE;
960                 goto fail2;
961         }
962
963         /*
964          * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree
965          * in efx_loopback_mask() and in siena_phy.c:siena_phy_get_link().
966          */
967         efx_loopback_mask(EFX_LOOPBACK_KIND_ALL, &mask);
968
969         EFX_AND_QWORD(mask,
970             *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_SUGGESTED));
971
972         modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_100M);
973         EFX_AND_QWORD(modes, mask);
974         encp->enc_loopback_types[EFX_LINK_100FDX] = modes;
975
976         modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_1G);
977         EFX_AND_QWORD(modes, mask);
978         encp->enc_loopback_types[EFX_LINK_1000FDX] = modes;
979
980         modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_10G);
981         EFX_AND_QWORD(modes, mask);
982         encp->enc_loopback_types[EFX_LINK_10000FDX] = modes;
983
984         if (req.emr_out_length_used >=
985             MC_CMD_GET_LOOPBACK_MODES_OUT_40G_OFST +
986             MC_CMD_GET_LOOPBACK_MODES_OUT_40G_LEN) {
987                 /* Response includes 40G loopback modes */
988                 modes =
989                     *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_40G);
990                 EFX_AND_QWORD(modes, mask);
991                 encp->enc_loopback_types[EFX_LINK_40000FDX] = modes;
992         }
993
994         EFX_ZERO_QWORD(modes);
995         EFX_SET_QWORD_BIT(modes, EFX_LOOPBACK_OFF);
996         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_100FDX]);
997         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_1000FDX]);
998         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_10000FDX]);
999         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_40000FDX]);
1000         encp->enc_loopback_types[EFX_LINK_UNKNOWN] = modes;
1001
1002         return (0);
1003
1004 fail2:
1005         EFSYS_PROBE(fail2);
1006 fail1:
1007         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1008
1009         return (rc);
1010 }
1011
1012 #endif /* EFSYS_OPT_LOOPBACK */
1013
1014         __checkReturn   efx_rc_t
1015 efx_nic_calculate_pcie_link_bandwidth(
1016         __in            uint32_t pcie_link_width,
1017         __in            uint32_t pcie_link_gen,
1018         __out           uint32_t *bandwidth_mbpsp)
1019 {
1020         uint32_t lane_bandwidth;
1021         uint32_t total_bandwidth;
1022         efx_rc_t rc;
1023
1024         if ((pcie_link_width == 0) || (pcie_link_width > 16) ||
1025             !ISP2(pcie_link_width)) {
1026                 rc = EINVAL;
1027                 goto fail1;
1028         }
1029
1030         switch (pcie_link_gen) {
1031         case EFX_PCIE_LINK_SPEED_GEN1:
1032                 /* 2.5 Gb/s raw bandwidth with 8b/10b encoding */
1033                 lane_bandwidth = 2000;
1034                 break;
1035         case EFX_PCIE_LINK_SPEED_GEN2:
1036                 /* 5.0 Gb/s raw bandwidth with 8b/10b encoding */
1037                 lane_bandwidth = 4000;
1038                 break;
1039         case EFX_PCIE_LINK_SPEED_GEN3:
1040                 /* 8.0 Gb/s raw bandwidth with 128b/130b encoding */
1041                 lane_bandwidth = 7877;
1042                 break;
1043         default:
1044                 rc = EINVAL;
1045                 goto fail2;
1046         }
1047
1048         total_bandwidth = lane_bandwidth * pcie_link_width;
1049         *bandwidth_mbpsp = total_bandwidth;
1050
1051         return (0);
1052
1053 fail2:
1054         EFSYS_PROBE(fail2);
1055 fail1:
1056         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1057
1058         return (rc);
1059 }
1060
1061
1062         __checkReturn   efx_rc_t
1063 efx_nic_check_pcie_link_speed(
1064         __in            efx_nic_t *enp,
1065         __in            uint32_t pcie_link_width,
1066         __in            uint32_t pcie_link_gen,
1067         __out           efx_pcie_link_performance_t *resultp)
1068 {
1069         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1070         uint32_t bandwidth;
1071         efx_pcie_link_performance_t result;
1072         efx_rc_t rc;
1073
1074         if ((encp->enc_required_pcie_bandwidth_mbps == 0) ||
1075             (pcie_link_width == 0) || (pcie_link_width == 32) ||
1076             (pcie_link_gen == 0)) {
1077                 /*
1078                  * No usable info on what is required and/or in use. In virtual
1079                  * machines, sometimes the PCIe link width is reported as 0 or
1080                  * 32, or the speed as 0.
1081                  */
1082                 result = EFX_PCIE_LINK_PERFORMANCE_UNKNOWN_BANDWIDTH;
1083                 goto out;
1084         }
1085
1086         /* Calculate the available bandwidth in megabits per second */
1087         rc = efx_nic_calculate_pcie_link_bandwidth(pcie_link_width,
1088                                             pcie_link_gen, &bandwidth);
1089         if (rc != 0)
1090                 goto fail1;
1091
1092         if (bandwidth < encp->enc_required_pcie_bandwidth_mbps) {
1093                 result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_BANDWIDTH;
1094         } else if (pcie_link_gen < encp->enc_max_pcie_link_gen) {
1095                 /* The link provides enough bandwidth but not optimal latency */
1096                 result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_LATENCY;
1097         } else {
1098                 result = EFX_PCIE_LINK_PERFORMANCE_OPTIMAL;
1099         }
1100
1101 out:
1102         *resultp = result;
1103
1104         return (0);
1105
1106 fail1:
1107         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1108
1109         return (rc);
1110 }