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