net/sfc/base: import SFN8xxx family support
[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         siena_nic_fini,                 /* eno_fini */
188         siena_nic_unprobe,              /* eno_unprobe */
189 };
190
191 #endif  /* EFSYS_OPT_SIENA */
192
193 #if EFSYS_OPT_HUNTINGTON
194
195 static const efx_nic_ops_t      __efx_nic_hunt_ops = {
196         ef10_nic_probe,                 /* eno_probe */
197         hunt_board_cfg,                 /* eno_board_cfg */
198         ef10_nic_set_drv_limits,        /* eno_set_drv_limits */
199         ef10_nic_reset,                 /* eno_reset */
200         ef10_nic_init,                  /* eno_init */
201         ef10_nic_get_vi_pool,           /* eno_get_vi_pool */
202         ef10_nic_get_bar_region,        /* eno_get_bar_region */
203         ef10_nic_fini,                  /* eno_fini */
204         ef10_nic_unprobe,               /* eno_unprobe */
205 };
206
207 #endif  /* EFSYS_OPT_HUNTINGTON */
208
209 #if EFSYS_OPT_MEDFORD
210
211 static const efx_nic_ops_t      __efx_nic_medford_ops = {
212         ef10_nic_probe,                 /* eno_probe */
213         medford_board_cfg,              /* eno_board_cfg */
214         ef10_nic_set_drv_limits,        /* eno_set_drv_limits */
215         ef10_nic_reset,                 /* eno_reset */
216         ef10_nic_init,                  /* eno_init */
217         ef10_nic_get_vi_pool,           /* eno_get_vi_pool */
218         ef10_nic_get_bar_region,        /* eno_get_bar_region */
219         ef10_nic_fini,                  /* eno_fini */
220         ef10_nic_unprobe,               /* eno_unprobe */
221 };
222
223 #endif  /* EFSYS_OPT_MEDFORD */
224
225
226         __checkReturn   efx_rc_t
227 efx_nic_create(
228         __in            efx_family_t family,
229         __in            efsys_identifier_t *esip,
230         __in            efsys_bar_t *esbp,
231         __in            efsys_lock_t *eslp,
232         __deref_out     efx_nic_t **enpp)
233 {
234         efx_nic_t *enp;
235         efx_rc_t rc;
236
237         EFSYS_ASSERT3U(family, >, EFX_FAMILY_INVALID);
238         EFSYS_ASSERT3U(family, <, EFX_FAMILY_NTYPES);
239
240         /* Allocate a NIC object */
241         EFSYS_KMEM_ALLOC(esip, sizeof (efx_nic_t), enp);
242
243         if (enp == NULL) {
244                 rc = ENOMEM;
245                 goto fail1;
246         }
247
248         enp->en_magic = EFX_NIC_MAGIC;
249
250         switch (family) {
251 #if EFSYS_OPT_SIENA
252         case EFX_FAMILY_SIENA:
253                 enp->en_enop = &__efx_nic_siena_ops;
254                 enp->en_features =
255                     EFX_FEATURE_IPV6 |
256                     EFX_FEATURE_LFSR_HASH_INSERT |
257                     EFX_FEATURE_LINK_EVENTS |
258                     EFX_FEATURE_PERIODIC_MAC_STATS |
259                     EFX_FEATURE_MCDI |
260                     EFX_FEATURE_LOOKAHEAD_SPLIT |
261                     EFX_FEATURE_MAC_HEADER_FILTERS |
262                     EFX_FEATURE_TX_SRC_FILTERS;
263                 break;
264 #endif  /* EFSYS_OPT_SIENA */
265
266 #if EFSYS_OPT_HUNTINGTON
267         case EFX_FAMILY_HUNTINGTON:
268                 enp->en_enop = &__efx_nic_hunt_ops;
269                 enp->en_features =
270                     EFX_FEATURE_IPV6 |
271                     EFX_FEATURE_LINK_EVENTS |
272                     EFX_FEATURE_PERIODIC_MAC_STATS |
273                     EFX_FEATURE_MCDI |
274                     EFX_FEATURE_MAC_HEADER_FILTERS |
275                     EFX_FEATURE_MCDI_DMA |
276                     EFX_FEATURE_PIO_BUFFERS |
277                     EFX_FEATURE_FW_ASSISTED_TSO |
278                     EFX_FEATURE_FW_ASSISTED_TSO_V2 |
279                     EFX_FEATURE_PACKED_STREAM;
280                 break;
281 #endif  /* EFSYS_OPT_HUNTINGTON */
282
283 #if EFSYS_OPT_MEDFORD
284         case EFX_FAMILY_MEDFORD:
285                 enp->en_enop = &__efx_nic_medford_ops;
286                 /*
287                  * FW_ASSISTED_TSO omitted as Medford only supports firmware
288                  * assisted TSO version 2, not the v1 scheme used on Huntington.
289                  */
290                 enp->en_features =
291                     EFX_FEATURE_IPV6 |
292                     EFX_FEATURE_LINK_EVENTS |
293                     EFX_FEATURE_PERIODIC_MAC_STATS |
294                     EFX_FEATURE_MCDI |
295                     EFX_FEATURE_MAC_HEADER_FILTERS |
296                     EFX_FEATURE_MCDI_DMA |
297                     EFX_FEATURE_PIO_BUFFERS |
298                     EFX_FEATURE_FW_ASSISTED_TSO_V2 |
299                     EFX_FEATURE_PACKED_STREAM;
300                 break;
301 #endif  /* EFSYS_OPT_MEDFORD */
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 {
335         const efx_nic_ops_t *enop;
336         efx_rc_t rc;
337
338         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
339 #if EFSYS_OPT_MCDI
340         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
341 #endif  /* EFSYS_OPT_MCDI */
342         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_PROBE));
343
344         enop = enp->en_enop;
345         if ((rc = enop->eno_probe(enp)) != 0)
346                 goto fail1;
347
348         if ((rc = efx_phy_probe(enp)) != 0)
349                 goto fail2;
350
351         enp->en_mod_flags |= EFX_MOD_PROBE;
352
353         return (0);
354
355 fail2:
356         EFSYS_PROBE(fail2);
357
358         enop->eno_unprobe(enp);
359
360 fail1:
361         EFSYS_PROBE1(fail1, efx_rc_t, rc);
362
363         return (rc);
364 }
365
366         __checkReturn   efx_rc_t
367 efx_nic_set_drv_limits(
368         __inout         efx_nic_t *enp,
369         __in            efx_drv_limits_t *edlp)
370 {
371         const efx_nic_ops_t *enop = enp->en_enop;
372         efx_rc_t rc;
373
374         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
375         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
376
377         if (enop->eno_set_drv_limits != NULL) {
378                 if ((rc = enop->eno_set_drv_limits(enp, edlp)) != 0)
379                         goto fail1;
380         }
381
382         return (0);
383
384 fail1:
385         EFSYS_PROBE1(fail1, efx_rc_t, rc);
386
387         return (rc);
388 }
389
390         __checkReturn   efx_rc_t
391 efx_nic_get_bar_region(
392         __in            efx_nic_t *enp,
393         __in            efx_nic_region_t region,
394         __out           uint32_t *offsetp,
395         __out           size_t *sizep)
396 {
397         const efx_nic_ops_t *enop = enp->en_enop;
398         efx_rc_t rc;
399
400         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
401         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
402         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
403
404         if (enop->eno_get_bar_region == NULL) {
405                 rc = ENOTSUP;
406                 goto fail1;
407         }
408         if ((rc = (enop->eno_get_bar_region)(enp,
409                     region, offsetp, sizep)) != 0) {
410                 goto fail2;
411         }
412
413         return (0);
414
415 fail2:
416         EFSYS_PROBE(fail2);
417
418 fail1:
419         EFSYS_PROBE1(fail1, efx_rc_t, rc);
420
421         return (rc);
422 }
423
424
425         __checkReturn   efx_rc_t
426 efx_nic_get_vi_pool(
427         __in            efx_nic_t *enp,
428         __out           uint32_t *evq_countp,
429         __out           uint32_t *rxq_countp,
430         __out           uint32_t *txq_countp)
431 {
432         const efx_nic_ops_t *enop = enp->en_enop;
433         efx_nic_cfg_t *encp = &enp->en_nic_cfg;
434         efx_rc_t rc;
435
436         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
437         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
438         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
439
440         if (enop->eno_get_vi_pool != NULL) {
441                 uint32_t vi_count = 0;
442
443                 if ((rc = (enop->eno_get_vi_pool)(enp, &vi_count)) != 0)
444                         goto fail1;
445
446                 *evq_countp = vi_count;
447                 *rxq_countp = vi_count;
448                 *txq_countp = vi_count;
449         } else {
450                 /* Use NIC limits as default value */
451                 *evq_countp = encp->enc_evq_limit;
452                 *rxq_countp = encp->enc_rxq_limit;
453                 *txq_countp = encp->enc_txq_limit;
454         }
455
456         return (0);
457
458 fail1:
459         EFSYS_PROBE1(fail1, efx_rc_t, rc);
460
461         return (rc);
462 }
463
464
465         __checkReturn   efx_rc_t
466 efx_nic_init(
467         __in            efx_nic_t *enp)
468 {
469         const efx_nic_ops_t *enop = enp->en_enop;
470         efx_rc_t rc;
471
472         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
473         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
474
475         if (enp->en_mod_flags & EFX_MOD_NIC) {
476                 rc = EINVAL;
477                 goto fail1;
478         }
479
480         if ((rc = enop->eno_init(enp)) != 0)
481                 goto fail2;
482
483         enp->en_mod_flags |= EFX_MOD_NIC;
484
485         return (0);
486
487 fail2:
488         EFSYS_PROBE(fail2);
489 fail1:
490         EFSYS_PROBE1(fail1, efx_rc_t, rc);
491
492         return (rc);
493 }
494
495                         void
496 efx_nic_fini(
497         __in            efx_nic_t *enp)
498 {
499         const efx_nic_ops_t *enop = enp->en_enop;
500
501         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
502         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
503         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_NIC);
504         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
505         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
506         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
507         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
508
509         enop->eno_fini(enp);
510
511         enp->en_mod_flags &= ~EFX_MOD_NIC;
512 }
513
514                         void
515 efx_nic_unprobe(
516         __in            efx_nic_t *enp)
517 {
518         const efx_nic_ops_t *enop = enp->en_enop;
519
520         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
521 #if EFSYS_OPT_MCDI
522         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
523 #endif  /* EFSYS_OPT_MCDI */
524         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
525         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
526         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
527         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
528         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
529         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
530
531         efx_phy_unprobe(enp);
532
533         enop->eno_unprobe(enp);
534
535         enp->en_mod_flags &= ~EFX_MOD_PROBE;
536 }
537
538                         void
539 efx_nic_destroy(
540         __in    efx_nic_t *enp)
541 {
542         efsys_identifier_t *esip = enp->en_esip;
543
544         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
545         EFSYS_ASSERT3U(enp->en_mod_flags, ==, 0);
546
547         enp->en_family = EFX_FAMILY_INVALID;
548         enp->en_esip = NULL;
549         enp->en_esbp = NULL;
550         enp->en_eslp = NULL;
551
552         enp->en_enop = NULL;
553
554         enp->en_magic = 0;
555
556         /* Free the NIC object */
557         EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
558 }
559
560         __checkReturn   efx_rc_t
561 efx_nic_reset(
562         __in            efx_nic_t *enp)
563 {
564         const efx_nic_ops_t *enop = enp->en_enop;
565         unsigned int mod_flags;
566         efx_rc_t rc;
567
568         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
569         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
570         /*
571          * All modules except the MCDI, PROBE, NVRAM, VPD, MON
572          * (which we do not reset here) must have been shut down or never
573          * initialized.
574          *
575          * A rule of thumb here is: If the controller or MC reboots, is *any*
576          * state lost. If it's lost and needs reapplying, then the module
577          * *must* not be initialised during the reset.
578          */
579         mod_flags = enp->en_mod_flags;
580         mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM |
581                     EFX_MOD_VPD | EFX_MOD_MON);
582         EFSYS_ASSERT3U(mod_flags, ==, 0);
583         if (mod_flags != 0) {
584                 rc = EINVAL;
585                 goto fail1;
586         }
587
588         if ((rc = enop->eno_reset(enp)) != 0)
589                 goto fail2;
590
591         return (0);
592
593 fail2:
594         EFSYS_PROBE(fail2);
595 fail1:
596         EFSYS_PROBE1(fail1, efx_rc_t, rc);
597
598         return (rc);
599 }
600
601                         const efx_nic_cfg_t *
602 efx_nic_cfg_get(
603         __in            efx_nic_t *enp)
604 {
605         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
606
607         return (&(enp->en_nic_cfg));
608 }
609
610         __checkReturn   efx_rc_t
611 efx_nic_calculate_pcie_link_bandwidth(
612         __in            uint32_t pcie_link_width,
613         __in            uint32_t pcie_link_gen,
614         __out           uint32_t *bandwidth_mbpsp)
615 {
616         uint32_t lane_bandwidth;
617         uint32_t total_bandwidth;
618         efx_rc_t rc;
619
620         if ((pcie_link_width == 0) || (pcie_link_width > 16) ||
621             !ISP2(pcie_link_width)) {
622                 rc = EINVAL;
623                 goto fail1;
624         }
625
626         switch (pcie_link_gen) {
627         case EFX_PCIE_LINK_SPEED_GEN1:
628                 /* 2.5 Gb/s raw bandwidth with 8b/10b encoding */
629                 lane_bandwidth = 2000;
630                 break;
631         case EFX_PCIE_LINK_SPEED_GEN2:
632                 /* 5.0 Gb/s raw bandwidth with 8b/10b encoding */
633                 lane_bandwidth = 4000;
634                 break;
635         case EFX_PCIE_LINK_SPEED_GEN3:
636                 /* 8.0 Gb/s raw bandwidth with 128b/130b encoding */
637                 lane_bandwidth = 7877;
638                 break;
639         default:
640                 rc = EINVAL;
641                 goto fail2;
642         }
643
644         total_bandwidth = lane_bandwidth * pcie_link_width;
645         *bandwidth_mbpsp = total_bandwidth;
646
647         return (0);
648
649 fail2:
650         EFSYS_PROBE(fail2);
651 fail1:
652         EFSYS_PROBE1(fail1, efx_rc_t, rc);
653
654         return (rc);
655 }
656
657
658         __checkReturn   efx_rc_t
659 efx_nic_check_pcie_link_speed(
660         __in            efx_nic_t *enp,
661         __in            uint32_t pcie_link_width,
662         __in            uint32_t pcie_link_gen,
663         __out           efx_pcie_link_performance_t *resultp)
664 {
665         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
666         uint32_t bandwidth;
667         efx_pcie_link_performance_t result;
668         efx_rc_t rc;
669
670         if ((encp->enc_required_pcie_bandwidth_mbps == 0) ||
671             (pcie_link_width == 0) || (pcie_link_width == 32) ||
672             (pcie_link_gen == 0)) {
673                 /*
674                  * No usable info on what is required and/or in use. In virtual
675                  * machines, sometimes the PCIe link width is reported as 0 or
676                  * 32, or the speed as 0.
677                  */
678                 result = EFX_PCIE_LINK_PERFORMANCE_UNKNOWN_BANDWIDTH;
679                 goto out;
680         }
681
682         /* Calculate the available bandwidth in megabits per second */
683         rc = efx_nic_calculate_pcie_link_bandwidth(pcie_link_width,
684                                             pcie_link_gen, &bandwidth);
685         if (rc != 0)
686                 goto fail1;
687
688         if (bandwidth < encp->enc_required_pcie_bandwidth_mbps) {
689                 result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_BANDWIDTH;
690         } else if (pcie_link_gen < encp->enc_max_pcie_link_gen) {
691                 /* The link provides enough bandwidth but not optimal latency */
692                 result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_LATENCY;
693         } else {
694                 result = EFX_PCIE_LINK_PERFORMANCE_OPTIMAL;
695         }
696
697 out:
698         *resultp = result;
699
700         return (0);
701
702 fail1:
703         EFSYS_PROBE1(fail1, efx_rc_t, rc);
704
705         return (rc);
706 }