]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/sfxge/common/efx_nic.c
Merge once more from ^/vendor/llvm-project/release-10.x, to get the
[FreeBSD/FreeBSD.git] / sys / dev / sfxge / common / efx_nic.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2007-2016 Solarflare Communications Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  *    this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  *    this list of conditions and the following disclaimer in the documentation
14  *    and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * The views and conclusions contained in the software and documentation are
29  * those of the authors and should not be interpreted as representing official
30  * policies, either expressed or implied, of the FreeBSD Project.
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include "efx.h"
37 #include "efx_impl.h"
38
39
40         __checkReturn   efx_rc_t
41 efx_family(
42         __in            uint16_t venid,
43         __in            uint16_t devid,
44         __out           efx_family_t *efp,
45         __out           unsigned int *membarp)
46 {
47         if (venid == EFX_PCI_VENID_SFC) {
48                 switch (devid) {
49 #if EFSYS_OPT_SIENA
50                 case EFX_PCI_DEVID_SIENA_F1_UNINIT:
51                         /*
52                          * Hardware default for PF0 of uninitialised Siena.
53                          * manftest must be able to cope with this device id.
54                          */
55                 case EFX_PCI_DEVID_BETHPAGE:
56                 case EFX_PCI_DEVID_SIENA:
57                         *efp = EFX_FAMILY_SIENA;
58                         *membarp = EFX_MEM_BAR_SIENA;
59                         return (0);
60 #endif /* EFSYS_OPT_SIENA */
61
62 #if EFSYS_OPT_HUNTINGTON
63                 case EFX_PCI_DEVID_HUNTINGTON_PF_UNINIT:
64                         /*
65                          * Hardware default for PF0 of uninitialised Huntington.
66                          * manftest must be able to cope with this device id.
67                          */
68                 case EFX_PCI_DEVID_FARMINGDALE:
69                 case EFX_PCI_DEVID_GREENPORT:
70                         *efp = EFX_FAMILY_HUNTINGTON;
71                         *membarp = EFX_MEM_BAR_HUNTINGTON_PF;
72                         return (0);
73
74                 case EFX_PCI_DEVID_FARMINGDALE_VF:
75                 case EFX_PCI_DEVID_GREENPORT_VF:
76                         *efp = EFX_FAMILY_HUNTINGTON;
77                         *membarp = EFX_MEM_BAR_HUNTINGTON_VF;
78                         return (0);
79 #endif /* EFSYS_OPT_HUNTINGTON */
80
81 #if EFSYS_OPT_MEDFORD
82                 case EFX_PCI_DEVID_MEDFORD_PF_UNINIT:
83                         /*
84                          * Hardware default for PF0 of uninitialised Medford.
85                          * manftest must be able to cope with this device id.
86                          */
87                 case EFX_PCI_DEVID_MEDFORD:
88                         *efp = EFX_FAMILY_MEDFORD;
89                         *membarp = EFX_MEM_BAR_MEDFORD_PF;
90                         return (0);
91
92                 case EFX_PCI_DEVID_MEDFORD_VF:
93                         *efp = EFX_FAMILY_MEDFORD;
94                         *membarp = EFX_MEM_BAR_MEDFORD_VF;
95                         return (0);
96 #endif /* EFSYS_OPT_MEDFORD */
97
98 #if EFSYS_OPT_MEDFORD2
99                 case EFX_PCI_DEVID_MEDFORD2_PF_UNINIT:
100                         /*
101                          * Hardware default for PF0 of uninitialised Medford2.
102                          * manftest must be able to cope with this device id.
103                          */
104                 case EFX_PCI_DEVID_MEDFORD2:
105                 case EFX_PCI_DEVID_MEDFORD2_VF:
106                         *efp = EFX_FAMILY_MEDFORD2;
107                         *membarp = EFX_MEM_BAR_MEDFORD2;
108                         return (0);
109 #endif /* EFSYS_OPT_MEDFORD2 */
110
111                 case EFX_PCI_DEVID_FALCON:      /* Obsolete, not supported */
112                 default:
113                         break;
114                 }
115         }
116
117         *efp = EFX_FAMILY_INVALID;
118         return (ENOTSUP);
119 }
120
121
122 #if EFSYS_OPT_SIENA
123
124 static const efx_nic_ops_t      __efx_nic_siena_ops = {
125         siena_nic_probe,                /* eno_probe */
126         NULL,                           /* eno_board_cfg */
127         NULL,                           /* eno_set_drv_limits */
128         siena_nic_reset,                /* eno_reset */
129         siena_nic_init,                 /* eno_init */
130         NULL,                           /* eno_get_vi_pool */
131         NULL,                           /* eno_get_bar_region */
132         NULL,                           /* eno_hw_unavailable */
133         NULL,                           /* eno_set_hw_unavailable */
134 #if EFSYS_OPT_DIAG
135         siena_nic_register_test,        /* eno_register_test */
136 #endif  /* EFSYS_OPT_DIAG */
137         siena_nic_fini,                 /* eno_fini */
138         siena_nic_unprobe,              /* eno_unprobe */
139 };
140
141 #endif  /* EFSYS_OPT_SIENA */
142
143 #if EFSYS_OPT_HUNTINGTON
144
145 static const efx_nic_ops_t      __efx_nic_hunt_ops = {
146         ef10_nic_probe,                 /* eno_probe */
147         hunt_board_cfg,                 /* eno_board_cfg */
148         ef10_nic_set_drv_limits,        /* eno_set_drv_limits */
149         ef10_nic_reset,                 /* eno_reset */
150         ef10_nic_init,                  /* eno_init */
151         ef10_nic_get_vi_pool,           /* eno_get_vi_pool */
152         ef10_nic_get_bar_region,        /* eno_get_bar_region */
153         ef10_nic_hw_unavailable,        /* eno_hw_unavailable */
154         ef10_nic_set_hw_unavailable,    /* eno_set_hw_unavailable */
155 #if EFSYS_OPT_DIAG
156         ef10_nic_register_test,         /* eno_register_test */
157 #endif  /* EFSYS_OPT_DIAG */
158         ef10_nic_fini,                  /* eno_fini */
159         ef10_nic_unprobe,               /* eno_unprobe */
160 };
161
162 #endif  /* EFSYS_OPT_HUNTINGTON */
163
164 #if EFSYS_OPT_MEDFORD
165
166 static const efx_nic_ops_t      __efx_nic_medford_ops = {
167         ef10_nic_probe,                 /* eno_probe */
168         medford_board_cfg,              /* eno_board_cfg */
169         ef10_nic_set_drv_limits,        /* eno_set_drv_limits */
170         ef10_nic_reset,                 /* eno_reset */
171         ef10_nic_init,                  /* eno_init */
172         ef10_nic_get_vi_pool,           /* eno_get_vi_pool */
173         ef10_nic_get_bar_region,        /* eno_get_bar_region */
174         ef10_nic_hw_unavailable,        /* eno_hw_unavailable */
175         ef10_nic_set_hw_unavailable,    /* eno_set_hw_unavailable */
176 #if EFSYS_OPT_DIAG
177         ef10_nic_register_test,         /* eno_register_test */
178 #endif  /* EFSYS_OPT_DIAG */
179         ef10_nic_fini,                  /* eno_fini */
180         ef10_nic_unprobe,               /* eno_unprobe */
181 };
182
183 #endif  /* EFSYS_OPT_MEDFORD */
184
185 #if EFSYS_OPT_MEDFORD2
186
187 static const efx_nic_ops_t      __efx_nic_medford2_ops = {
188         ef10_nic_probe,                 /* eno_probe */
189         medford2_board_cfg,             /* eno_board_cfg */
190         ef10_nic_set_drv_limits,        /* eno_set_drv_limits */
191         ef10_nic_reset,                 /* eno_reset */
192         ef10_nic_init,                  /* eno_init */
193         ef10_nic_get_vi_pool,           /* eno_get_vi_pool */
194         ef10_nic_get_bar_region,        /* eno_get_bar_region */
195         ef10_nic_hw_unavailable,        /* eno_hw_unavailable */
196         ef10_nic_set_hw_unavailable,    /* eno_set_hw_unavailable */
197 #if EFSYS_OPT_DIAG
198         ef10_nic_register_test,         /* eno_register_test */
199 #endif  /* EFSYS_OPT_DIAG */
200         ef10_nic_fini,                  /* eno_fini */
201         ef10_nic_unprobe,               /* eno_unprobe */
202 };
203
204 #endif  /* EFSYS_OPT_MEDFORD2 */
205
206
207         __checkReturn   efx_rc_t
208 efx_nic_create(
209         __in            efx_family_t family,
210         __in            efsys_identifier_t *esip,
211         __in            efsys_bar_t *esbp,
212         __in            efsys_lock_t *eslp,
213         __deref_out     efx_nic_t **enpp)
214 {
215         efx_nic_t *enp;
216         efx_rc_t rc;
217
218         EFSYS_ASSERT3U(family, >, EFX_FAMILY_INVALID);
219         EFSYS_ASSERT3U(family, <, EFX_FAMILY_NTYPES);
220
221         /* Allocate a NIC object */
222         EFSYS_KMEM_ALLOC(esip, sizeof (efx_nic_t), enp);
223
224         if (enp == NULL) {
225                 rc = ENOMEM;
226                 goto fail1;
227         }
228
229         enp->en_magic = EFX_NIC_MAGIC;
230
231         switch (family) {
232 #if EFSYS_OPT_SIENA
233         case EFX_FAMILY_SIENA:
234                 enp->en_enop = &__efx_nic_siena_ops;
235                 enp->en_features =
236                     EFX_FEATURE_IPV6 |
237                     EFX_FEATURE_LFSR_HASH_INSERT |
238                     EFX_FEATURE_LINK_EVENTS |
239                     EFX_FEATURE_PERIODIC_MAC_STATS |
240                     EFX_FEATURE_MCDI |
241                     EFX_FEATURE_LOOKAHEAD_SPLIT |
242                     EFX_FEATURE_MAC_HEADER_FILTERS |
243                     EFX_FEATURE_TX_SRC_FILTERS;
244                 break;
245 #endif  /* EFSYS_OPT_SIENA */
246
247 #if EFSYS_OPT_HUNTINGTON
248         case EFX_FAMILY_HUNTINGTON:
249                 enp->en_enop = &__efx_nic_hunt_ops;
250                 enp->en_features =
251                     EFX_FEATURE_IPV6 |
252                     EFX_FEATURE_LINK_EVENTS |
253                     EFX_FEATURE_PERIODIC_MAC_STATS |
254                     EFX_FEATURE_MCDI |
255                     EFX_FEATURE_MAC_HEADER_FILTERS |
256                     EFX_FEATURE_MCDI_DMA |
257                     EFX_FEATURE_PIO_BUFFERS |
258                     EFX_FEATURE_FW_ASSISTED_TSO |
259                     EFX_FEATURE_FW_ASSISTED_TSO_V2 |
260                     EFX_FEATURE_PACKED_STREAM |
261                     EFX_FEATURE_TXQ_CKSUM_OP_DESC;
262                 break;
263 #endif  /* EFSYS_OPT_HUNTINGTON */
264
265 #if EFSYS_OPT_MEDFORD
266         case EFX_FAMILY_MEDFORD:
267                 enp->en_enop = &__efx_nic_medford_ops;
268                 /*
269                  * FW_ASSISTED_TSO omitted as Medford only supports firmware
270                  * assisted TSO version 2, not the v1 scheme used on Huntington.
271                  */
272                 enp->en_features =
273                     EFX_FEATURE_IPV6 |
274                     EFX_FEATURE_LINK_EVENTS |
275                     EFX_FEATURE_PERIODIC_MAC_STATS |
276                     EFX_FEATURE_MCDI |
277                     EFX_FEATURE_MAC_HEADER_FILTERS |
278                     EFX_FEATURE_MCDI_DMA |
279                     EFX_FEATURE_PIO_BUFFERS |
280                     EFX_FEATURE_FW_ASSISTED_TSO_V2 |
281                     EFX_FEATURE_PACKED_STREAM |
282                     EFX_FEATURE_TXQ_CKSUM_OP_DESC;
283                 break;
284 #endif  /* EFSYS_OPT_MEDFORD */
285
286 #if EFSYS_OPT_MEDFORD2
287         case EFX_FAMILY_MEDFORD2:
288                 enp->en_enop = &__efx_nic_medford2_ops;
289                 enp->en_features =
290                     EFX_FEATURE_IPV6 |
291                     EFX_FEATURE_LINK_EVENTS |
292                     EFX_FEATURE_PERIODIC_MAC_STATS |
293                     EFX_FEATURE_MCDI |
294                     EFX_FEATURE_MAC_HEADER_FILTERS |
295                     EFX_FEATURE_MCDI_DMA |
296                     EFX_FEATURE_PIO_BUFFERS |
297                     EFX_FEATURE_FW_ASSISTED_TSO_V2 |
298                     EFX_FEATURE_PACKED_STREAM |
299                     EFX_FEATURE_TXQ_CKSUM_OP_DESC;
300                 break;
301 #endif  /* EFSYS_OPT_MEDFORD2 */
302
303         default:
304                 rc = ENOTSUP;
305                 goto fail2;
306         }
307
308         enp->en_family = family;
309         enp->en_esip = esip;
310         enp->en_esbp = esbp;
311         enp->en_eslp = eslp;
312
313         *enpp = enp;
314
315         return (0);
316
317 fail2:
318         EFSYS_PROBE(fail2);
319
320         enp->en_magic = 0;
321
322         /* Free the NIC object */
323         EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
324
325 fail1:
326         EFSYS_PROBE1(fail1, efx_rc_t, rc);
327
328         return (rc);
329 }
330
331         __checkReturn   efx_rc_t
332 efx_nic_probe(
333         __in            efx_nic_t *enp,
334         __in            efx_fw_variant_t efv)
335 {
336         const efx_nic_ops_t *enop;
337         efx_rc_t rc;
338
339         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
340 #if EFSYS_OPT_MCDI
341         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
342 #endif  /* EFSYS_OPT_MCDI */
343         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_PROBE));
344
345         /* Ensure FW variant codes match with MC_CMD_FW codes */
346         EFX_STATIC_ASSERT(EFX_FW_VARIANT_FULL_FEATURED ==
347             MC_CMD_FW_FULL_FEATURED);
348         EFX_STATIC_ASSERT(EFX_FW_VARIANT_LOW_LATENCY ==
349             MC_CMD_FW_LOW_LATENCY);
350         EFX_STATIC_ASSERT(EFX_FW_VARIANT_PACKED_STREAM ==
351             MC_CMD_FW_PACKED_STREAM);
352         EFX_STATIC_ASSERT(EFX_FW_VARIANT_HIGH_TX_RATE ==
353             MC_CMD_FW_HIGH_TX_RATE);
354         EFX_STATIC_ASSERT(EFX_FW_VARIANT_PACKED_STREAM_HASH_MODE_1 ==
355             MC_CMD_FW_PACKED_STREAM_HASH_MODE_1);
356         EFX_STATIC_ASSERT(EFX_FW_VARIANT_RULES_ENGINE ==
357             MC_CMD_FW_RULES_ENGINE);
358         EFX_STATIC_ASSERT(EFX_FW_VARIANT_DPDK ==
359             MC_CMD_FW_DPDK);
360         EFX_STATIC_ASSERT(EFX_FW_VARIANT_DONT_CARE ==
361             (int)MC_CMD_FW_DONT_CARE);
362
363         enop = enp->en_enop;
364         enp->efv = efv;
365
366         if ((rc = enop->eno_probe(enp)) != 0)
367                 goto fail1;
368
369         if ((rc = efx_phy_probe(enp)) != 0)
370                 goto fail2;
371
372         enp->en_mod_flags |= EFX_MOD_PROBE;
373
374         return (0);
375
376 fail2:
377         EFSYS_PROBE(fail2);
378
379         enop->eno_unprobe(enp);
380
381 fail1:
382         EFSYS_PROBE1(fail1, efx_rc_t, rc);
383
384         return (rc);
385 }
386
387         __checkReturn   efx_rc_t
388 efx_nic_set_drv_limits(
389         __inout         efx_nic_t *enp,
390         __in            efx_drv_limits_t *edlp)
391 {
392         const efx_nic_ops_t *enop = enp->en_enop;
393         efx_rc_t rc;
394
395         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
396         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
397
398         if (enop->eno_set_drv_limits != NULL) {
399                 if ((rc = enop->eno_set_drv_limits(enp, edlp)) != 0)
400                         goto fail1;
401         }
402
403         return (0);
404
405 fail1:
406         EFSYS_PROBE1(fail1, efx_rc_t, rc);
407
408         return (rc);
409 }
410
411         __checkReturn   efx_rc_t
412 efx_nic_get_bar_region(
413         __in            efx_nic_t *enp,
414         __in            efx_nic_region_t region,
415         __out           uint32_t *offsetp,
416         __out           size_t *sizep)
417 {
418         const efx_nic_ops_t *enop = enp->en_enop;
419         efx_rc_t rc;
420
421         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
422         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
423         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
424
425         if (enop->eno_get_bar_region == NULL) {
426                 rc = ENOTSUP;
427                 goto fail1;
428         }
429         if ((rc = (enop->eno_get_bar_region)(enp,
430                     region, offsetp, sizep)) != 0) {
431                 goto fail2;
432         }
433
434         return (0);
435
436 fail2:
437         EFSYS_PROBE(fail2);
438
439 fail1:
440         EFSYS_PROBE1(fail1, efx_rc_t, rc);
441
442         return (rc);
443 }
444
445
446         __checkReturn   efx_rc_t
447 efx_nic_get_vi_pool(
448         __in            efx_nic_t *enp,
449         __out           uint32_t *evq_countp,
450         __out           uint32_t *rxq_countp,
451         __out           uint32_t *txq_countp)
452 {
453         const efx_nic_ops_t *enop = enp->en_enop;
454         efx_nic_cfg_t *encp = &enp->en_nic_cfg;
455         efx_rc_t rc;
456
457         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
458         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
459         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
460
461         if (enop->eno_get_vi_pool != NULL) {
462                 uint32_t vi_count = 0;
463
464                 if ((rc = (enop->eno_get_vi_pool)(enp, &vi_count)) != 0)
465                         goto fail1;
466
467                 *evq_countp = vi_count;
468                 *rxq_countp = vi_count;
469                 *txq_countp = vi_count;
470         } else {
471                 /* Use NIC limits as default value */
472                 *evq_countp = encp->enc_evq_limit;
473                 *rxq_countp = encp->enc_rxq_limit;
474                 *txq_countp = encp->enc_txq_limit;
475         }
476
477         return (0);
478
479 fail1:
480         EFSYS_PROBE1(fail1, efx_rc_t, rc);
481
482         return (rc);
483 }
484
485
486         __checkReturn   efx_rc_t
487 efx_nic_init(
488         __in            efx_nic_t *enp)
489 {
490         const efx_nic_ops_t *enop = enp->en_enop;
491         efx_rc_t rc;
492
493         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
494         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
495
496         if (enp->en_mod_flags & EFX_MOD_NIC) {
497                 rc = EINVAL;
498                 goto fail1;
499         }
500
501         if ((rc = enop->eno_init(enp)) != 0)
502                 goto fail2;
503
504         enp->en_mod_flags |= EFX_MOD_NIC;
505
506         return (0);
507
508 fail2:
509         EFSYS_PROBE(fail2);
510 fail1:
511         EFSYS_PROBE1(fail1, efx_rc_t, rc);
512
513         return (rc);
514 }
515
516                         void
517 efx_nic_fini(
518         __in            efx_nic_t *enp)
519 {
520         const efx_nic_ops_t *enop = enp->en_enop;
521
522         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
523         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
524         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_NIC);
525         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
526         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
527         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
528         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
529
530         enop->eno_fini(enp);
531
532         enp->en_mod_flags &= ~EFX_MOD_NIC;
533 }
534
535                         void
536 efx_nic_unprobe(
537         __in            efx_nic_t *enp)
538 {
539         const efx_nic_ops_t *enop = enp->en_enop;
540
541         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
542 #if EFSYS_OPT_MCDI
543         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
544 #endif  /* EFSYS_OPT_MCDI */
545         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
546         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
547         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
548         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
549         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
550         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
551
552         efx_phy_unprobe(enp);
553
554         enop->eno_unprobe(enp);
555
556         enp->en_mod_flags &= ~EFX_MOD_PROBE;
557 }
558
559                         void
560 efx_nic_destroy(
561         __in    efx_nic_t *enp)
562 {
563         efsys_identifier_t *esip = enp->en_esip;
564
565         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
566         EFSYS_ASSERT3U(enp->en_mod_flags, ==, 0);
567
568         enp->en_family = EFX_FAMILY_INVALID;
569         enp->en_esip = NULL;
570         enp->en_esbp = NULL;
571         enp->en_eslp = NULL;
572
573         enp->en_enop = NULL;
574
575         enp->en_magic = 0;
576
577         /* Free the NIC object */
578         EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
579 }
580
581         __checkReturn   efx_rc_t
582 efx_nic_reset(
583         __in            efx_nic_t *enp)
584 {
585         const efx_nic_ops_t *enop = enp->en_enop;
586         unsigned int mod_flags;
587         efx_rc_t rc;
588
589         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
590         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
591         /*
592          * All modules except the MCDI, PROBE, NVRAM, VPD, MON, TUNNEL
593          * (which we do not reset here) must have been shut down or never
594          * initialized.
595          *
596          * A rule of thumb here is: If the controller or MC reboots, is *any*
597          * state lost. If it's lost and needs reapplying, then the module
598          * *must* not be initialised during the reset.
599          */
600         mod_flags = enp->en_mod_flags;
601         mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM |
602             EFX_MOD_VPD | EFX_MOD_MON);
603 #if EFSYS_OPT_TUNNEL
604         mod_flags &= ~EFX_MOD_TUNNEL;
605 #endif /* EFSYS_OPT_TUNNEL */
606         EFSYS_ASSERT3U(mod_flags, ==, 0);
607         if (mod_flags != 0) {
608                 rc = EINVAL;
609                 goto fail1;
610         }
611
612         if ((rc = enop->eno_reset(enp)) != 0)
613                 goto fail2;
614
615         return (0);
616
617 fail2:
618         EFSYS_PROBE(fail2);
619 fail1:
620         EFSYS_PROBE1(fail1, efx_rc_t, rc);
621
622         return (rc);
623 }
624
625                         const efx_nic_cfg_t *
626 efx_nic_cfg_get(
627         __in            efx_nic_t *enp)
628 {
629         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
630         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
631
632         return (&(enp->en_nic_cfg));
633 }
634
635         __checkReturn           efx_rc_t
636 efx_nic_get_fw_version(
637         __in                    efx_nic_t *enp,
638         __out                   efx_nic_fw_info_t *enfip)
639 {
640         uint16_t mc_fw_version[4];
641         efx_rc_t rc;
642
643         if (enfip == NULL) {
644                 rc = EINVAL;
645                 goto fail1;
646         }
647
648         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
649         EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
650
651         /* Ensure RXDP_FW_ID codes match with MC_CMD_GET_CAPABILITIES codes */
652         EFX_STATIC_ASSERT(EFX_RXDP_FULL_FEATURED_FW_ID ==
653             MC_CMD_GET_CAPABILITIES_OUT_RXDP);
654         EFX_STATIC_ASSERT(EFX_RXDP_LOW_LATENCY_FW_ID ==
655             MC_CMD_GET_CAPABILITIES_OUT_RXDP_LOW_LATENCY);
656         EFX_STATIC_ASSERT(EFX_RXDP_PACKED_STREAM_FW_ID ==
657             MC_CMD_GET_CAPABILITIES_OUT_RXDP_PACKED_STREAM);
658         EFX_STATIC_ASSERT(EFX_RXDP_RULES_ENGINE_FW_ID ==
659             MC_CMD_GET_CAPABILITIES_OUT_RXDP_RULES_ENGINE);
660         EFX_STATIC_ASSERT(EFX_RXDP_DPDK_FW_ID ==
661             MC_CMD_GET_CAPABILITIES_OUT_RXDP_DPDK);
662
663         rc = efx_mcdi_version(enp, mc_fw_version, NULL, NULL);
664         if (rc != 0)
665                 goto fail2;
666
667         rc = efx_mcdi_get_capabilities(enp, NULL,
668             &enfip->enfi_rx_dpcpu_fw_id,
669             &enfip->enfi_tx_dpcpu_fw_id,
670             NULL, NULL);
671         if (rc == 0) {
672                 enfip->enfi_dpcpu_fw_ids_valid = B_TRUE;
673         } else if (rc == ENOTSUP) {
674                 enfip->enfi_dpcpu_fw_ids_valid = B_FALSE;
675                 enfip->enfi_rx_dpcpu_fw_id = 0;
676                 enfip->enfi_tx_dpcpu_fw_id = 0;
677         } else {
678                 goto fail3;
679         }
680
681         memcpy(enfip->enfi_mc_fw_version, mc_fw_version,
682             sizeof (mc_fw_version));
683
684         return (0);
685
686 fail3:
687         EFSYS_PROBE(fail3);
688 fail2:
689         EFSYS_PROBE(fail2);
690 fail1:
691         EFSYS_PROBE1(fail1, efx_rc_t, rc);
692
693         return (rc);
694 }
695
696         __checkReturn   boolean_t
697 efx_nic_hw_unavailable(
698         __in            efx_nic_t *enp)
699 {
700         const efx_nic_ops_t *enop = enp->en_enop;
701
702         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
703         /* NOTE: can be used by MCDI before NIC probe */
704
705         if (enop->eno_hw_unavailable != NULL) {
706                 if ((enop->eno_hw_unavailable)(enp) != B_FALSE)
707                         goto unavail;
708         }
709
710         return (B_FALSE);
711
712 unavail:
713         return (B_TRUE);
714 }
715
716                         void
717 efx_nic_set_hw_unavailable(
718         __in            efx_nic_t *enp)
719 {
720         const efx_nic_ops_t *enop = enp->en_enop;
721
722         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
723
724         if (enop->eno_set_hw_unavailable != NULL)
725                 enop->eno_set_hw_unavailable(enp);
726 }
727
728
729 #if EFSYS_OPT_DIAG
730
731         __checkReturn   efx_rc_t
732 efx_nic_register_test(
733         __in            efx_nic_t *enp)
734 {
735         const efx_nic_ops_t *enop = enp->en_enop;
736         efx_rc_t rc;
737
738         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
739         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
740         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
741
742         if ((rc = enop->eno_register_test(enp)) != 0)
743                 goto fail1;
744
745         return (0);
746
747 fail1:
748         EFSYS_PROBE1(fail1, efx_rc_t, rc);
749
750         return (rc);
751 }
752
753 #endif  /* EFSYS_OPT_DIAG */
754
755 #if EFSYS_OPT_LOOPBACK
756
757 extern                  void
758 efx_loopback_mask(
759         __in    efx_loopback_kind_t loopback_kind,
760         __out   efx_qword_t *maskp)
761 {
762         efx_qword_t mask;
763
764         EFSYS_ASSERT3U(loopback_kind, <, EFX_LOOPBACK_NKINDS);
765         EFSYS_ASSERT(maskp != NULL);
766
767         /* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree */
768 #define LOOPBACK_CHECK(_mcdi, _efx) \
769         EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_##_mcdi == EFX_LOOPBACK_##_efx)
770
771         LOOPBACK_CHECK(NONE, OFF);
772         LOOPBACK_CHECK(DATA, DATA);
773         LOOPBACK_CHECK(GMAC, GMAC);
774         LOOPBACK_CHECK(XGMII, XGMII);
775         LOOPBACK_CHECK(XGXS, XGXS);
776         LOOPBACK_CHECK(XAUI, XAUI);
777         LOOPBACK_CHECK(GMII, GMII);
778         LOOPBACK_CHECK(SGMII, SGMII);
779         LOOPBACK_CHECK(XGBR, XGBR);
780         LOOPBACK_CHECK(XFI, XFI);
781         LOOPBACK_CHECK(XAUI_FAR, XAUI_FAR);
782         LOOPBACK_CHECK(GMII_FAR, GMII_FAR);
783         LOOPBACK_CHECK(SGMII_FAR, SGMII_FAR);
784         LOOPBACK_CHECK(XFI_FAR, XFI_FAR);
785         LOOPBACK_CHECK(GPHY, GPHY);
786         LOOPBACK_CHECK(PHYXS, PHY_XS);
787         LOOPBACK_CHECK(PCS, PCS);
788         LOOPBACK_CHECK(PMAPMD, PMA_PMD);
789         LOOPBACK_CHECK(XPORT, XPORT);
790         LOOPBACK_CHECK(XGMII_WS, XGMII_WS);
791         LOOPBACK_CHECK(XAUI_WS, XAUI_WS);
792         LOOPBACK_CHECK(XAUI_WS_FAR, XAUI_WS_FAR);
793         LOOPBACK_CHECK(XAUI_WS_NEAR, XAUI_WS_NEAR);
794         LOOPBACK_CHECK(GMII_WS, GMII_WS);
795         LOOPBACK_CHECK(XFI_WS, XFI_WS);
796         LOOPBACK_CHECK(XFI_WS_FAR, XFI_WS_FAR);
797         LOOPBACK_CHECK(PHYXS_WS, PHYXS_WS);
798         LOOPBACK_CHECK(PMA_INT, PMA_INT);
799         LOOPBACK_CHECK(SD_NEAR, SD_NEAR);
800         LOOPBACK_CHECK(SD_FAR, SD_FAR);
801         LOOPBACK_CHECK(PMA_INT_WS, PMA_INT_WS);
802         LOOPBACK_CHECK(SD_FEP2_WS, SD_FEP2_WS);
803         LOOPBACK_CHECK(SD_FEP1_5_WS, SD_FEP1_5_WS);
804         LOOPBACK_CHECK(SD_FEP_WS, SD_FEP_WS);
805         LOOPBACK_CHECK(SD_FES_WS, SD_FES_WS);
806         LOOPBACK_CHECK(AOE_INT_NEAR, AOE_INT_NEAR);
807         LOOPBACK_CHECK(DATA_WS, DATA_WS);
808         LOOPBACK_CHECK(FORCE_EXT_LINK, FORCE_EXT_LINK);
809 #undef LOOPBACK_CHECK
810
811         /* Build bitmask of possible loopback types */
812         EFX_ZERO_QWORD(mask);
813
814         if ((loopback_kind == EFX_LOOPBACK_KIND_OFF) ||
815             (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
816                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_OFF);
817         }
818
819         if ((loopback_kind == EFX_LOOPBACK_KIND_MAC) ||
820             (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
821                 /*
822                  * The "MAC" grouping has historically been used by drivers to
823                  * mean loopbacks supported by on-chip hardware. Keep that
824                  * meaning here, and include on-chip PHY layer loopbacks.
825                  */
826                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_DATA);
827                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMAC);
828                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGMII);
829                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGXS);
830                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI);
831                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII);
832                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII);
833                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGBR);
834                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI);
835                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI_FAR);
836                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII_FAR);
837                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII_FAR);
838                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI_FAR);
839                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_INT);
840                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_NEAR);
841                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_FAR);
842         }
843
844         if ((loopback_kind == EFX_LOOPBACK_KIND_PHY) ||
845             (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
846                 /*
847                  * The "PHY" grouping has historically been used by drivers to
848                  * mean loopbacks supported by off-chip hardware. Keep that
849                  * meaning here.
850                  */
851                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GPHY);
852                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PHY_XS);
853                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PCS);
854                 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_PMD);
855         }
856
857         *maskp = mask;
858 }
859
860         __checkReturn   efx_rc_t
861 efx_mcdi_get_loopback_modes(
862         __in            efx_nic_t *enp)
863 {
864         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
865         efx_mcdi_req_t req;
866         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LOOPBACK_MODES_IN_LEN,
867                 MC_CMD_GET_LOOPBACK_MODES_OUT_V2_LEN);
868         efx_qword_t mask;
869         efx_qword_t modes;
870         efx_rc_t rc;
871
872         req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES;
873         req.emr_in_buf = payload;
874         req.emr_in_length = MC_CMD_GET_LOOPBACK_MODES_IN_LEN;
875         req.emr_out_buf = payload;
876         req.emr_out_length = MC_CMD_GET_LOOPBACK_MODES_OUT_V2_LEN;
877
878         efx_mcdi_execute(enp, &req);
879
880         if (req.emr_rc != 0) {
881                 rc = req.emr_rc;
882                 goto fail1;
883         }
884
885         if (req.emr_out_length_used <
886             MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST +
887             MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN) {
888                 rc = EMSGSIZE;
889                 goto fail2;
890         }
891
892         /*
893          * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree
894          * in efx_loopback_mask() and in siena_phy.c:siena_phy_get_link().
895          */
896         efx_loopback_mask(EFX_LOOPBACK_KIND_ALL, &mask);
897
898         EFX_AND_QWORD(mask,
899             *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_SUGGESTED));
900
901         modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_100M);
902         EFX_AND_QWORD(modes, mask);
903         encp->enc_loopback_types[EFX_LINK_100FDX] = modes;
904
905         modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_1G);
906         EFX_AND_QWORD(modes, mask);
907         encp->enc_loopback_types[EFX_LINK_1000FDX] = modes;
908
909         modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_10G);
910         EFX_AND_QWORD(modes, mask);
911         encp->enc_loopback_types[EFX_LINK_10000FDX] = modes;
912
913         if (req.emr_out_length_used >=
914             MC_CMD_GET_LOOPBACK_MODES_OUT_40G_OFST +
915             MC_CMD_GET_LOOPBACK_MODES_OUT_40G_LEN) {
916                 /* Response includes 40G loopback modes */
917                 modes = *MCDI_OUT2(req, efx_qword_t,
918                     GET_LOOPBACK_MODES_OUT_40G);
919                 EFX_AND_QWORD(modes, mask);
920                 encp->enc_loopback_types[EFX_LINK_40000FDX] = modes;
921         }
922
923         if (req.emr_out_length_used >=
924             MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_OFST +
925             MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_LEN) {
926                 /* Response includes 25G loopback modes */
927                 modes = *MCDI_OUT2(req, efx_qword_t,
928                     GET_LOOPBACK_MODES_OUT_V2_25G);
929                 EFX_AND_QWORD(modes, mask);
930                 encp->enc_loopback_types[EFX_LINK_25000FDX] = modes;
931         }
932
933         if (req.emr_out_length_used >=
934             MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_OFST +
935             MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_LEN) {
936                 /* Response includes 50G loopback modes */
937                 modes = *MCDI_OUT2(req, efx_qword_t,
938                     GET_LOOPBACK_MODES_OUT_V2_50G);
939                 EFX_AND_QWORD(modes, mask);
940                 encp->enc_loopback_types[EFX_LINK_50000FDX] = modes;
941         }
942
943         if (req.emr_out_length_used >=
944             MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_OFST +
945             MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_LEN) {
946                 /* Response includes 100G loopback modes */
947                 modes = *MCDI_OUT2(req, efx_qword_t,
948                     GET_LOOPBACK_MODES_OUT_V2_100G);
949                 EFX_AND_QWORD(modes, mask);
950                 encp->enc_loopback_types[EFX_LINK_100000FDX] = modes;
951         }
952
953         EFX_ZERO_QWORD(modes);
954         EFX_SET_QWORD_BIT(modes, EFX_LOOPBACK_OFF);
955         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_100FDX]);
956         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_1000FDX]);
957         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_10000FDX]);
958         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_40000FDX]);
959         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_25000FDX]);
960         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_50000FDX]);
961         EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_100000FDX]);
962         encp->enc_loopback_types[EFX_LINK_UNKNOWN] = modes;
963
964         return (0);
965
966 fail2:
967         EFSYS_PROBE(fail2);
968 fail1:
969         EFSYS_PROBE1(fail1, efx_rc_t, rc);
970
971         return (rc);
972 }
973
974 #endif /* EFSYS_OPT_LOOPBACK */
975
976         __checkReturn   efx_rc_t
977 efx_nic_calculate_pcie_link_bandwidth(
978         __in            uint32_t pcie_link_width,
979         __in            uint32_t pcie_link_gen,
980         __out           uint32_t *bandwidth_mbpsp)
981 {
982         uint32_t lane_bandwidth;
983         uint32_t total_bandwidth;
984         efx_rc_t rc;
985
986         if ((pcie_link_width == 0) || (pcie_link_width > 16) ||
987             !ISP2(pcie_link_width)) {
988                 rc = EINVAL;
989                 goto fail1;
990         }
991
992         switch (pcie_link_gen) {
993         case EFX_PCIE_LINK_SPEED_GEN1:
994                 /* 2.5 Gb/s raw bandwidth with 8b/10b encoding */
995                 lane_bandwidth = 2000;
996                 break;
997         case EFX_PCIE_LINK_SPEED_GEN2:
998                 /* 5.0 Gb/s raw bandwidth with 8b/10b encoding */
999                 lane_bandwidth = 4000;
1000                 break;
1001         case EFX_PCIE_LINK_SPEED_GEN3:
1002                 /* 8.0 Gb/s raw bandwidth with 128b/130b encoding */
1003                 lane_bandwidth = 7877;
1004                 break;
1005         default:
1006                 rc = EINVAL;
1007                 goto fail2;
1008         }
1009
1010         total_bandwidth = lane_bandwidth * pcie_link_width;
1011         *bandwidth_mbpsp = total_bandwidth;
1012
1013         return (0);
1014
1015 fail2:
1016         EFSYS_PROBE(fail2);
1017 fail1:
1018         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1019
1020         return (rc);
1021 }
1022
1023 #if EFSYS_OPT_FW_SUBVARIANT_AWARE
1024
1025         __checkReturn   efx_rc_t
1026 efx_nic_get_fw_subvariant(
1027         __in            efx_nic_t *enp,
1028         __out           efx_nic_fw_subvariant_t *subvariantp)
1029 {
1030         efx_rc_t rc;
1031         uint32_t value;
1032
1033         rc = efx_mcdi_get_nic_global(enp,
1034             MC_CMD_SET_NIC_GLOBAL_IN_FIRMWARE_SUBVARIANT, &value);
1035         if (rc != 0)
1036                 goto fail1;
1037
1038         /* Mapping is not required since values match MCDI */
1039         EFX_STATIC_ASSERT(EFX_NIC_FW_SUBVARIANT_DEFAULT ==
1040             MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_DEFAULT);
1041         EFX_STATIC_ASSERT(EFX_NIC_FW_SUBVARIANT_NO_TX_CSUM ==
1042             MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_NO_TX_CSUM);
1043
1044         switch (value) {
1045         case MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_DEFAULT:
1046         case MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_NO_TX_CSUM:
1047                 *subvariantp = value;
1048                 break;
1049         default:
1050                 rc = EINVAL;
1051                 goto fail2;
1052         }
1053
1054         return (0);
1055
1056 fail2:
1057         EFSYS_PROBE(fail2);
1058
1059 fail1:
1060         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1061
1062         return (rc);
1063 }
1064
1065         __checkReturn   efx_rc_t
1066 efx_nic_set_fw_subvariant(
1067         __in            efx_nic_t *enp,
1068         __in            efx_nic_fw_subvariant_t subvariant)
1069 {
1070         efx_rc_t rc;
1071
1072         switch (subvariant) {
1073         case EFX_NIC_FW_SUBVARIANT_DEFAULT:
1074         case EFX_NIC_FW_SUBVARIANT_NO_TX_CSUM:
1075                 /* Mapping is not required since values match MCDI */
1076                 break;
1077         default:
1078                 rc = EINVAL;
1079                 goto fail1;
1080         }
1081
1082         rc = efx_mcdi_set_nic_global(enp,
1083             MC_CMD_SET_NIC_GLOBAL_IN_FIRMWARE_SUBVARIANT, subvariant);
1084         if (rc != 0)
1085                 goto fail2;
1086
1087         return (0);
1088
1089 fail2:
1090         EFSYS_PROBE(fail2);
1091
1092 fail1:
1093         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1094
1095         return (rc);
1096 }
1097
1098 #endif  /* EFSYS_OPT_FW_SUBVARIANT_AWARE */
1099
1100         __checkReturn   efx_rc_t
1101 efx_nic_check_pcie_link_speed(
1102         __in            efx_nic_t *enp,
1103         __in            uint32_t pcie_link_width,
1104         __in            uint32_t pcie_link_gen,
1105         __out           efx_pcie_link_performance_t *resultp)
1106 {
1107         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1108         uint32_t bandwidth;
1109         efx_pcie_link_performance_t result;
1110         efx_rc_t rc;
1111
1112         if ((encp->enc_required_pcie_bandwidth_mbps == 0) ||
1113             (pcie_link_width == 0) || (pcie_link_width == 32) ||
1114             (pcie_link_gen == 0)) {
1115                 /*
1116                  * No usable info on what is required and/or in use. In virtual
1117                  * machines, sometimes the PCIe link width is reported as 0 or
1118                  * 32, or the speed as 0.
1119                  */
1120                 result = EFX_PCIE_LINK_PERFORMANCE_UNKNOWN_BANDWIDTH;
1121                 goto out;
1122         }
1123
1124         /* Calculate the available bandwidth in megabits per second */
1125         rc = efx_nic_calculate_pcie_link_bandwidth(pcie_link_width,
1126                                             pcie_link_gen, &bandwidth);
1127         if (rc != 0)
1128                 goto fail1;
1129
1130         if (bandwidth < encp->enc_required_pcie_bandwidth_mbps) {
1131                 result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_BANDWIDTH;
1132         } else if (pcie_link_gen < encp->enc_max_pcie_link_gen) {
1133                 /* The link provides enough bandwidth but not optimal latency */
1134                 result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_LATENCY;
1135         } else {
1136                 result = EFX_PCIE_LINK_PERFORMANCE_OPTIMAL;
1137         }
1138
1139 out:
1140         *resultp = result;
1141
1142         return (0);
1143
1144 fail1:
1145         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1146
1147         return (rc);
1148 }