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 <sys/cdefs.h>
32 __FBSDID("$FreeBSD: stable/10/sys/dev/sfxge/common/efx_nic.c 342524 2018-12-26 10:37:06Z arybchik $");
33
34 #include "efx.h"
35 #include "efx_impl.h"
36
37 __checkReturn efx_rc_t
efx_family(__in uint16_t venid,__in uint16_t devid,__out efx_family_t * efp)38 efx_family(
39 __in uint16_t venid,
40 __in uint16_t devid,
41 __out efx_family_t *efp)
42 {
43 if (venid == EFX_PCI_VENID_SFC) {
44 switch (devid) {
45 #if EFSYS_OPT_SIENA
46 case EFX_PCI_DEVID_SIENA_F1_UNINIT:
47 /*
48 * Hardware default for PF0 of uninitialised Siena.
49 * manftest must be able to cope with this device id.
50 */
51 *efp = EFX_FAMILY_SIENA;
52 return (0);
53
54 case EFX_PCI_DEVID_BETHPAGE:
55 case EFX_PCI_DEVID_SIENA:
56 *efp = EFX_FAMILY_SIENA;
57 return (0);
58 #endif /* EFSYS_OPT_SIENA */
59
60 #if EFSYS_OPT_HUNTINGTON
61 case EFX_PCI_DEVID_HUNTINGTON_PF_UNINIT:
62 /*
63 * Hardware default for PF0 of uninitialised Huntington.
64 * manftest must be able to cope with this device id.
65 */
66 *efp = EFX_FAMILY_HUNTINGTON;
67 return (0);
68
69 case EFX_PCI_DEVID_FARMINGDALE:
70 case EFX_PCI_DEVID_GREENPORT:
71 *efp = EFX_FAMILY_HUNTINGTON;
72 return (0);
73
74 case EFX_PCI_DEVID_FARMINGDALE_VF:
75 case EFX_PCI_DEVID_GREENPORT_VF:
76 *efp = EFX_FAMILY_HUNTINGTON;
77 return (0);
78 #endif /* EFSYS_OPT_HUNTINGTON */
79
80 #if EFSYS_OPT_MEDFORD
81 case EFX_PCI_DEVID_MEDFORD_PF_UNINIT:
82 /*
83 * Hardware default for PF0 of uninitialised Medford.
84 * manftest must be able to cope with this device id.
85 */
86 *efp = EFX_FAMILY_MEDFORD;
87 return (0);
88
89 case EFX_PCI_DEVID_MEDFORD:
90 *efp = EFX_FAMILY_MEDFORD;
91 return (0);
92
93 case EFX_PCI_DEVID_MEDFORD_VF:
94 *efp = EFX_FAMILY_MEDFORD;
95 return (0);
96 #endif /* EFSYS_OPT_MEDFORD */
97
98 case EFX_PCI_DEVID_FALCON: /* Obsolete, not supported */
99 default:
100 break;
101 }
102 }
103
104 *efp = EFX_FAMILY_INVALID;
105 return (ENOTSUP);
106 }
107
108 #if EFSYS_OPT_SIENA
109
110 static const efx_nic_ops_t __efx_nic_siena_ops = {
111 siena_nic_probe, /* eno_probe */
112 NULL, /* eno_board_cfg */
113 NULL, /* eno_set_drv_limits */
114 siena_nic_reset, /* eno_reset */
115 siena_nic_init, /* eno_init */
116 NULL, /* eno_get_vi_pool */
117 NULL, /* eno_get_bar_region */
118 #if EFSYS_OPT_DIAG
119 siena_nic_register_test, /* eno_register_test */
120 #endif /* EFSYS_OPT_DIAG */
121 siena_nic_fini, /* eno_fini */
122 siena_nic_unprobe, /* eno_unprobe */
123 };
124
125 #endif /* EFSYS_OPT_SIENA */
126
127 #if EFSYS_OPT_HUNTINGTON
128
129 static const efx_nic_ops_t __efx_nic_hunt_ops = {
130 ef10_nic_probe, /* eno_probe */
131 hunt_board_cfg, /* eno_board_cfg */
132 ef10_nic_set_drv_limits, /* eno_set_drv_limits */
133 ef10_nic_reset, /* eno_reset */
134 ef10_nic_init, /* eno_init */
135 ef10_nic_get_vi_pool, /* eno_get_vi_pool */
136 ef10_nic_get_bar_region, /* eno_get_bar_region */
137 #if EFSYS_OPT_DIAG
138 ef10_nic_register_test, /* eno_register_test */
139 #endif /* EFSYS_OPT_DIAG */
140 ef10_nic_fini, /* eno_fini */
141 ef10_nic_unprobe, /* eno_unprobe */
142 };
143
144 #endif /* EFSYS_OPT_HUNTINGTON */
145
146 #if EFSYS_OPT_MEDFORD
147
148 static const efx_nic_ops_t __efx_nic_medford_ops = {
149 ef10_nic_probe, /* eno_probe */
150 medford_board_cfg, /* eno_board_cfg */
151 ef10_nic_set_drv_limits, /* eno_set_drv_limits */
152 ef10_nic_reset, /* eno_reset */
153 ef10_nic_init, /* eno_init */
154 ef10_nic_get_vi_pool, /* eno_get_vi_pool */
155 ef10_nic_get_bar_region, /* eno_get_bar_region */
156 #if EFSYS_OPT_DIAG
157 ef10_nic_register_test, /* eno_register_test */
158 #endif /* EFSYS_OPT_DIAG */
159 ef10_nic_fini, /* eno_fini */
160 ef10_nic_unprobe, /* eno_unprobe */
161 };
162
163 #endif /* EFSYS_OPT_MEDFORD */
164
165
166 __checkReturn efx_rc_t
efx_nic_create(__in efx_family_t family,__in efsys_identifier_t * esip,__in efsys_bar_t * esbp,__in efsys_lock_t * eslp,__deref_out efx_nic_t ** enpp)167 efx_nic_create(
168 __in efx_family_t family,
169 __in efsys_identifier_t *esip,
170 __in efsys_bar_t *esbp,
171 __in efsys_lock_t *eslp,
172 __deref_out efx_nic_t **enpp)
173 {
174 efx_nic_t *enp;
175 efx_rc_t rc;
176
177 EFSYS_ASSERT3U(family, >, EFX_FAMILY_INVALID);
178 EFSYS_ASSERT3U(family, <, EFX_FAMILY_NTYPES);
179
180 /* Allocate a NIC object */
181 EFSYS_KMEM_ALLOC(esip, sizeof (efx_nic_t), enp);
182
183 if (enp == NULL) {
184 rc = ENOMEM;
185 goto fail1;
186 }
187
188 enp->en_magic = EFX_NIC_MAGIC;
189
190 switch (family) {
191 #if EFSYS_OPT_SIENA
192 case EFX_FAMILY_SIENA:
193 enp->en_enop = &__efx_nic_siena_ops;
194 enp->en_features =
195 EFX_FEATURE_IPV6 |
196 EFX_FEATURE_LFSR_HASH_INSERT |
197 EFX_FEATURE_LINK_EVENTS |
198 EFX_FEATURE_PERIODIC_MAC_STATS |
199 EFX_FEATURE_MCDI |
200 EFX_FEATURE_LOOKAHEAD_SPLIT |
201 EFX_FEATURE_MAC_HEADER_FILTERS |
202 EFX_FEATURE_TX_SRC_FILTERS;
203 break;
204 #endif /* EFSYS_OPT_SIENA */
205
206 #if EFSYS_OPT_HUNTINGTON
207 case EFX_FAMILY_HUNTINGTON:
208 enp->en_enop = &__efx_nic_hunt_ops;
209 enp->en_features =
210 EFX_FEATURE_IPV6 |
211 EFX_FEATURE_LINK_EVENTS |
212 EFX_FEATURE_PERIODIC_MAC_STATS |
213 EFX_FEATURE_MCDI |
214 EFX_FEATURE_MAC_HEADER_FILTERS |
215 EFX_FEATURE_MCDI_DMA |
216 EFX_FEATURE_PIO_BUFFERS |
217 EFX_FEATURE_FW_ASSISTED_TSO |
218 EFX_FEATURE_FW_ASSISTED_TSO_V2 |
219 EFX_FEATURE_TXQ_CKSUM_OP_DESC;
220 break;
221 #endif /* EFSYS_OPT_HUNTINGTON */
222
223 #if EFSYS_OPT_MEDFORD
224 case EFX_FAMILY_MEDFORD:
225 enp->en_enop = &__efx_nic_medford_ops;
226 /*
227 * FW_ASSISTED_TSO ommitted as Medford only supports firmware
228 * assisted TSO version 2, not the v1 scheme used on Huntington.
229 */
230 enp->en_features =
231 EFX_FEATURE_IPV6 |
232 EFX_FEATURE_LINK_EVENTS |
233 EFX_FEATURE_PERIODIC_MAC_STATS |
234 EFX_FEATURE_MCDI |
235 EFX_FEATURE_MAC_HEADER_FILTERS |
236 EFX_FEATURE_MCDI_DMA |
237 EFX_FEATURE_PIO_BUFFERS |
238 EFX_FEATURE_FW_ASSISTED_TSO_V2 |
239 EFX_FEATURE_TXQ_CKSUM_OP_DESC;
240 break;
241 #endif /* EFSYS_OPT_MEDFORD */
242
243 default:
244 rc = ENOTSUP;
245 goto fail2;
246 }
247
248 enp->en_family = family;
249 enp->en_esip = esip;
250 enp->en_esbp = esbp;
251 enp->en_eslp = eslp;
252
253 *enpp = enp;
254
255 return (0);
256
257 fail2:
258 EFSYS_PROBE(fail2);
259
260 enp->en_magic = 0;
261
262 /* Free the NIC object */
263 EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
264
265 fail1:
266 EFSYS_PROBE1(fail1, efx_rc_t, rc);
267
268 return (rc);
269 }
270
271 __checkReturn efx_rc_t
efx_nic_probe(__in efx_nic_t * enp)272 efx_nic_probe(
273 __in efx_nic_t *enp)
274 {
275 const efx_nic_ops_t *enop;
276 efx_rc_t rc;
277
278 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
279 #if EFSYS_OPT_MCDI
280 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
281 #endif /* EFSYS_OPT_MCDI */
282 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_PROBE));
283
284 enop = enp->en_enop;
285 if ((rc = enop->eno_probe(enp)) != 0)
286 goto fail1;
287
288 if ((rc = efx_phy_probe(enp)) != 0)
289 goto fail2;
290
291 enp->en_mod_flags |= EFX_MOD_PROBE;
292
293 return (0);
294
295 fail2:
296 EFSYS_PROBE(fail2);
297
298 enop->eno_unprobe(enp);
299
300 fail1:
301 EFSYS_PROBE1(fail1, efx_rc_t, rc);
302
303 return (rc);
304 }
305
306 __checkReturn efx_rc_t
efx_nic_set_drv_limits(__inout efx_nic_t * enp,__in efx_drv_limits_t * edlp)307 efx_nic_set_drv_limits(
308 __inout efx_nic_t *enp,
309 __in efx_drv_limits_t *edlp)
310 {
311 const efx_nic_ops_t *enop = enp->en_enop;
312 efx_rc_t rc;
313
314 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
315 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
316
317 if (enop->eno_set_drv_limits != NULL) {
318 if ((rc = enop->eno_set_drv_limits(enp, edlp)) != 0)
319 goto fail1;
320 }
321
322 return (0);
323
324 fail1:
325 EFSYS_PROBE1(fail1, efx_rc_t, rc);
326
327 return (rc);
328 }
329
330 __checkReturn efx_rc_t
efx_nic_get_bar_region(__in efx_nic_t * enp,__in efx_nic_region_t region,__out uint32_t * offsetp,__out size_t * sizep)331 efx_nic_get_bar_region(
332 __in efx_nic_t *enp,
333 __in efx_nic_region_t region,
334 __out uint32_t *offsetp,
335 __out size_t *sizep)
336 {
337 const efx_nic_ops_t *enop = enp->en_enop;
338 efx_rc_t rc;
339
340 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
341 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
342 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
343
344 if (enop->eno_get_bar_region == NULL) {
345 rc = ENOTSUP;
346 goto fail1;
347 }
348 if ((rc = (enop->eno_get_bar_region)(enp,
349 region, offsetp, sizep)) != 0) {
350 goto fail2;
351 }
352
353 return (0);
354
355 fail2:
356 EFSYS_PROBE(fail2);
357
358 fail1:
359 EFSYS_PROBE1(fail1, efx_rc_t, rc);
360
361 return (rc);
362 }
363
364
365 __checkReturn efx_rc_t
efx_nic_get_vi_pool(__in efx_nic_t * enp,__out uint32_t * evq_countp,__out uint32_t * rxq_countp,__out uint32_t * txq_countp)366 efx_nic_get_vi_pool(
367 __in efx_nic_t *enp,
368 __out uint32_t *evq_countp,
369 __out uint32_t *rxq_countp,
370 __out uint32_t *txq_countp)
371 {
372 const efx_nic_ops_t *enop = enp->en_enop;
373 efx_nic_cfg_t *encp = &enp->en_nic_cfg;
374 efx_rc_t rc;
375
376 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
377 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
378 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
379
380 if (enop->eno_get_vi_pool != NULL) {
381 uint32_t vi_count = 0;
382
383 if ((rc = (enop->eno_get_vi_pool)(enp, &vi_count)) != 0)
384 goto fail1;
385
386 *evq_countp = vi_count;
387 *rxq_countp = vi_count;
388 *txq_countp = vi_count;
389 } else {
390 /* Use NIC limits as default value */
391 *evq_countp = encp->enc_evq_limit;
392 *rxq_countp = encp->enc_rxq_limit;
393 *txq_countp = encp->enc_txq_limit;
394 }
395
396 return (0);
397
398 fail1:
399 EFSYS_PROBE1(fail1, efx_rc_t, rc);
400
401 return (rc);
402 }
403
404
405 __checkReturn efx_rc_t
efx_nic_init(__in efx_nic_t * enp)406 efx_nic_init(
407 __in efx_nic_t *enp)
408 {
409 const efx_nic_ops_t *enop = enp->en_enop;
410 efx_rc_t rc;
411
412 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
413 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
414
415 if (enp->en_mod_flags & EFX_MOD_NIC) {
416 rc = EINVAL;
417 goto fail1;
418 }
419
420 if ((rc = enop->eno_init(enp)) != 0)
421 goto fail2;
422
423 enp->en_mod_flags |= EFX_MOD_NIC;
424
425 return (0);
426
427 fail2:
428 EFSYS_PROBE(fail2);
429 fail1:
430 EFSYS_PROBE1(fail1, efx_rc_t, rc);
431
432 return (rc);
433 }
434
435 void
efx_nic_fini(__in efx_nic_t * enp)436 efx_nic_fini(
437 __in efx_nic_t *enp)
438 {
439 const efx_nic_ops_t *enop = enp->en_enop;
440
441 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
442 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
443 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_NIC);
444 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
445 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
446 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
447 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
448
449 enop->eno_fini(enp);
450
451 enp->en_mod_flags &= ~EFX_MOD_NIC;
452 }
453
454 void
efx_nic_unprobe(__in efx_nic_t * enp)455 efx_nic_unprobe(
456 __in efx_nic_t *enp)
457 {
458 const efx_nic_ops_t *enop = enp->en_enop;
459
460 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
461 #if EFSYS_OPT_MCDI
462 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
463 #endif /* EFSYS_OPT_MCDI */
464 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
465 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
466 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
467 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
468 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
469 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
470
471 efx_phy_unprobe(enp);
472
473 enop->eno_unprobe(enp);
474
475 enp->en_mod_flags &= ~EFX_MOD_PROBE;
476 }
477
478 void
efx_nic_destroy(__in efx_nic_t * enp)479 efx_nic_destroy(
480 __in efx_nic_t *enp)
481 {
482 efsys_identifier_t *esip = enp->en_esip;
483
484 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
485 EFSYS_ASSERT3U(enp->en_mod_flags, ==, 0);
486
487 enp->en_family = EFX_FAMILY_INVALID;
488 enp->en_esip = NULL;
489 enp->en_esbp = NULL;
490 enp->en_eslp = NULL;
491
492 enp->en_enop = NULL;
493
494 enp->en_magic = 0;
495
496 /* Free the NIC object */
497 EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
498 }
499
500 __checkReturn efx_rc_t
efx_nic_reset(__in efx_nic_t * enp)501 efx_nic_reset(
502 __in efx_nic_t *enp)
503 {
504 const efx_nic_ops_t *enop = enp->en_enop;
505 unsigned int mod_flags;
506 efx_rc_t rc;
507
508 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
509 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
510 /*
511 * All modules except the MCDI, PROBE, NVRAM, VPD, MON
512 * (which we do not reset here) must have been shut down or never
513 * initialized.
514 *
515 * A rule of thumb here is: If the controller or MC reboots, is *any*
516 * state lost. If it's lost and needs reapplying, then the module
517 * *must* not be initialised during the reset.
518 */
519 mod_flags = enp->en_mod_flags;
520 mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM |
521 EFX_MOD_VPD | EFX_MOD_MON);
522 EFSYS_ASSERT3U(mod_flags, ==, 0);
523 if (mod_flags != 0) {
524 rc = EINVAL;
525 goto fail1;
526 }
527
528 if ((rc = enop->eno_reset(enp)) != 0)
529 goto fail2;
530
531 return (0);
532
533 fail2:
534 EFSYS_PROBE(fail2);
535 fail1:
536 EFSYS_PROBE1(fail1, efx_rc_t, rc);
537
538 return (rc);
539 }
540
541 const efx_nic_cfg_t *
efx_nic_cfg_get(__in efx_nic_t * enp)542 efx_nic_cfg_get(
543 __in efx_nic_t *enp)
544 {
545 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
546 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
547
548 return (&(enp->en_nic_cfg));
549 }
550
551 #if EFSYS_OPT_DIAG
552
553 __checkReturn efx_rc_t
efx_nic_register_test(__in efx_nic_t * enp)554 efx_nic_register_test(
555 __in efx_nic_t *enp)
556 {
557 const efx_nic_ops_t *enop = enp->en_enop;
558 efx_rc_t rc;
559
560 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
561 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
562 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
563
564 if ((rc = enop->eno_register_test(enp)) != 0)
565 goto fail1;
566
567 return (0);
568
569 fail1:
570 EFSYS_PROBE1(fail1, efx_rc_t, rc);
571
572 return (rc);
573 }
574
575 #endif /* EFSYS_OPT_DIAG */
576
577 #if EFSYS_OPT_LOOPBACK
578
579 extern void
efx_loopback_mask(__in efx_loopback_kind_t loopback_kind,__out efx_qword_t * maskp)580 efx_loopback_mask(
581 __in efx_loopback_kind_t loopback_kind,
582 __out efx_qword_t *maskp)
583 {
584 efx_qword_t mask;
585
586 EFSYS_ASSERT3U(loopback_kind, <, EFX_LOOPBACK_NKINDS);
587 EFSYS_ASSERT(maskp != NULL);
588
589 /* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespace agree */
590 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_NONE == EFX_LOOPBACK_OFF);
591 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_DATA == EFX_LOOPBACK_DATA);
592 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMAC == EFX_LOOPBACK_GMAC);
593 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII == EFX_LOOPBACK_XGMII);
594 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGXS == EFX_LOOPBACK_XGXS);
595 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI == EFX_LOOPBACK_XAUI);
596 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII == EFX_LOOPBACK_GMII);
597 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII == EFX_LOOPBACK_SGMII);
598 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGBR == EFX_LOOPBACK_XGBR);
599 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI == EFX_LOOPBACK_XFI);
600 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_FAR == EFX_LOOPBACK_XAUI_FAR);
601 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_FAR == EFX_LOOPBACK_GMII_FAR);
602 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII_FAR == EFX_LOOPBACK_SGMII_FAR);
603 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_FAR == EFX_LOOPBACK_XFI_FAR);
604 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GPHY == EFX_LOOPBACK_GPHY);
605 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS == EFX_LOOPBACK_PHY_XS);
606 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PCS == EFX_LOOPBACK_PCS);
607 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMAPMD == EFX_LOOPBACK_PMA_PMD);
608 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XPORT == EFX_LOOPBACK_XPORT);
609 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII_WS == EFX_LOOPBACK_XGMII_WS);
610 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_WS == EFX_LOOPBACK_XAUI_WS);
611 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_WS_FAR ==
612 EFX_LOOPBACK_XAUI_WS_FAR);
613 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_WS_NEAR ==
614 EFX_LOOPBACK_XAUI_WS_NEAR);
615 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_WS == EFX_LOOPBACK_GMII_WS);
616 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_WS == EFX_LOOPBACK_XFI_WS);
617 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_WS_FAR ==
618 EFX_LOOPBACK_XFI_WS_FAR);
619 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS_WS == EFX_LOOPBACK_PHYXS_WS);
620 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMA_INT == EFX_LOOPBACK_PMA_INT);
621 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_NEAR == EFX_LOOPBACK_SD_NEAR);
622 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FAR == EFX_LOOPBACK_SD_FAR);
623 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMA_INT_WS ==
624 EFX_LOOPBACK_PMA_INT_WS);
625 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FEP2_WS ==
626 EFX_LOOPBACK_SD_FEP2_WS);
627 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FEP1_5_WS ==
628 EFX_LOOPBACK_SD_FEP1_5_WS);
629 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FEP_WS == EFX_LOOPBACK_SD_FEP_WS);
630 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FES_WS == EFX_LOOPBACK_SD_FES_WS);
631
632 /* Build bitmask of possible loopback types */
633 EFX_ZERO_QWORD(mask);
634
635 if ((loopback_kind == EFX_LOOPBACK_KIND_OFF) ||
636 (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
637 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_OFF);
638 }
639
640 if ((loopback_kind == EFX_LOOPBACK_KIND_MAC) ||
641 (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
642 /*
643 * The "MAC" grouping has historically been used by drivers to
644 * mean loopbacks supported by on-chip hardware. Keep that
645 * meaning here, and include on-chip PHY layer loopbacks.
646 */
647 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_DATA);
648 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMAC);
649 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGMII);
650 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGXS);
651 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI);
652 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII);
653 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII);
654 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGBR);
655 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI);
656 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI_FAR);
657 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII_FAR);
658 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII_FAR);
659 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI_FAR);
660 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_INT);
661 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_NEAR);
662 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_FAR);
663 }
664
665 if ((loopback_kind == EFX_LOOPBACK_KIND_PHY) ||
666 (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
667 /*
668 * The "PHY" grouping has historically been used by drivers to
669 * mean loopbacks supported by off-chip hardware. Keep that
670 * meaning here.
671 */
672 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GPHY);
673 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PHY_XS);
674 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PCS);
675 EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_PMD);
676 }
677
678 *maskp = mask;
679 }
680
681 __checkReturn efx_rc_t
efx_mcdi_get_loopback_modes(__in efx_nic_t * enp)682 efx_mcdi_get_loopback_modes(
683 __in efx_nic_t *enp)
684 {
685 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
686 efx_mcdi_req_t req;
687 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LOOPBACK_MODES_IN_LEN,
688 MC_CMD_GET_LOOPBACK_MODES_OUT_LEN);
689 efx_qword_t mask;
690 efx_qword_t modes;
691 efx_rc_t rc;
692
693 req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES;
694 req.emr_in_buf = payload;
695 req.emr_in_length = MC_CMD_GET_LOOPBACK_MODES_IN_LEN;
696 req.emr_out_buf = payload;
697 req.emr_out_length = MC_CMD_GET_LOOPBACK_MODES_OUT_LEN;
698
699 efx_mcdi_execute(enp, &req);
700
701 if (req.emr_rc != 0) {
702 rc = req.emr_rc;
703 goto fail1;
704 }
705
706 if (req.emr_out_length_used <
707 MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST +
708 MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN) {
709 rc = EMSGSIZE;
710 goto fail2;
711 }
712
713 /*
714 * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree
715 * in efx_loopback_mask() and in siena_phy.c:siena_phy_get_link().
716 */
717 efx_loopback_mask(EFX_LOOPBACK_KIND_ALL, &mask);
718
719 EFX_AND_QWORD(mask,
720 *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_SUGGESTED));
721
722 modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_100M);
723 EFX_AND_QWORD(modes, mask);
724 encp->enc_loopback_types[EFX_LINK_100FDX] = modes;
725
726 modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_1G);
727 EFX_AND_QWORD(modes, mask);
728 encp->enc_loopback_types[EFX_LINK_1000FDX] = modes;
729
730 modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_10G);
731 EFX_AND_QWORD(modes, mask);
732 encp->enc_loopback_types[EFX_LINK_10000FDX] = modes;
733
734 if (req.emr_out_length_used >=
735 MC_CMD_GET_LOOPBACK_MODES_OUT_40G_OFST +
736 MC_CMD_GET_LOOPBACK_MODES_OUT_40G_LEN) {
737 /* Response includes 40G loopback modes */
738 modes =
739 *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_40G);
740 EFX_AND_QWORD(modes, mask);
741 encp->enc_loopback_types[EFX_LINK_40000FDX] = modes;
742 }
743
744 EFX_ZERO_QWORD(modes);
745 EFX_SET_QWORD_BIT(modes, EFX_LOOPBACK_OFF);
746 EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_100FDX]);
747 EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_1000FDX]);
748 EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_10000FDX]);
749 EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_40000FDX]);
750 encp->enc_loopback_types[EFX_LINK_UNKNOWN] = modes;
751
752 return (0);
753
754 fail2:
755 EFSYS_PROBE(fail2);
756 fail1:
757 EFSYS_PROBE1(fail1, efx_rc_t, rc);
758
759 return (rc);
760 }
761
762 #endif /* EFSYS_OPT_LOOPBACK */
763
764 __checkReturn efx_rc_t
efx_nic_calculate_pcie_link_bandwidth(__in uint32_t pcie_link_width,__in uint32_t pcie_link_gen,__out uint32_t * bandwidth_mbpsp)765 efx_nic_calculate_pcie_link_bandwidth(
766 __in uint32_t pcie_link_width,
767 __in uint32_t pcie_link_gen,
768 __out uint32_t *bandwidth_mbpsp)
769 {
770 uint32_t lane_bandwidth;
771 uint32_t total_bandwidth;
772 efx_rc_t rc;
773
774 if ((pcie_link_width == 0) || (pcie_link_width > 16) ||
775 !ISP2(pcie_link_width)) {
776 rc = EINVAL;
777 goto fail1;
778 }
779
780 switch (pcie_link_gen) {
781 case EFX_PCIE_LINK_SPEED_GEN1:
782 /* 2.5 Gb/s raw bandwidth with 8b/10b encoding */
783 lane_bandwidth = 2000;
784 break;
785 case EFX_PCIE_LINK_SPEED_GEN2:
786 /* 5.0 Gb/s raw bandwidth with 8b/10b encoding */
787 lane_bandwidth = 4000;
788 break;
789 case EFX_PCIE_LINK_SPEED_GEN3:
790 /* 8.0 Gb/s raw bandwidth with 128b/130b encoding */
791 lane_bandwidth = 7877;
792 break;
793 default:
794 rc = EINVAL;
795 goto fail2;
796 }
797
798 total_bandwidth = lane_bandwidth * pcie_link_width;
799 *bandwidth_mbpsp = total_bandwidth;
800
801 return (0);
802
803 fail2:
804 EFSYS_PROBE(fail2);
805 fail1:
806 EFSYS_PROBE1(fail1, efx_rc_t, rc);
807
808 return (rc);
809 }
810
811
812 __checkReturn efx_rc_t
efx_nic_check_pcie_link_speed(__in efx_nic_t * enp,__in uint32_t pcie_link_width,__in uint32_t pcie_link_gen,__out efx_pcie_link_performance_t * resultp)813 efx_nic_check_pcie_link_speed(
814 __in efx_nic_t *enp,
815 __in uint32_t pcie_link_width,
816 __in uint32_t pcie_link_gen,
817 __out efx_pcie_link_performance_t *resultp)
818 {
819 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
820 uint32_t bandwidth;
821 efx_pcie_link_performance_t result;
822 efx_rc_t rc;
823
824 if ((encp->enc_required_pcie_bandwidth_mbps == 0) ||
825 (pcie_link_width == 0) || (pcie_link_width == 32) ||
826 (pcie_link_gen == 0)) {
827 /*
828 * No usable info on what is required and/or in use. In virtual
829 * machines, sometimes the PCIe link width is reported as 0 or
830 * 32, or the speed as 0.
831 */
832 result = EFX_PCIE_LINK_PERFORMANCE_UNKNOWN_BANDWIDTH;
833 goto out;
834 }
835
836 /* Calculate the available bandwidth in megabits per second */
837 rc = efx_nic_calculate_pcie_link_bandwidth(pcie_link_width,
838 pcie_link_gen, &bandwidth);
839 if (rc != 0)
840 goto fail1;
841
842 if (bandwidth < encp->enc_required_pcie_bandwidth_mbps) {
843 result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_BANDWIDTH;
844 } else if (pcie_link_gen < encp->enc_max_pcie_link_gen) {
845 /* The link provides enough bandwidth but not optimal latency */
846 result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_LATENCY;
847 } else {
848 result = EFX_PCIE_LINK_PERFORMANCE_OPTIMAL;
849 }
850
851 out:
852 *resultp = result;
853
854 return (0);
855
856 fail1:
857 EFSYS_PROBE1(fail1, efx_rc_t, rc);
858
859 return (rc);
860 }
861