xref: /dpdk/drivers/common/sfc_efx/base/efx_nic.c (revision 60fb370c7bc95cdf74dd00a0ab0d779e21d71b23)
15e111ed8SAndrew Rybchenko /* SPDX-License-Identifier: BSD-3-Clause
25e111ed8SAndrew Rybchenko  *
3672386c1SAndrew Rybchenko  * Copyright(c) 2019-2021 Xilinx, Inc.
45e111ed8SAndrew Rybchenko  * Copyright(c) 2007-2019 Solarflare Communications Inc.
55e111ed8SAndrew Rybchenko  */
65e111ed8SAndrew Rybchenko 
75e111ed8SAndrew Rybchenko #include "efx.h"
85e111ed8SAndrew Rybchenko #include "efx_impl.h"
95e111ed8SAndrew Rybchenko 
105e111ed8SAndrew Rybchenko 
115e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_family(__in uint16_t venid,__in uint16_t devid,__out efx_family_t * efp,__out unsigned int * membarp)125e111ed8SAndrew Rybchenko efx_family(
135e111ed8SAndrew Rybchenko 	__in		uint16_t venid,
145e111ed8SAndrew Rybchenko 	__in		uint16_t devid,
155e111ed8SAndrew Rybchenko 	__out		efx_family_t *efp,
165e111ed8SAndrew Rybchenko 	__out		unsigned int *membarp)
175e111ed8SAndrew Rybchenko {
185e111ed8SAndrew Rybchenko 	if (venid == EFX_PCI_VENID_SFC) {
195e111ed8SAndrew Rybchenko 		switch (devid) {
205e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA
215e111ed8SAndrew Rybchenko 		case EFX_PCI_DEVID_SIENA_F1_UNINIT:
225e111ed8SAndrew Rybchenko 			/*
235e111ed8SAndrew Rybchenko 			 * Hardware default for PF0 of uninitialised Siena.
245e111ed8SAndrew Rybchenko 			 * manftest must be able to cope with this device id.
255e111ed8SAndrew Rybchenko 			 */
265e111ed8SAndrew Rybchenko 		case EFX_PCI_DEVID_BETHPAGE:
275e111ed8SAndrew Rybchenko 		case EFX_PCI_DEVID_SIENA:
285e111ed8SAndrew Rybchenko 			*efp = EFX_FAMILY_SIENA;
295e111ed8SAndrew Rybchenko 			*membarp = EFX_MEM_BAR_SIENA;
305e111ed8SAndrew Rybchenko 			return (0);
315e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
325e111ed8SAndrew Rybchenko 
335e111ed8SAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
345e111ed8SAndrew Rybchenko 		case EFX_PCI_DEVID_HUNTINGTON_PF_UNINIT:
355e111ed8SAndrew Rybchenko 			/*
365e111ed8SAndrew Rybchenko 			 * Hardware default for PF0 of uninitialised Huntington.
375e111ed8SAndrew Rybchenko 			 * manftest must be able to cope with this device id.
385e111ed8SAndrew Rybchenko 			 */
395e111ed8SAndrew Rybchenko 		case EFX_PCI_DEVID_FARMINGDALE:
405e111ed8SAndrew Rybchenko 		case EFX_PCI_DEVID_GREENPORT:
415e111ed8SAndrew Rybchenko 			*efp = EFX_FAMILY_HUNTINGTON;
425e111ed8SAndrew Rybchenko 			*membarp = EFX_MEM_BAR_HUNTINGTON_PF;
435e111ed8SAndrew Rybchenko 			return (0);
445e111ed8SAndrew Rybchenko 
455e111ed8SAndrew Rybchenko 		case EFX_PCI_DEVID_FARMINGDALE_VF:
465e111ed8SAndrew Rybchenko 		case EFX_PCI_DEVID_GREENPORT_VF:
475e111ed8SAndrew Rybchenko 			*efp = EFX_FAMILY_HUNTINGTON;
485e111ed8SAndrew Rybchenko 			*membarp = EFX_MEM_BAR_HUNTINGTON_VF;
495e111ed8SAndrew Rybchenko 			return (0);
505e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */
515e111ed8SAndrew Rybchenko 
525e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD
535e111ed8SAndrew Rybchenko 		case EFX_PCI_DEVID_MEDFORD_PF_UNINIT:
545e111ed8SAndrew Rybchenko 			/*
555e111ed8SAndrew Rybchenko 			 * Hardware default for PF0 of uninitialised Medford.
565e111ed8SAndrew Rybchenko 			 * manftest must be able to cope with this device id.
575e111ed8SAndrew Rybchenko 			 */
585e111ed8SAndrew Rybchenko 		case EFX_PCI_DEVID_MEDFORD:
595e111ed8SAndrew Rybchenko 			*efp = EFX_FAMILY_MEDFORD;
605e111ed8SAndrew Rybchenko 			*membarp = EFX_MEM_BAR_MEDFORD_PF;
615e111ed8SAndrew Rybchenko 			return (0);
625e111ed8SAndrew Rybchenko 
635e111ed8SAndrew Rybchenko 		case EFX_PCI_DEVID_MEDFORD_VF:
645e111ed8SAndrew Rybchenko 			*efp = EFX_FAMILY_MEDFORD;
655e111ed8SAndrew Rybchenko 			*membarp = EFX_MEM_BAR_MEDFORD_VF;
665e111ed8SAndrew Rybchenko 			return (0);
675e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */
685e111ed8SAndrew Rybchenko 
695e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
705e111ed8SAndrew Rybchenko 		case EFX_PCI_DEVID_MEDFORD2_PF_UNINIT:
715e111ed8SAndrew Rybchenko 			/*
725e111ed8SAndrew Rybchenko 			 * Hardware default for PF0 of uninitialised Medford2.
735e111ed8SAndrew Rybchenko 			 * manftest must be able to cope with this device id.
745e111ed8SAndrew Rybchenko 			 */
755e111ed8SAndrew Rybchenko 		case EFX_PCI_DEVID_MEDFORD2:
765e111ed8SAndrew Rybchenko 		case EFX_PCI_DEVID_MEDFORD2_VF:
775e111ed8SAndrew Rybchenko 			*efp = EFX_FAMILY_MEDFORD2;
785e111ed8SAndrew Rybchenko 			*membarp = EFX_MEM_BAR_MEDFORD2;
795e111ed8SAndrew Rybchenko 			return (0);
805e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD2 */
815e111ed8SAndrew Rybchenko 
825e111ed8SAndrew Rybchenko 		case EFX_PCI_DEVID_FALCON:	/* Obsolete, not supported */
835e111ed8SAndrew Rybchenko 		default:
845e111ed8SAndrew Rybchenko 			break;
855e111ed8SAndrew Rybchenko 		}
865e111ed8SAndrew Rybchenko 	}
875e111ed8SAndrew Rybchenko 
88206ef24fSAndrew Rybchenko 	if (venid == EFX_PCI_VENID_XILINX) {
89206ef24fSAndrew Rybchenko 		switch (devid) {
90206ef24fSAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD
91206ef24fSAndrew Rybchenko 		case EFX_PCI_DEVID_RIVERHEAD:
92206ef24fSAndrew Rybchenko 		case EFX_PCI_DEVID_RIVERHEAD_VF:
93206ef24fSAndrew Rybchenko 			*efp = EFX_FAMILY_RIVERHEAD;
94206ef24fSAndrew Rybchenko 			*membarp = EFX_MEM_BAR_RIVERHEAD;
95206ef24fSAndrew Rybchenko 			return (0);
96206ef24fSAndrew Rybchenko #endif /* EFSYS_OPT_RIVERHEAD */
97206ef24fSAndrew Rybchenko 		default:
98206ef24fSAndrew Rybchenko 			break;
99206ef24fSAndrew Rybchenko 		}
100206ef24fSAndrew Rybchenko 	}
101206ef24fSAndrew Rybchenko 
1025e111ed8SAndrew Rybchenko 	*efp = EFX_FAMILY_INVALID;
1035e111ed8SAndrew Rybchenko 	return (ENOTSUP);
1045e111ed8SAndrew Rybchenko }
1055e111ed8SAndrew Rybchenko 
106a45edfceSIgor Romanov #if EFSYS_OPT_PCI
107a45edfceSIgor Romanov 
108a45edfceSIgor Romanov 	__checkReturn	efx_rc_t
efx_family_probe_bar(__in uint16_t venid,__in uint16_t devid,__in efsys_pci_config_t * espcp,__in const efx_pci_ops_t * epop,__out efx_family_t * efp,__out efx_bar_region_t * ebrp)109a45edfceSIgor Romanov efx_family_probe_bar(
110a45edfceSIgor Romanov 	__in		uint16_t venid,
111a45edfceSIgor Romanov 	__in		uint16_t devid,
112a45edfceSIgor Romanov 	__in		efsys_pci_config_t *espcp,
11307999984SIgor Romanov 	__in		const efx_pci_ops_t *epop,
114a45edfceSIgor Romanov 	__out		efx_family_t *efp,
115a45edfceSIgor Romanov 	__out		efx_bar_region_t *ebrp)
116a45edfceSIgor Romanov {
117a45edfceSIgor Romanov 	efx_rc_t rc;
118a45edfceSIgor Romanov 	unsigned int membar;
119a45edfceSIgor Romanov 
120a45edfceSIgor Romanov 	if (venid == EFX_PCI_VENID_XILINX) {
121a45edfceSIgor Romanov 		switch (devid) {
122a45edfceSIgor Romanov #if EFSYS_OPT_RIVERHEAD
123a45edfceSIgor Romanov 		case EFX_PCI_DEVID_RIVERHEAD:
124a45edfceSIgor Romanov 		case EFX_PCI_DEVID_RIVERHEAD_VF:
12507999984SIgor Romanov 			rc = rhead_pci_nic_membar_lookup(espcp, epop, ebrp);
126a45edfceSIgor Romanov 			if (rc == 0)
127a45edfceSIgor Romanov 				*efp = EFX_FAMILY_RIVERHEAD;
128a45edfceSIgor Romanov 
129a45edfceSIgor Romanov 			return (rc);
130a45edfceSIgor Romanov #endif /* EFSYS_OPT_RIVERHEAD */
131a45edfceSIgor Romanov 		default:
132a45edfceSIgor Romanov 			break;
133a45edfceSIgor Romanov 		}
134a45edfceSIgor Romanov 	}
135a45edfceSIgor Romanov 
136a45edfceSIgor Romanov 	rc = efx_family(venid, devid, efp, &membar);
137a45edfceSIgor Romanov 	if (rc == 0) {
138a45edfceSIgor Romanov 		ebrp->ebr_type = EFX_BAR_TYPE_MEM;
139a45edfceSIgor Romanov 		ebrp->ebr_index = membar;
140a45edfceSIgor Romanov 		ebrp->ebr_offset = 0;
141a45edfceSIgor Romanov 		ebrp->ebr_length = 0;
142a45edfceSIgor Romanov 	}
143a45edfceSIgor Romanov 
144a45edfceSIgor Romanov 	return (rc);
145a45edfceSIgor Romanov }
146a45edfceSIgor Romanov 
147a45edfceSIgor Romanov #endif /* EFSYS_OPT_PCI */
1485e111ed8SAndrew Rybchenko 
1495e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA
1505e111ed8SAndrew Rybchenko 
1515e111ed8SAndrew Rybchenko static const efx_nic_ops_t	__efx_nic_siena_ops = {
1525e111ed8SAndrew Rybchenko 	siena_nic_probe,		/* eno_probe */
1535e111ed8SAndrew Rybchenko 	NULL,				/* eno_board_cfg */
1545e111ed8SAndrew Rybchenko 	NULL,				/* eno_set_drv_limits */
1555e111ed8SAndrew Rybchenko 	siena_nic_reset,		/* eno_reset */
1565e111ed8SAndrew Rybchenko 	siena_nic_init,			/* eno_init */
1575e111ed8SAndrew Rybchenko 	NULL,				/* eno_get_vi_pool */
1585e111ed8SAndrew Rybchenko 	NULL,				/* eno_get_bar_region */
1595e111ed8SAndrew Rybchenko 	NULL,				/* eno_hw_unavailable */
1605e111ed8SAndrew Rybchenko 	NULL,				/* eno_set_hw_unavailable */
1615e111ed8SAndrew Rybchenko #if EFSYS_OPT_DIAG
1625e111ed8SAndrew Rybchenko 	siena_nic_register_test,	/* eno_register_test */
1635e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_DIAG */
1645e111ed8SAndrew Rybchenko 	siena_nic_fini,			/* eno_fini */
1655e111ed8SAndrew Rybchenko 	siena_nic_unprobe,		/* eno_unprobe */
1665e111ed8SAndrew Rybchenko };
1675e111ed8SAndrew Rybchenko 
1685e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_SIENA */
1695e111ed8SAndrew Rybchenko 
1705e111ed8SAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
1715e111ed8SAndrew Rybchenko 
1725e111ed8SAndrew Rybchenko static const efx_nic_ops_t	__efx_nic_hunt_ops = {
1735e111ed8SAndrew Rybchenko 	ef10_nic_probe,			/* eno_probe */
1745e111ed8SAndrew Rybchenko 	hunt_board_cfg,			/* eno_board_cfg */
1755e111ed8SAndrew Rybchenko 	ef10_nic_set_drv_limits,	/* eno_set_drv_limits */
1765e111ed8SAndrew Rybchenko 	ef10_nic_reset,			/* eno_reset */
1775e111ed8SAndrew Rybchenko 	ef10_nic_init,			/* eno_init */
1785e111ed8SAndrew Rybchenko 	ef10_nic_get_vi_pool,		/* eno_get_vi_pool */
1795e111ed8SAndrew Rybchenko 	ef10_nic_get_bar_region,	/* eno_get_bar_region */
1805e111ed8SAndrew Rybchenko 	ef10_nic_hw_unavailable,	/* eno_hw_unavailable */
1815e111ed8SAndrew Rybchenko 	ef10_nic_set_hw_unavailable,	/* eno_set_hw_unavailable */
1825e111ed8SAndrew Rybchenko #if EFSYS_OPT_DIAG
1835e111ed8SAndrew Rybchenko 	ef10_nic_register_test,		/* eno_register_test */
1845e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_DIAG */
1855e111ed8SAndrew Rybchenko 	ef10_nic_fini,			/* eno_fini */
1865e111ed8SAndrew Rybchenko 	ef10_nic_unprobe,		/* eno_unprobe */
1875e111ed8SAndrew Rybchenko };
1885e111ed8SAndrew Rybchenko 
1895e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_HUNTINGTON */
1905e111ed8SAndrew Rybchenko 
1915e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD
1925e111ed8SAndrew Rybchenko 
1935e111ed8SAndrew Rybchenko static const efx_nic_ops_t	__efx_nic_medford_ops = {
1945e111ed8SAndrew Rybchenko 	ef10_nic_probe,			/* eno_probe */
1955e111ed8SAndrew Rybchenko 	medford_board_cfg,		/* eno_board_cfg */
1965e111ed8SAndrew Rybchenko 	ef10_nic_set_drv_limits,	/* eno_set_drv_limits */
1975e111ed8SAndrew Rybchenko 	ef10_nic_reset,			/* eno_reset */
1985e111ed8SAndrew Rybchenko 	ef10_nic_init,			/* eno_init */
1995e111ed8SAndrew Rybchenko 	ef10_nic_get_vi_pool,		/* eno_get_vi_pool */
2005e111ed8SAndrew Rybchenko 	ef10_nic_get_bar_region,	/* eno_get_bar_region */
2015e111ed8SAndrew Rybchenko 	ef10_nic_hw_unavailable,	/* eno_hw_unavailable */
2025e111ed8SAndrew Rybchenko 	ef10_nic_set_hw_unavailable,	/* eno_set_hw_unavailable */
2035e111ed8SAndrew Rybchenko #if EFSYS_OPT_DIAG
2045e111ed8SAndrew Rybchenko 	ef10_nic_register_test,		/* eno_register_test */
2055e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_DIAG */
2065e111ed8SAndrew Rybchenko 	ef10_nic_fini,			/* eno_fini */
2075e111ed8SAndrew Rybchenko 	ef10_nic_unprobe,		/* eno_unprobe */
2085e111ed8SAndrew Rybchenko };
2095e111ed8SAndrew Rybchenko 
2105e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_MEDFORD */
2115e111ed8SAndrew Rybchenko 
2125e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
2135e111ed8SAndrew Rybchenko 
2145e111ed8SAndrew Rybchenko static const efx_nic_ops_t	__efx_nic_medford2_ops = {
2155e111ed8SAndrew Rybchenko 	ef10_nic_probe,			/* eno_probe */
2165e111ed8SAndrew Rybchenko 	medford2_board_cfg,		/* eno_board_cfg */
2175e111ed8SAndrew Rybchenko 	ef10_nic_set_drv_limits,	/* eno_set_drv_limits */
2185e111ed8SAndrew Rybchenko 	ef10_nic_reset,			/* eno_reset */
2195e111ed8SAndrew Rybchenko 	ef10_nic_init,			/* eno_init */
2205e111ed8SAndrew Rybchenko 	ef10_nic_get_vi_pool,		/* eno_get_vi_pool */
2215e111ed8SAndrew Rybchenko 	ef10_nic_get_bar_region,	/* eno_get_bar_region */
2225e111ed8SAndrew Rybchenko 	ef10_nic_hw_unavailable,	/* eno_hw_unavailable */
2235e111ed8SAndrew Rybchenko 	ef10_nic_set_hw_unavailable,	/* eno_set_hw_unavailable */
2245e111ed8SAndrew Rybchenko #if EFSYS_OPT_DIAG
2255e111ed8SAndrew Rybchenko 	ef10_nic_register_test,		/* eno_register_test */
2265e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_DIAG */
2275e111ed8SAndrew Rybchenko 	ef10_nic_fini,			/* eno_fini */
2285e111ed8SAndrew Rybchenko 	ef10_nic_unprobe,		/* eno_unprobe */
2295e111ed8SAndrew Rybchenko };
2305e111ed8SAndrew Rybchenko 
2315e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_MEDFORD2 */
2325e111ed8SAndrew Rybchenko 
2333c1c5cc4SAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD
2343c1c5cc4SAndrew Rybchenko 
2353c1c5cc4SAndrew Rybchenko static const efx_nic_ops_t	__efx_nic_riverhead_ops = {
2363c1c5cc4SAndrew Rybchenko 	rhead_nic_probe,		/* eno_probe */
2373c1c5cc4SAndrew Rybchenko 	rhead_board_cfg,		/* eno_board_cfg */
2383c1c5cc4SAndrew Rybchenko 	rhead_nic_set_drv_limits,	/* eno_set_drv_limits */
2393c1c5cc4SAndrew Rybchenko 	rhead_nic_reset,		/* eno_reset */
2403c1c5cc4SAndrew Rybchenko 	rhead_nic_init,			/* eno_init */
2413c1c5cc4SAndrew Rybchenko 	rhead_nic_get_vi_pool,		/* eno_get_vi_pool */
2423c1c5cc4SAndrew Rybchenko 	rhead_nic_get_bar_region,	/* eno_get_bar_region */
2433c1c5cc4SAndrew Rybchenko 	rhead_nic_hw_unavailable,	/* eno_hw_unavailable */
2443c1c5cc4SAndrew Rybchenko 	rhead_nic_set_hw_unavailable,	/* eno_set_hw_unavailable */
2453c1c5cc4SAndrew Rybchenko #if EFSYS_OPT_DIAG
2463c1c5cc4SAndrew Rybchenko 	rhead_nic_register_test,	/* eno_register_test */
2473c1c5cc4SAndrew Rybchenko #endif	/* EFSYS_OPT_DIAG */
2483c1c5cc4SAndrew Rybchenko 	rhead_nic_fini,			/* eno_fini */
2493c1c5cc4SAndrew Rybchenko 	rhead_nic_unprobe,		/* eno_unprobe */
2503c1c5cc4SAndrew Rybchenko };
2513c1c5cc4SAndrew Rybchenko 
2523c1c5cc4SAndrew Rybchenko #endif	/* EFSYS_OPT_RIVERHEAD */
2533c1c5cc4SAndrew Rybchenko 
2545e111ed8SAndrew Rybchenko 
2555e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_nic_create(__in efx_family_t family,__in efsys_identifier_t * esip,__in efsys_bar_t * esbp,__in uint32_t fcw_offset,__in efsys_lock_t * eslp,__deref_out efx_nic_t ** enpp)2565e111ed8SAndrew Rybchenko efx_nic_create(
2575e111ed8SAndrew Rybchenko 	__in		efx_family_t family,
2585e111ed8SAndrew Rybchenko 	__in		efsys_identifier_t *esip,
2595e111ed8SAndrew Rybchenko 	__in		efsys_bar_t *esbp,
260341bd4e0SIgor Romanov 	__in		uint32_t fcw_offset,
2615e111ed8SAndrew Rybchenko 	__in		efsys_lock_t *eslp,
2625e111ed8SAndrew Rybchenko 	__deref_out	efx_nic_t **enpp)
2635e111ed8SAndrew Rybchenko {
2645e111ed8SAndrew Rybchenko 	efx_nic_t *enp;
2655e111ed8SAndrew Rybchenko 	efx_rc_t rc;
2665e111ed8SAndrew Rybchenko 
2675e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(family, >, EFX_FAMILY_INVALID);
2685e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(family, <, EFX_FAMILY_NTYPES);
2695e111ed8SAndrew Rybchenko 
2705e111ed8SAndrew Rybchenko 	/* Allocate a NIC object */
2715e111ed8SAndrew Rybchenko 	EFSYS_KMEM_ALLOC(esip, sizeof (efx_nic_t), enp);
2725e111ed8SAndrew Rybchenko 
2735e111ed8SAndrew Rybchenko 	if (enp == NULL) {
2745e111ed8SAndrew Rybchenko 		rc = ENOMEM;
2755e111ed8SAndrew Rybchenko 		goto fail1;
2765e111ed8SAndrew Rybchenko 	}
2775e111ed8SAndrew Rybchenko 
2785e111ed8SAndrew Rybchenko 	enp->en_magic = EFX_NIC_MAGIC;
2795e111ed8SAndrew Rybchenko 
2805e111ed8SAndrew Rybchenko 	switch (family) {
2815e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA
2825e111ed8SAndrew Rybchenko 	case EFX_FAMILY_SIENA:
2835e111ed8SAndrew Rybchenko 		enp->en_enop = &__efx_nic_siena_ops;
2845e111ed8SAndrew Rybchenko 		enp->en_features =
2855e111ed8SAndrew Rybchenko 		    EFX_FEATURE_IPV6 |
2865e111ed8SAndrew Rybchenko 		    EFX_FEATURE_LFSR_HASH_INSERT |
2875e111ed8SAndrew Rybchenko 		    EFX_FEATURE_LINK_EVENTS |
2885e111ed8SAndrew Rybchenko 		    EFX_FEATURE_PERIODIC_MAC_STATS |
2895e111ed8SAndrew Rybchenko 		    EFX_FEATURE_MCDI |
2905e111ed8SAndrew Rybchenko 		    EFX_FEATURE_LOOKAHEAD_SPLIT |
2915e111ed8SAndrew Rybchenko 		    EFX_FEATURE_MAC_HEADER_FILTERS |
2925e111ed8SAndrew Rybchenko 		    EFX_FEATURE_TX_SRC_FILTERS;
2935e111ed8SAndrew Rybchenko 		break;
2945e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_SIENA */
2955e111ed8SAndrew Rybchenko 
2965e111ed8SAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
2975e111ed8SAndrew Rybchenko 	case EFX_FAMILY_HUNTINGTON:
2985e111ed8SAndrew Rybchenko 		enp->en_enop = &__efx_nic_hunt_ops;
2995e111ed8SAndrew Rybchenko 		enp->en_features =
3005e111ed8SAndrew Rybchenko 		    EFX_FEATURE_IPV6 |
3015e111ed8SAndrew Rybchenko 		    EFX_FEATURE_LINK_EVENTS |
3025e111ed8SAndrew Rybchenko 		    EFX_FEATURE_PERIODIC_MAC_STATS |
3035e111ed8SAndrew Rybchenko 		    EFX_FEATURE_MCDI |
3045e111ed8SAndrew Rybchenko 		    EFX_FEATURE_MAC_HEADER_FILTERS |
3055e111ed8SAndrew Rybchenko 		    EFX_FEATURE_MCDI_DMA |
3065e111ed8SAndrew Rybchenko 		    EFX_FEATURE_PIO_BUFFERS |
3075e111ed8SAndrew Rybchenko 		    EFX_FEATURE_FW_ASSISTED_TSO |
3085e111ed8SAndrew Rybchenko 		    EFX_FEATURE_FW_ASSISTED_TSO_V2 |
3095e111ed8SAndrew Rybchenko 		    EFX_FEATURE_PACKED_STREAM |
3105e111ed8SAndrew Rybchenko 		    EFX_FEATURE_TXQ_CKSUM_OP_DESC;
3115e111ed8SAndrew Rybchenko 		break;
3125e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_HUNTINGTON */
3135e111ed8SAndrew Rybchenko 
3145e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD
3155e111ed8SAndrew Rybchenko 	case EFX_FAMILY_MEDFORD:
3165e111ed8SAndrew Rybchenko 		enp->en_enop = &__efx_nic_medford_ops;
3175e111ed8SAndrew Rybchenko 		/*
3185e111ed8SAndrew Rybchenko 		 * FW_ASSISTED_TSO omitted as Medford only supports firmware
3195e111ed8SAndrew Rybchenko 		 * assisted TSO version 2, not the v1 scheme used on Huntington.
3205e111ed8SAndrew Rybchenko 		 */
3215e111ed8SAndrew Rybchenko 		enp->en_features =
3225e111ed8SAndrew Rybchenko 		    EFX_FEATURE_IPV6 |
3235e111ed8SAndrew Rybchenko 		    EFX_FEATURE_LINK_EVENTS |
3245e111ed8SAndrew Rybchenko 		    EFX_FEATURE_PERIODIC_MAC_STATS |
3255e111ed8SAndrew Rybchenko 		    EFX_FEATURE_MCDI |
3265e111ed8SAndrew Rybchenko 		    EFX_FEATURE_MAC_HEADER_FILTERS |
3275e111ed8SAndrew Rybchenko 		    EFX_FEATURE_MCDI_DMA |
3285e111ed8SAndrew Rybchenko 		    EFX_FEATURE_PIO_BUFFERS |
3295e111ed8SAndrew Rybchenko 		    EFX_FEATURE_FW_ASSISTED_TSO_V2 |
3305e111ed8SAndrew Rybchenko 		    EFX_FEATURE_PACKED_STREAM |
3315e111ed8SAndrew Rybchenko 		    EFX_FEATURE_TXQ_CKSUM_OP_DESC;
3325e111ed8SAndrew Rybchenko 		break;
3335e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_MEDFORD */
3345e111ed8SAndrew Rybchenko 
3355e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
3365e111ed8SAndrew Rybchenko 	case EFX_FAMILY_MEDFORD2:
3375e111ed8SAndrew Rybchenko 		enp->en_enop = &__efx_nic_medford2_ops;
3385e111ed8SAndrew Rybchenko 		enp->en_features =
3395e111ed8SAndrew Rybchenko 		    EFX_FEATURE_IPV6 |
3405e111ed8SAndrew Rybchenko 		    EFX_FEATURE_LINK_EVENTS |
3415e111ed8SAndrew Rybchenko 		    EFX_FEATURE_PERIODIC_MAC_STATS |
3425e111ed8SAndrew Rybchenko 		    EFX_FEATURE_MCDI |
3435e111ed8SAndrew Rybchenko 		    EFX_FEATURE_MAC_HEADER_FILTERS |
3445e111ed8SAndrew Rybchenko 		    EFX_FEATURE_MCDI_DMA |
3455e111ed8SAndrew Rybchenko 		    EFX_FEATURE_PIO_BUFFERS |
3465e111ed8SAndrew Rybchenko 		    EFX_FEATURE_FW_ASSISTED_TSO_V2 |
3475e111ed8SAndrew Rybchenko 		    EFX_FEATURE_PACKED_STREAM |
3485e111ed8SAndrew Rybchenko 		    EFX_FEATURE_TXQ_CKSUM_OP_DESC;
3495e111ed8SAndrew Rybchenko 		break;
3505e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_MEDFORD2 */
3515e111ed8SAndrew Rybchenko 
3523c1c5cc4SAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD
3533c1c5cc4SAndrew Rybchenko 	case EFX_FAMILY_RIVERHEAD:
3543c1c5cc4SAndrew Rybchenko 		enp->en_enop = &__efx_nic_riverhead_ops;
3553c1c5cc4SAndrew Rybchenko 		enp->en_features =
3563c1c5cc4SAndrew Rybchenko 		    EFX_FEATURE_IPV6 |
3573c1c5cc4SAndrew Rybchenko 		    EFX_FEATURE_LINK_EVENTS |
3583c1c5cc4SAndrew Rybchenko 		    EFX_FEATURE_PERIODIC_MAC_STATS |
3593c1c5cc4SAndrew Rybchenko 		    EFX_FEATURE_MCDI |
3603c1c5cc4SAndrew Rybchenko 		    EFX_FEATURE_MAC_HEADER_FILTERS |
3613c1c5cc4SAndrew Rybchenko 		    EFX_FEATURE_MCDI_DMA;
362341bd4e0SIgor Romanov 		enp->en_arch.ef10.ena_fcw_base = fcw_offset;
3633c1c5cc4SAndrew Rybchenko 		break;
3643c1c5cc4SAndrew Rybchenko #endif	/* EFSYS_OPT_RIVERHEAD */
3653c1c5cc4SAndrew Rybchenko 
3665e111ed8SAndrew Rybchenko 	default:
3675e111ed8SAndrew Rybchenko 		rc = ENOTSUP;
3685e111ed8SAndrew Rybchenko 		goto fail2;
3695e111ed8SAndrew Rybchenko 	}
3705e111ed8SAndrew Rybchenko 
371341bd4e0SIgor Romanov 	if ((family != EFX_FAMILY_RIVERHEAD) && (fcw_offset != 0)) {
372341bd4e0SIgor Romanov 		rc = EINVAL;
373341bd4e0SIgor Romanov 		goto fail3;
374341bd4e0SIgor Romanov 	}
375341bd4e0SIgor Romanov 
3765e111ed8SAndrew Rybchenko 	enp->en_family = family;
3775e111ed8SAndrew Rybchenko 	enp->en_esip = esip;
3785e111ed8SAndrew Rybchenko 	enp->en_esbp = esbp;
3795e111ed8SAndrew Rybchenko 	enp->en_eslp = eslp;
3805e111ed8SAndrew Rybchenko 
3815e111ed8SAndrew Rybchenko 	*enpp = enp;
3825e111ed8SAndrew Rybchenko 
3835e111ed8SAndrew Rybchenko 	return (0);
3845e111ed8SAndrew Rybchenko 
385341bd4e0SIgor Romanov fail3:
386341bd4e0SIgor Romanov 	EFSYS_PROBE(fail3);
3875e111ed8SAndrew Rybchenko fail2:
3885e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
3895e111ed8SAndrew Rybchenko 
3905e111ed8SAndrew Rybchenko 	enp->en_magic = 0;
3915e111ed8SAndrew Rybchenko 
3925e111ed8SAndrew Rybchenko 	/* Free the NIC object */
3935e111ed8SAndrew Rybchenko 	EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
3945e111ed8SAndrew Rybchenko 
3955e111ed8SAndrew Rybchenko fail1:
3965e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
3975e111ed8SAndrew Rybchenko 
3985e111ed8SAndrew Rybchenko 	return (rc);
3995e111ed8SAndrew Rybchenko }
4005e111ed8SAndrew Rybchenko 
4015e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_nic_probe(__in efx_nic_t * enp,__in efx_fw_variant_t efv)4025e111ed8SAndrew Rybchenko efx_nic_probe(
4035e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
4045e111ed8SAndrew Rybchenko 	__in		efx_fw_variant_t efv)
4055e111ed8SAndrew Rybchenko {
406538fd2acSAndrew Rybchenko 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
4075e111ed8SAndrew Rybchenko 	const efx_nic_ops_t *enop;
4085e111ed8SAndrew Rybchenko 	efx_rc_t rc;
4095e111ed8SAndrew Rybchenko 
4105e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
4115e111ed8SAndrew Rybchenko #if EFSYS_OPT_MCDI
4125e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
4135e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_MCDI */
4145e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_PROBE));
4155e111ed8SAndrew Rybchenko 
4165e111ed8SAndrew Rybchenko 	/* Ensure FW variant codes match with MC_CMD_FW codes */
4175e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_FW_VARIANT_FULL_FEATURED ==
4185e111ed8SAndrew Rybchenko 	    MC_CMD_FW_FULL_FEATURED);
4195e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_FW_VARIANT_LOW_LATENCY ==
4205e111ed8SAndrew Rybchenko 	    MC_CMD_FW_LOW_LATENCY);
4215e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_FW_VARIANT_PACKED_STREAM ==
4225e111ed8SAndrew Rybchenko 	    MC_CMD_FW_PACKED_STREAM);
4235e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_FW_VARIANT_HIGH_TX_RATE ==
4245e111ed8SAndrew Rybchenko 	    MC_CMD_FW_HIGH_TX_RATE);
4255e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_FW_VARIANT_PACKED_STREAM_HASH_MODE_1 ==
4265e111ed8SAndrew Rybchenko 	    MC_CMD_FW_PACKED_STREAM_HASH_MODE_1);
4275e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_FW_VARIANT_RULES_ENGINE ==
4285e111ed8SAndrew Rybchenko 	    MC_CMD_FW_RULES_ENGINE);
4295e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_FW_VARIANT_DPDK ==
4305e111ed8SAndrew Rybchenko 	    MC_CMD_FW_DPDK);
4315e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_FW_VARIANT_DONT_CARE ==
4325e111ed8SAndrew Rybchenko 	    (int)MC_CMD_FW_DONT_CARE);
4335e111ed8SAndrew Rybchenko 
4345e111ed8SAndrew Rybchenko 	enop = enp->en_enop;
4355e111ed8SAndrew Rybchenko 	enp->efv = efv;
4365e111ed8SAndrew Rybchenko 
4375e111ed8SAndrew Rybchenko 	if ((rc = enop->eno_probe(enp)) != 0)
4385e111ed8SAndrew Rybchenko 		goto fail1;
4395e111ed8SAndrew Rybchenko 
440538fd2acSAndrew Rybchenko 	encp->enc_features = enp->en_features;
441538fd2acSAndrew Rybchenko 
4425e111ed8SAndrew Rybchenko 	if ((rc = efx_phy_probe(enp)) != 0)
4435e111ed8SAndrew Rybchenko 		goto fail2;
4445e111ed8SAndrew Rybchenko 
4455e111ed8SAndrew Rybchenko 	enp->en_mod_flags |= EFX_MOD_PROBE;
4465e111ed8SAndrew Rybchenko 
4475e111ed8SAndrew Rybchenko 	return (0);
4485e111ed8SAndrew Rybchenko 
4495e111ed8SAndrew Rybchenko fail2:
4505e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
4515e111ed8SAndrew Rybchenko 
4525e111ed8SAndrew Rybchenko 	enop->eno_unprobe(enp);
4535e111ed8SAndrew Rybchenko 
4545e111ed8SAndrew Rybchenko fail1:
4555e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
4565e111ed8SAndrew Rybchenko 
4575e111ed8SAndrew Rybchenko 	return (rc);
4585e111ed8SAndrew Rybchenko }
4595e111ed8SAndrew Rybchenko 
4605e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_nic_set_drv_limits(__inout efx_nic_t * enp,__in efx_drv_limits_t * edlp)4615e111ed8SAndrew Rybchenko efx_nic_set_drv_limits(
4625e111ed8SAndrew Rybchenko 	__inout		efx_nic_t *enp,
4635e111ed8SAndrew Rybchenko 	__in		efx_drv_limits_t *edlp)
4645e111ed8SAndrew Rybchenko {
4655e111ed8SAndrew Rybchenko 	const efx_nic_ops_t *enop = enp->en_enop;
4665e111ed8SAndrew Rybchenko 	efx_rc_t rc;
4675e111ed8SAndrew Rybchenko 
4685e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
4695e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
4705e111ed8SAndrew Rybchenko 
4715e111ed8SAndrew Rybchenko 	if (enop->eno_set_drv_limits != NULL) {
4725e111ed8SAndrew Rybchenko 		if ((rc = enop->eno_set_drv_limits(enp, edlp)) != 0)
4735e111ed8SAndrew Rybchenko 			goto fail1;
4745e111ed8SAndrew Rybchenko 	}
4755e111ed8SAndrew Rybchenko 
4765e111ed8SAndrew Rybchenko 	return (0);
4775e111ed8SAndrew Rybchenko 
4785e111ed8SAndrew Rybchenko fail1:
4795e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
4805e111ed8SAndrew Rybchenko 
4815e111ed8SAndrew Rybchenko 	return (rc);
4825e111ed8SAndrew Rybchenko }
4835e111ed8SAndrew Rybchenko 
4845e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_nic_set_drv_version(__inout efx_nic_t * enp,__in_ecount (length)char const * verp,__in size_t length)4855e111ed8SAndrew Rybchenko efx_nic_set_drv_version(
4865e111ed8SAndrew Rybchenko 	__inout			efx_nic_t *enp,
4875e111ed8SAndrew Rybchenko 	__in_ecount(length)	char const *verp,
4885e111ed8SAndrew Rybchenko 	__in			size_t length)
4895e111ed8SAndrew Rybchenko {
4905e111ed8SAndrew Rybchenko 	efx_rc_t rc;
4915e111ed8SAndrew Rybchenko 
4925e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
4935e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_PROBE));
4945e111ed8SAndrew Rybchenko 
4955e111ed8SAndrew Rybchenko 	/*
4965e111ed8SAndrew Rybchenko 	 * length is the string content length in bytes.
4975e111ed8SAndrew Rybchenko 	 * Accept any content which fits into the version
4985e111ed8SAndrew Rybchenko 	 * buffer, excluding the last byte. This is reserved
4995e111ed8SAndrew Rybchenko 	 * for an appended NUL terminator.
5005e111ed8SAndrew Rybchenko 	 */
5015e111ed8SAndrew Rybchenko 	if (length >= sizeof (enp->en_drv_version)) {
5025e111ed8SAndrew Rybchenko 		rc = E2BIG;
5035e111ed8SAndrew Rybchenko 		goto fail1;
5045e111ed8SAndrew Rybchenko 	}
5055e111ed8SAndrew Rybchenko 
5065e111ed8SAndrew Rybchenko 	(void) memset(enp->en_drv_version, 0,
5075e111ed8SAndrew Rybchenko 	    sizeof (enp->en_drv_version));
5085e111ed8SAndrew Rybchenko 	memcpy(enp->en_drv_version, verp, length);
5095e111ed8SAndrew Rybchenko 
5105e111ed8SAndrew Rybchenko 	return (0);
5115e111ed8SAndrew Rybchenko 
5125e111ed8SAndrew Rybchenko fail1:
5135e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
5145e111ed8SAndrew Rybchenko 
5155e111ed8SAndrew Rybchenko 	return (rc);
5165e111ed8SAndrew Rybchenko }
5175e111ed8SAndrew Rybchenko 
5185e111ed8SAndrew Rybchenko 
5195e111ed8SAndrew Rybchenko 	__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)5205e111ed8SAndrew Rybchenko efx_nic_get_bar_region(
5215e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
5225e111ed8SAndrew Rybchenko 	__in		efx_nic_region_t region,
5235e111ed8SAndrew Rybchenko 	__out		uint32_t *offsetp,
5245e111ed8SAndrew Rybchenko 	__out		size_t *sizep)
5255e111ed8SAndrew Rybchenko {
5265e111ed8SAndrew Rybchenko 	const efx_nic_ops_t *enop = enp->en_enop;
5275e111ed8SAndrew Rybchenko 	efx_rc_t rc;
5285e111ed8SAndrew Rybchenko 
5295e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
5305e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
5315e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
5325e111ed8SAndrew Rybchenko 
5335e111ed8SAndrew Rybchenko 	if (enop->eno_get_bar_region == NULL) {
5345e111ed8SAndrew Rybchenko 		rc = ENOTSUP;
5355e111ed8SAndrew Rybchenko 		goto fail1;
5365e111ed8SAndrew Rybchenko 	}
5375e111ed8SAndrew Rybchenko 	if ((rc = (enop->eno_get_bar_region)(enp,
5385e111ed8SAndrew Rybchenko 		    region, offsetp, sizep)) != 0) {
5395e111ed8SAndrew Rybchenko 		goto fail2;
5405e111ed8SAndrew Rybchenko 	}
5415e111ed8SAndrew Rybchenko 
5425e111ed8SAndrew Rybchenko 	return (0);
5435e111ed8SAndrew Rybchenko 
5445e111ed8SAndrew Rybchenko fail2:
5455e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
5465e111ed8SAndrew Rybchenko 
5475e111ed8SAndrew Rybchenko fail1:
5485e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
5495e111ed8SAndrew Rybchenko 
5505e111ed8SAndrew Rybchenko 	return (rc);
5515e111ed8SAndrew Rybchenko }
5525e111ed8SAndrew Rybchenko 
5535e111ed8SAndrew Rybchenko 
5545e111ed8SAndrew Rybchenko 	__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)5555e111ed8SAndrew Rybchenko efx_nic_get_vi_pool(
5565e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
5575e111ed8SAndrew Rybchenko 	__out		uint32_t *evq_countp,
5585e111ed8SAndrew Rybchenko 	__out		uint32_t *rxq_countp,
5595e111ed8SAndrew Rybchenko 	__out		uint32_t *txq_countp)
5605e111ed8SAndrew Rybchenko {
5615e111ed8SAndrew Rybchenko 	const efx_nic_ops_t *enop = enp->en_enop;
5625e111ed8SAndrew Rybchenko 	efx_nic_cfg_t *encp = &enp->en_nic_cfg;
5635e111ed8SAndrew Rybchenko 	efx_rc_t rc;
5645e111ed8SAndrew Rybchenko 
5655e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
5665e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
5675e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
5685e111ed8SAndrew Rybchenko 
5695e111ed8SAndrew Rybchenko 	if (enop->eno_get_vi_pool != NULL) {
5705e111ed8SAndrew Rybchenko 		uint32_t vi_count = 0;
5715e111ed8SAndrew Rybchenko 
5725e111ed8SAndrew Rybchenko 		if ((rc = (enop->eno_get_vi_pool)(enp, &vi_count)) != 0)
5735e111ed8SAndrew Rybchenko 			goto fail1;
5745e111ed8SAndrew Rybchenko 
5755e111ed8SAndrew Rybchenko 		*evq_countp = vi_count;
5765e111ed8SAndrew Rybchenko 		*rxq_countp = vi_count;
5775e111ed8SAndrew Rybchenko 		*txq_countp = vi_count;
5785e111ed8SAndrew Rybchenko 	} else {
5795e111ed8SAndrew Rybchenko 		/* Use NIC limits as default value */
5805e111ed8SAndrew Rybchenko 		*evq_countp = encp->enc_evq_limit;
5815e111ed8SAndrew Rybchenko 		*rxq_countp = encp->enc_rxq_limit;
5825e111ed8SAndrew Rybchenko 		*txq_countp = encp->enc_txq_limit;
5835e111ed8SAndrew Rybchenko 	}
5845e111ed8SAndrew Rybchenko 
5855e111ed8SAndrew Rybchenko 	return (0);
5865e111ed8SAndrew Rybchenko 
5875e111ed8SAndrew Rybchenko fail1:
5885e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
5895e111ed8SAndrew Rybchenko 
5905e111ed8SAndrew Rybchenko 	return (rc);
5915e111ed8SAndrew Rybchenko }
5925e111ed8SAndrew Rybchenko 
5935e111ed8SAndrew Rybchenko 
5945e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_nic_init(__in efx_nic_t * enp)5955e111ed8SAndrew Rybchenko efx_nic_init(
5965e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
5975e111ed8SAndrew Rybchenko {
5985e111ed8SAndrew Rybchenko 	const efx_nic_ops_t *enop = enp->en_enop;
5995e111ed8SAndrew Rybchenko 	efx_rc_t rc;
6005e111ed8SAndrew Rybchenko 
6015e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
6025e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
6035e111ed8SAndrew Rybchenko 
6045e111ed8SAndrew Rybchenko 	if (enp->en_mod_flags & EFX_MOD_NIC) {
6055e111ed8SAndrew Rybchenko 		rc = EINVAL;
6065e111ed8SAndrew Rybchenko 		goto fail1;
6075e111ed8SAndrew Rybchenko 	}
6085e111ed8SAndrew Rybchenko 
6095e111ed8SAndrew Rybchenko 	if ((rc = enop->eno_init(enp)) != 0)
6105e111ed8SAndrew Rybchenko 		goto fail2;
6115e111ed8SAndrew Rybchenko 
6125e111ed8SAndrew Rybchenko 	enp->en_mod_flags |= EFX_MOD_NIC;
6135e111ed8SAndrew Rybchenko 
6145e111ed8SAndrew Rybchenko 	return (0);
6155e111ed8SAndrew Rybchenko 
6165e111ed8SAndrew Rybchenko fail2:
6175e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
6185e111ed8SAndrew Rybchenko fail1:
6195e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
6205e111ed8SAndrew Rybchenko 
6215e111ed8SAndrew Rybchenko 	return (rc);
6225e111ed8SAndrew Rybchenko }
6235e111ed8SAndrew Rybchenko 
6245e111ed8SAndrew Rybchenko 			void
efx_nic_fini(__in efx_nic_t * enp)6255e111ed8SAndrew Rybchenko efx_nic_fini(
6265e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
6275e111ed8SAndrew Rybchenko {
6285e111ed8SAndrew Rybchenko 	const efx_nic_ops_t *enop = enp->en_enop;
6295e111ed8SAndrew Rybchenko 
6305e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
6315e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
6325e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_NIC);
6335e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
6345e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
6355e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
6365e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
6375e111ed8SAndrew Rybchenko 
6385e111ed8SAndrew Rybchenko 	enop->eno_fini(enp);
6395e111ed8SAndrew Rybchenko 
6405e111ed8SAndrew Rybchenko 	enp->en_mod_flags &= ~EFX_MOD_NIC;
6415e111ed8SAndrew Rybchenko }
6425e111ed8SAndrew Rybchenko 
6435e111ed8SAndrew Rybchenko 			void
efx_nic_unprobe(__in efx_nic_t * enp)6445e111ed8SAndrew Rybchenko efx_nic_unprobe(
6455e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
6465e111ed8SAndrew Rybchenko {
6475e111ed8SAndrew Rybchenko 	const efx_nic_ops_t *enop = enp->en_enop;
6485e111ed8SAndrew Rybchenko 
6495e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
6505e111ed8SAndrew Rybchenko #if EFSYS_OPT_MCDI
6515e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
6525e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_MCDI */
6535e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
6545e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
6555e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
6565e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
6575e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
6585e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
6595e111ed8SAndrew Rybchenko 
6605e111ed8SAndrew Rybchenko 	efx_phy_unprobe(enp);
6615e111ed8SAndrew Rybchenko 
6625e111ed8SAndrew Rybchenko 	enop->eno_unprobe(enp);
6635e111ed8SAndrew Rybchenko 
6645e111ed8SAndrew Rybchenko 	enp->en_mod_flags &= ~EFX_MOD_PROBE;
6655e111ed8SAndrew Rybchenko }
6665e111ed8SAndrew Rybchenko 
6675e111ed8SAndrew Rybchenko 			void
efx_nic_destroy(__in efx_nic_t * enp)6685e111ed8SAndrew Rybchenko efx_nic_destroy(
6695e111ed8SAndrew Rybchenko 	__in	efx_nic_t *enp)
6705e111ed8SAndrew Rybchenko {
6715e111ed8SAndrew Rybchenko 	efsys_identifier_t *esip = enp->en_esip;
6725e111ed8SAndrew Rybchenko 
6735e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
6745e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, ==, 0);
6755e111ed8SAndrew Rybchenko 
6765e111ed8SAndrew Rybchenko 	enp->en_family = EFX_FAMILY_INVALID;
6775e111ed8SAndrew Rybchenko 	enp->en_esip = NULL;
6785e111ed8SAndrew Rybchenko 	enp->en_esbp = NULL;
6795e111ed8SAndrew Rybchenko 	enp->en_eslp = NULL;
6805e111ed8SAndrew Rybchenko 
6815e111ed8SAndrew Rybchenko 	enp->en_enop = NULL;
6825e111ed8SAndrew Rybchenko 
6835e111ed8SAndrew Rybchenko 	enp->en_magic = 0;
6845e111ed8SAndrew Rybchenko 
6855e111ed8SAndrew Rybchenko 	/* Free the NIC object */
6865e111ed8SAndrew Rybchenko 	EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
6875e111ed8SAndrew Rybchenko }
6885e111ed8SAndrew Rybchenko 
6895e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_nic_reset(__in efx_nic_t * enp)6905e111ed8SAndrew Rybchenko efx_nic_reset(
6915e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
6925e111ed8SAndrew Rybchenko {
6935e111ed8SAndrew Rybchenko 	const efx_nic_ops_t *enop = enp->en_enop;
6945e111ed8SAndrew Rybchenko 	unsigned int mod_flags;
6955e111ed8SAndrew Rybchenko 	efx_rc_t rc;
6965e111ed8SAndrew Rybchenko 
6975e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
6985e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
6995e111ed8SAndrew Rybchenko 	/*
7005e111ed8SAndrew Rybchenko 	 * All modules except the MCDI, PROBE, NVRAM, VPD, MON, TUNNEL
7015e111ed8SAndrew Rybchenko 	 * (which we do not reset here) must have been shut down or never
7025e111ed8SAndrew Rybchenko 	 * initialized.
7035e111ed8SAndrew Rybchenko 	 *
7045e111ed8SAndrew Rybchenko 	 * A rule of thumb here is: If the controller or MC reboots, is *any*
7055e111ed8SAndrew Rybchenko 	 * state lost. If it's lost and needs reapplying, then the module
7065e111ed8SAndrew Rybchenko 	 * *must* not be initialised during the reset.
7075e111ed8SAndrew Rybchenko 	 */
7085e111ed8SAndrew Rybchenko 	mod_flags = enp->en_mod_flags;
7095e111ed8SAndrew Rybchenko 	mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM |
7105e111ed8SAndrew Rybchenko 	    EFX_MOD_VPD | EFX_MOD_MON);
7115e111ed8SAndrew Rybchenko #if EFSYS_OPT_TUNNEL
7125e111ed8SAndrew Rybchenko 	mod_flags &= ~EFX_MOD_TUNNEL;
7135e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_TUNNEL */
7145e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(mod_flags, ==, 0);
7155e111ed8SAndrew Rybchenko 	if (mod_flags != 0) {
7165e111ed8SAndrew Rybchenko 		rc = EINVAL;
7175e111ed8SAndrew Rybchenko 		goto fail1;
7185e111ed8SAndrew Rybchenko 	}
7195e111ed8SAndrew Rybchenko 
7205e111ed8SAndrew Rybchenko 	if ((rc = enop->eno_reset(enp)) != 0)
7215e111ed8SAndrew Rybchenko 		goto fail2;
7225e111ed8SAndrew Rybchenko 
7235e111ed8SAndrew Rybchenko 	return (0);
7245e111ed8SAndrew Rybchenko 
7255e111ed8SAndrew Rybchenko fail2:
7265e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
7275e111ed8SAndrew Rybchenko fail1:
7285e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
7295e111ed8SAndrew Rybchenko 
7305e111ed8SAndrew Rybchenko 	return (rc);
7315e111ed8SAndrew Rybchenko }
7325e111ed8SAndrew Rybchenko 
7335e111ed8SAndrew Rybchenko 			const efx_nic_cfg_t *
efx_nic_cfg_get(__in const efx_nic_t * enp)7345e111ed8SAndrew Rybchenko efx_nic_cfg_get(
7355e111ed8SAndrew Rybchenko 	__in		const efx_nic_t *enp)
7365e111ed8SAndrew Rybchenko {
7375e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
7385e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
7395e111ed8SAndrew Rybchenko 
7405e111ed8SAndrew Rybchenko 	return (&(enp->en_nic_cfg));
7415e111ed8SAndrew Rybchenko }
7425e111ed8SAndrew Rybchenko 
7435e111ed8SAndrew Rybchenko 	__checkReturn		efx_rc_t
efx_nic_get_fw_version(__in efx_nic_t * enp,__out efx_nic_fw_info_t * enfip)7445e111ed8SAndrew Rybchenko efx_nic_get_fw_version(
7455e111ed8SAndrew Rybchenko 	__in			efx_nic_t *enp,
7465e111ed8SAndrew Rybchenko 	__out			efx_nic_fw_info_t *enfip)
7475e111ed8SAndrew Rybchenko {
7485e111ed8SAndrew Rybchenko 	uint16_t mc_fw_version[4];
7495e111ed8SAndrew Rybchenko 	efx_rc_t rc;
7505e111ed8SAndrew Rybchenko 
7515e111ed8SAndrew Rybchenko 	if (enfip == NULL) {
7525e111ed8SAndrew Rybchenko 		rc = EINVAL;
7535e111ed8SAndrew Rybchenko 		goto fail1;
7545e111ed8SAndrew Rybchenko 	}
7555e111ed8SAndrew Rybchenko 
7565e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
7575e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
7585e111ed8SAndrew Rybchenko 
7595e111ed8SAndrew Rybchenko 	/* Ensure RXDP_FW_ID codes match with MC_CMD_GET_CAPABILITIES codes */
7605e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RXDP_FULL_FEATURED_FW_ID ==
7615e111ed8SAndrew Rybchenko 	    MC_CMD_GET_CAPABILITIES_OUT_RXDP);
7625e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RXDP_LOW_LATENCY_FW_ID ==
7635e111ed8SAndrew Rybchenko 	    MC_CMD_GET_CAPABILITIES_OUT_RXDP_LOW_LATENCY);
7645e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RXDP_PACKED_STREAM_FW_ID ==
7655e111ed8SAndrew Rybchenko 	    MC_CMD_GET_CAPABILITIES_OUT_RXDP_PACKED_STREAM);
7665e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RXDP_RULES_ENGINE_FW_ID ==
7675e111ed8SAndrew Rybchenko 	    MC_CMD_GET_CAPABILITIES_OUT_RXDP_RULES_ENGINE);
7685e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RXDP_DPDK_FW_ID ==
7695e111ed8SAndrew Rybchenko 	    MC_CMD_GET_CAPABILITIES_OUT_RXDP_DPDK);
7705e111ed8SAndrew Rybchenko 
7715e111ed8SAndrew Rybchenko 	rc = efx_mcdi_version(enp, mc_fw_version, NULL, NULL);
7725e111ed8SAndrew Rybchenko 	if (rc != 0)
7735e111ed8SAndrew Rybchenko 		goto fail2;
7745e111ed8SAndrew Rybchenko 
7755e111ed8SAndrew Rybchenko 	rc = efx_mcdi_get_capabilities(enp, NULL,
7765e111ed8SAndrew Rybchenko 	    &enfip->enfi_rx_dpcpu_fw_id,
7775e111ed8SAndrew Rybchenko 	    &enfip->enfi_tx_dpcpu_fw_id,
7785e111ed8SAndrew Rybchenko 	    NULL, NULL);
7795e111ed8SAndrew Rybchenko 	if (rc == 0) {
7805e111ed8SAndrew Rybchenko 		enfip->enfi_dpcpu_fw_ids_valid = B_TRUE;
7815e111ed8SAndrew Rybchenko 	} else if (rc == ENOTSUP) {
7825e111ed8SAndrew Rybchenko 		enfip->enfi_dpcpu_fw_ids_valid = B_FALSE;
7835e111ed8SAndrew Rybchenko 		enfip->enfi_rx_dpcpu_fw_id = 0;
7845e111ed8SAndrew Rybchenko 		enfip->enfi_tx_dpcpu_fw_id = 0;
7855e111ed8SAndrew Rybchenko 	} else {
7865e111ed8SAndrew Rybchenko 		goto fail3;
7875e111ed8SAndrew Rybchenko 	}
7885e111ed8SAndrew Rybchenko 
7895e111ed8SAndrew Rybchenko 	memcpy(enfip->enfi_mc_fw_version, mc_fw_version,
7905e111ed8SAndrew Rybchenko 	    sizeof (mc_fw_version));
7915e111ed8SAndrew Rybchenko 
7925e111ed8SAndrew Rybchenko 	return (0);
7935e111ed8SAndrew Rybchenko 
7945e111ed8SAndrew Rybchenko fail3:
7955e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
7965e111ed8SAndrew Rybchenko fail2:
7975e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
7985e111ed8SAndrew Rybchenko fail1:
7995e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
8005e111ed8SAndrew Rybchenko 
8015e111ed8SAndrew Rybchenko 	return (rc);
8025e111ed8SAndrew Rybchenko }
8035e111ed8SAndrew Rybchenko 
804833cfcd5SIvan Malov 	__checkReturn	efx_rc_t
efx_nic_get_board_info(__in efx_nic_t * enp,__out efx_nic_board_info_t * board_infop)805833cfcd5SIvan Malov efx_nic_get_board_info(
806833cfcd5SIvan Malov 	__in		efx_nic_t *enp,
807833cfcd5SIvan Malov 	__out		efx_nic_board_info_t *board_infop)
808833cfcd5SIvan Malov {
809833cfcd5SIvan Malov 	efx_mcdi_version_t ver;
810833cfcd5SIvan Malov 	efx_rc_t rc;
811833cfcd5SIvan Malov 
812833cfcd5SIvan Malov 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
813833cfcd5SIvan Malov 	EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
814833cfcd5SIvan Malov 
815833cfcd5SIvan Malov 	rc = efx_mcdi_get_version(enp, EFX_MCDI_VERSION_BOARD_INFO, &ver);
816833cfcd5SIvan Malov 	if (rc == EMSGSIZE) {
817833cfcd5SIvan Malov 		/*
818833cfcd5SIvan Malov 		 * Typically, EMSGSIZE is returned by above call in the
819833cfcd5SIvan Malov 		 * case when the NIC does not provide extra information.
820833cfcd5SIvan Malov 		 */
821833cfcd5SIvan Malov 		rc = ENOTSUP;
822833cfcd5SIvan Malov 		goto fail1;
823833cfcd5SIvan Malov 	} else if (rc != 0) {
824833cfcd5SIvan Malov 		goto fail2;
825833cfcd5SIvan Malov 	}
826833cfcd5SIvan Malov 
827833cfcd5SIvan Malov 	if ((ver.emv_flags & EFX_MCDI_VERSION_BOARD_INFO) == 0) {
828833cfcd5SIvan Malov 		rc = ENOTSUP;
829833cfcd5SIvan Malov 		goto fail3;
830833cfcd5SIvan Malov 	}
831833cfcd5SIvan Malov 
832833cfcd5SIvan Malov 	memcpy(board_infop, &ver.emv_board_info, sizeof (*board_infop));
833833cfcd5SIvan Malov 
834833cfcd5SIvan Malov 	/* MCDI should provide NUL-terminated strings, but stay vigilant. */
835833cfcd5SIvan Malov 	board_infop->enbi_serial[sizeof (board_infop->enbi_serial) - 1] = '\0';
836833cfcd5SIvan Malov 	board_infop->enbi_name[sizeof (board_infop->enbi_name) - 1] = '\0';
837833cfcd5SIvan Malov 
838833cfcd5SIvan Malov 	return (0);
839833cfcd5SIvan Malov 
840833cfcd5SIvan Malov fail3:
841833cfcd5SIvan Malov 	EFSYS_PROBE(fail3);
842833cfcd5SIvan Malov fail2:
843833cfcd5SIvan Malov 	EFSYS_PROBE(fail2);
844833cfcd5SIvan Malov fail1:
845833cfcd5SIvan Malov 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
846833cfcd5SIvan Malov 
847833cfcd5SIvan Malov 	return (rc);
848833cfcd5SIvan Malov }
849833cfcd5SIvan Malov 
8505e111ed8SAndrew Rybchenko 	__checkReturn	boolean_t
efx_nic_hw_unavailable(__in efx_nic_t * enp)8515e111ed8SAndrew Rybchenko efx_nic_hw_unavailable(
8525e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
8535e111ed8SAndrew Rybchenko {
8545e111ed8SAndrew Rybchenko 	const efx_nic_ops_t *enop = enp->en_enop;
8555e111ed8SAndrew Rybchenko 
8565e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
8575e111ed8SAndrew Rybchenko 	/* NOTE: can be used by MCDI before NIC probe */
8585e111ed8SAndrew Rybchenko 
8595e111ed8SAndrew Rybchenko 	if (enop->eno_hw_unavailable != NULL) {
8605e111ed8SAndrew Rybchenko 		if ((enop->eno_hw_unavailable)(enp) != B_FALSE)
8615e111ed8SAndrew Rybchenko 			goto unavail;
8625e111ed8SAndrew Rybchenko 	}
8635e111ed8SAndrew Rybchenko 
8645e111ed8SAndrew Rybchenko 	return (B_FALSE);
8655e111ed8SAndrew Rybchenko 
8665e111ed8SAndrew Rybchenko unavail:
8675e111ed8SAndrew Rybchenko 	return (B_TRUE);
8685e111ed8SAndrew Rybchenko }
8695e111ed8SAndrew Rybchenko 
8705e111ed8SAndrew Rybchenko 			void
efx_nic_set_hw_unavailable(__in efx_nic_t * enp)8715e111ed8SAndrew Rybchenko efx_nic_set_hw_unavailable(
8725e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
8735e111ed8SAndrew Rybchenko {
8745e111ed8SAndrew Rybchenko 	const efx_nic_ops_t *enop = enp->en_enop;
8755e111ed8SAndrew Rybchenko 
8765e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
8775e111ed8SAndrew Rybchenko 
8785e111ed8SAndrew Rybchenko 	if (enop->eno_set_hw_unavailable != NULL)
8795e111ed8SAndrew Rybchenko 		enop->eno_set_hw_unavailable(enp);
8805e111ed8SAndrew Rybchenko }
8815e111ed8SAndrew Rybchenko 
8825e111ed8SAndrew Rybchenko 
8835e111ed8SAndrew Rybchenko #if EFSYS_OPT_DIAG
8845e111ed8SAndrew Rybchenko 
8855e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_nic_register_test(__in efx_nic_t * enp)8865e111ed8SAndrew Rybchenko efx_nic_register_test(
8875e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
8885e111ed8SAndrew Rybchenko {
8895e111ed8SAndrew Rybchenko 	const efx_nic_ops_t *enop = enp->en_enop;
8905e111ed8SAndrew Rybchenko 	efx_rc_t rc;
8915e111ed8SAndrew Rybchenko 
8925e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
8935e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
8945e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
8955e111ed8SAndrew Rybchenko 
8965e111ed8SAndrew Rybchenko 	if ((rc = enop->eno_register_test(enp)) != 0)
8975e111ed8SAndrew Rybchenko 		goto fail1;
8985e111ed8SAndrew Rybchenko 
8995e111ed8SAndrew Rybchenko 	return (0);
9005e111ed8SAndrew Rybchenko 
9015e111ed8SAndrew Rybchenko fail1:
9025e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
9035e111ed8SAndrew Rybchenko 
9045e111ed8SAndrew Rybchenko 	return (rc);
9055e111ed8SAndrew Rybchenko }
9065e111ed8SAndrew Rybchenko 
9075e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_DIAG */
9085e111ed8SAndrew Rybchenko 
9095e111ed8SAndrew Rybchenko #if EFSYS_OPT_LOOPBACK
9105e111ed8SAndrew Rybchenko 
9115e111ed8SAndrew Rybchenko extern			void
efx_loopback_mask(__in efx_loopback_kind_t loopback_kind,__out efx_qword_t * maskp)9125e111ed8SAndrew Rybchenko efx_loopback_mask(
9135e111ed8SAndrew Rybchenko 	__in	efx_loopback_kind_t loopback_kind,
9145e111ed8SAndrew Rybchenko 	__out	efx_qword_t *maskp)
9155e111ed8SAndrew Rybchenko {
9165e111ed8SAndrew Rybchenko 	efx_qword_t mask;
9175e111ed8SAndrew Rybchenko 
9185e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(loopback_kind, <, EFX_LOOPBACK_NKINDS);
9195e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(maskp != NULL);
9205e111ed8SAndrew Rybchenko 
9215e111ed8SAndrew Rybchenko 	/* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree */
9225e111ed8SAndrew Rybchenko #define	LOOPBACK_CHECK(_mcdi, _efx) \
9235e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_##_mcdi == EFX_LOOPBACK_##_efx)
9245e111ed8SAndrew Rybchenko 
9255e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(NONE, OFF);
9265e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(DATA, DATA);
9275e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(GMAC, GMAC);
9285e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(XGMII, XGMII);
9295e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(XGXS, XGXS);
9305e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(XAUI, XAUI);
9315e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(GMII, GMII);
9325e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(SGMII, SGMII);
9335e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(XGBR, XGBR);
9345e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(XFI, XFI);
9355e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(XAUI_FAR, XAUI_FAR);
9365e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(GMII_FAR, GMII_FAR);
9375e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(SGMII_FAR, SGMII_FAR);
9385e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(XFI_FAR, XFI_FAR);
9395e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(GPHY, GPHY);
9405e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(PHYXS, PHY_XS);
9415e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(PCS, PCS);
9425e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(PMAPMD, PMA_PMD);
9435e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(XPORT, XPORT);
9445e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(XGMII_WS, XGMII_WS);
9455e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(XAUI_WS, XAUI_WS);
9465e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(XAUI_WS_FAR, XAUI_WS_FAR);
9475e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(XAUI_WS_NEAR, XAUI_WS_NEAR);
9485e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(GMII_WS, GMII_WS);
9495e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(XFI_WS, XFI_WS);
9505e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(XFI_WS_FAR, XFI_WS_FAR);
9515e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(PHYXS_WS, PHYXS_WS);
9525e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(PMA_INT, PMA_INT);
9535e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(SD_NEAR, SD_NEAR);
9545e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(SD_FAR, SD_FAR);
9555e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(PMA_INT_WS, PMA_INT_WS);
9565e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(SD_FEP2_WS, SD_FEP2_WS);
9575e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(SD_FEP1_5_WS, SD_FEP1_5_WS);
9585e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(SD_FEP_WS, SD_FEP_WS);
9595e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(SD_FES_WS, SD_FES_WS);
9605e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(AOE_INT_NEAR, AOE_INT_NEAR);
9615e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(DATA_WS, DATA_WS);
9625e111ed8SAndrew Rybchenko 	LOOPBACK_CHECK(FORCE_EXT_LINK, FORCE_EXT_LINK);
9635e111ed8SAndrew Rybchenko #undef LOOPBACK_CHECK
9645e111ed8SAndrew Rybchenko 
9655e111ed8SAndrew Rybchenko 	/* Build bitmask of possible loopback types */
9665e111ed8SAndrew Rybchenko 	EFX_ZERO_QWORD(mask);
9675e111ed8SAndrew Rybchenko 
9685e111ed8SAndrew Rybchenko 	if ((loopback_kind == EFX_LOOPBACK_KIND_OFF) ||
9695e111ed8SAndrew Rybchenko 	    (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
9705e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_OFF);
9715e111ed8SAndrew Rybchenko 	}
9725e111ed8SAndrew Rybchenko 
9735e111ed8SAndrew Rybchenko 	if ((loopback_kind == EFX_LOOPBACK_KIND_MAC) ||
9745e111ed8SAndrew Rybchenko 	    (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
9755e111ed8SAndrew Rybchenko 		/*
9765e111ed8SAndrew Rybchenko 		 * The "MAC" grouping has historically been used by drivers to
9775e111ed8SAndrew Rybchenko 		 * mean loopbacks supported by on-chip hardware. Keep that
9785e111ed8SAndrew Rybchenko 		 * meaning here, and include on-chip PHY layer loopbacks.
9795e111ed8SAndrew Rybchenko 		 */
9805e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_DATA);
9815e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMAC);
9825e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGMII);
9835e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGXS);
9845e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI);
9855e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII);
9865e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII);
9875e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGBR);
9885e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI);
9895e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI_FAR);
9905e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII_FAR);
9915e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII_FAR);
9925e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI_FAR);
9935e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_INT);
9945e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_NEAR);
9955e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_FAR);
9965e111ed8SAndrew Rybchenko 	}
9975e111ed8SAndrew Rybchenko 
9985e111ed8SAndrew Rybchenko 	if ((loopback_kind == EFX_LOOPBACK_KIND_PHY) ||
9995e111ed8SAndrew Rybchenko 	    (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {
10005e111ed8SAndrew Rybchenko 		/*
10015e111ed8SAndrew Rybchenko 		 * The "PHY" grouping has historically been used by drivers to
10025e111ed8SAndrew Rybchenko 		 * mean loopbacks supported by off-chip hardware. Keep that
10035e111ed8SAndrew Rybchenko 		 * meaning here.
10045e111ed8SAndrew Rybchenko 		 */
10055e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GPHY);
10065e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask,	EFX_LOOPBACK_PHY_XS);
10075e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PCS);
10085e111ed8SAndrew Rybchenko 		EFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_PMD);
10095e111ed8SAndrew Rybchenko 	}
10105e111ed8SAndrew Rybchenko 
10115e111ed8SAndrew Rybchenko 	*maskp = mask;
10125e111ed8SAndrew Rybchenko }
10135e111ed8SAndrew Rybchenko 
10145e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_mcdi_get_loopback_modes(__in efx_nic_t * enp)10155e111ed8SAndrew Rybchenko efx_mcdi_get_loopback_modes(
10165e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
10175e111ed8SAndrew Rybchenko {
10185e111ed8SAndrew Rybchenko 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
10195e111ed8SAndrew Rybchenko 	efx_mcdi_req_t req;
10205e111ed8SAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LOOPBACK_MODES_IN_LEN,
10215e111ed8SAndrew Rybchenko 		MC_CMD_GET_LOOPBACK_MODES_OUT_V2_LEN);
10225e111ed8SAndrew Rybchenko 	efx_qword_t mask;
10235e111ed8SAndrew Rybchenko 	efx_qword_t modes;
10245e111ed8SAndrew Rybchenko 	efx_rc_t rc;
10255e111ed8SAndrew Rybchenko 
10265e111ed8SAndrew Rybchenko 	req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES;
10275e111ed8SAndrew Rybchenko 	req.emr_in_buf = payload;
10285e111ed8SAndrew Rybchenko 	req.emr_in_length = MC_CMD_GET_LOOPBACK_MODES_IN_LEN;
10295e111ed8SAndrew Rybchenko 	req.emr_out_buf = payload;
10305e111ed8SAndrew Rybchenko 	req.emr_out_length = MC_CMD_GET_LOOPBACK_MODES_OUT_V2_LEN;
10315e111ed8SAndrew Rybchenko 
10325e111ed8SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
10335e111ed8SAndrew Rybchenko 
10345e111ed8SAndrew Rybchenko 	if (req.emr_rc != 0) {
10355e111ed8SAndrew Rybchenko 		rc = req.emr_rc;
10365e111ed8SAndrew Rybchenko 		goto fail1;
10375e111ed8SAndrew Rybchenko 	}
10385e111ed8SAndrew Rybchenko 
10395e111ed8SAndrew Rybchenko 	if (req.emr_out_length_used <
10405e111ed8SAndrew Rybchenko 	    MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST +
10415e111ed8SAndrew Rybchenko 	    MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN) {
10425e111ed8SAndrew Rybchenko 		rc = EMSGSIZE;
10435e111ed8SAndrew Rybchenko 		goto fail2;
10445e111ed8SAndrew Rybchenko 	}
10455e111ed8SAndrew Rybchenko 
10465e111ed8SAndrew Rybchenko 	/*
10475e111ed8SAndrew Rybchenko 	 * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree
10485e111ed8SAndrew Rybchenko 	 * in efx_loopback_mask() and in siena_phy.c:siena_phy_get_link().
10495e111ed8SAndrew Rybchenko 	 */
10505e111ed8SAndrew Rybchenko 	efx_loopback_mask(EFX_LOOPBACK_KIND_ALL, &mask);
10515e111ed8SAndrew Rybchenko 
10525e111ed8SAndrew Rybchenko 	EFX_AND_QWORD(mask,
10535e111ed8SAndrew Rybchenko 	    *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_SUGGESTED));
10545e111ed8SAndrew Rybchenko 
10555e111ed8SAndrew Rybchenko 	modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_100M);
10565e111ed8SAndrew Rybchenko 	EFX_AND_QWORD(modes, mask);
10575e111ed8SAndrew Rybchenko 	encp->enc_loopback_types[EFX_LINK_100FDX] = modes;
10585e111ed8SAndrew Rybchenko 
10595e111ed8SAndrew Rybchenko 	modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_1G);
10605e111ed8SAndrew Rybchenko 	EFX_AND_QWORD(modes, mask);
10615e111ed8SAndrew Rybchenko 	encp->enc_loopback_types[EFX_LINK_1000FDX] = modes;
10625e111ed8SAndrew Rybchenko 
10635e111ed8SAndrew Rybchenko 	modes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_10G);
10645e111ed8SAndrew Rybchenko 	EFX_AND_QWORD(modes, mask);
10655e111ed8SAndrew Rybchenko 	encp->enc_loopback_types[EFX_LINK_10000FDX] = modes;
10665e111ed8SAndrew Rybchenko 
10675e111ed8SAndrew Rybchenko 	if (req.emr_out_length_used >=
10685e111ed8SAndrew Rybchenko 	    MC_CMD_GET_LOOPBACK_MODES_OUT_40G_OFST +
10695e111ed8SAndrew Rybchenko 	    MC_CMD_GET_LOOPBACK_MODES_OUT_40G_LEN) {
10705e111ed8SAndrew Rybchenko 		/* Response includes 40G loopback modes */
10715e111ed8SAndrew Rybchenko 		modes = *MCDI_OUT2(req, efx_qword_t,
10725e111ed8SAndrew Rybchenko 		    GET_LOOPBACK_MODES_OUT_40G);
10735e111ed8SAndrew Rybchenko 		EFX_AND_QWORD(modes, mask);
10745e111ed8SAndrew Rybchenko 		encp->enc_loopback_types[EFX_LINK_40000FDX] = modes;
10755e111ed8SAndrew Rybchenko 	}
10765e111ed8SAndrew Rybchenko 
10775e111ed8SAndrew Rybchenko 	if (req.emr_out_length_used >=
10785e111ed8SAndrew Rybchenko 	    MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_OFST +
10795e111ed8SAndrew Rybchenko 	    MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_LEN) {
10805e111ed8SAndrew Rybchenko 		/* Response includes 25G loopback modes */
10815e111ed8SAndrew Rybchenko 		modes = *MCDI_OUT2(req, efx_qword_t,
10825e111ed8SAndrew Rybchenko 		    GET_LOOPBACK_MODES_OUT_V2_25G);
10835e111ed8SAndrew Rybchenko 		EFX_AND_QWORD(modes, mask);
10845e111ed8SAndrew Rybchenko 		encp->enc_loopback_types[EFX_LINK_25000FDX] = modes;
10855e111ed8SAndrew Rybchenko 	}
10865e111ed8SAndrew Rybchenko 
10875e111ed8SAndrew Rybchenko 	if (req.emr_out_length_used >=
10885e111ed8SAndrew Rybchenko 	    MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_OFST +
10895e111ed8SAndrew Rybchenko 	    MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_LEN) {
10905e111ed8SAndrew Rybchenko 		/* Response includes 50G loopback modes */
10915e111ed8SAndrew Rybchenko 		modes = *MCDI_OUT2(req, efx_qword_t,
10925e111ed8SAndrew Rybchenko 		    GET_LOOPBACK_MODES_OUT_V2_50G);
10935e111ed8SAndrew Rybchenko 		EFX_AND_QWORD(modes, mask);
10945e111ed8SAndrew Rybchenko 		encp->enc_loopback_types[EFX_LINK_50000FDX] = modes;
10955e111ed8SAndrew Rybchenko 	}
10965e111ed8SAndrew Rybchenko 
10975e111ed8SAndrew Rybchenko 	if (req.emr_out_length_used >=
10985e111ed8SAndrew Rybchenko 	    MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_OFST +
10995e111ed8SAndrew Rybchenko 	    MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_LEN) {
11005e111ed8SAndrew Rybchenko 		/* Response includes 100G loopback modes */
11015e111ed8SAndrew Rybchenko 		modes = *MCDI_OUT2(req, efx_qword_t,
11025e111ed8SAndrew Rybchenko 		    GET_LOOPBACK_MODES_OUT_V2_100G);
11035e111ed8SAndrew Rybchenko 		EFX_AND_QWORD(modes, mask);
11045e111ed8SAndrew Rybchenko 		encp->enc_loopback_types[EFX_LINK_100000FDX] = modes;
11055e111ed8SAndrew Rybchenko 	}
11065e111ed8SAndrew Rybchenko 
11075e111ed8SAndrew Rybchenko 	EFX_ZERO_QWORD(modes);
11085e111ed8SAndrew Rybchenko 	EFX_SET_QWORD_BIT(modes, EFX_LOOPBACK_OFF);
11095e111ed8SAndrew Rybchenko 	EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_100FDX]);
11105e111ed8SAndrew Rybchenko 	EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_1000FDX]);
11115e111ed8SAndrew Rybchenko 	EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_10000FDX]);
11125e111ed8SAndrew Rybchenko 	EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_40000FDX]);
11135e111ed8SAndrew Rybchenko 	EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_25000FDX]);
11145e111ed8SAndrew Rybchenko 	EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_50000FDX]);
11155e111ed8SAndrew Rybchenko 	EFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_100000FDX]);
11165e111ed8SAndrew Rybchenko 	encp->enc_loopback_types[EFX_LINK_UNKNOWN] = modes;
11175e111ed8SAndrew Rybchenko 
11185e111ed8SAndrew Rybchenko 	return (0);
11195e111ed8SAndrew Rybchenko 
11205e111ed8SAndrew Rybchenko fail2:
11215e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
11225e111ed8SAndrew Rybchenko fail1:
11235e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
11245e111ed8SAndrew Rybchenko 
11255e111ed8SAndrew Rybchenko 	return (rc);
11265e111ed8SAndrew Rybchenko }
11275e111ed8SAndrew Rybchenko 
11285e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_LOOPBACK */
11295e111ed8SAndrew Rybchenko 
11305e111ed8SAndrew Rybchenko 	__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)11315e111ed8SAndrew Rybchenko efx_nic_calculate_pcie_link_bandwidth(
11325e111ed8SAndrew Rybchenko 	__in		uint32_t pcie_link_width,
11335e111ed8SAndrew Rybchenko 	__in		uint32_t pcie_link_gen,
11345e111ed8SAndrew Rybchenko 	__out		uint32_t *bandwidth_mbpsp)
11355e111ed8SAndrew Rybchenko {
11365e111ed8SAndrew Rybchenko 	uint32_t lane_bandwidth;
11375e111ed8SAndrew Rybchenko 	uint32_t total_bandwidth;
11385e111ed8SAndrew Rybchenko 	efx_rc_t rc;
11395e111ed8SAndrew Rybchenko 
11405e111ed8SAndrew Rybchenko 	if ((pcie_link_width == 0) || (pcie_link_width > 16) ||
11415e111ed8SAndrew Rybchenko 	    !ISP2(pcie_link_width)) {
11425e111ed8SAndrew Rybchenko 		rc = EINVAL;
11435e111ed8SAndrew Rybchenko 		goto fail1;
11445e111ed8SAndrew Rybchenko 	}
11455e111ed8SAndrew Rybchenko 
11465e111ed8SAndrew Rybchenko 	switch (pcie_link_gen) {
11475e111ed8SAndrew Rybchenko 	case EFX_PCIE_LINK_SPEED_GEN1:
11485e111ed8SAndrew Rybchenko 		/* 2.5 Gb/s raw bandwidth with 8b/10b encoding */
11495e111ed8SAndrew Rybchenko 		lane_bandwidth = 2000;
11505e111ed8SAndrew Rybchenko 		break;
11515e111ed8SAndrew Rybchenko 	case EFX_PCIE_LINK_SPEED_GEN2:
11525e111ed8SAndrew Rybchenko 		/* 5.0 Gb/s raw bandwidth with 8b/10b encoding */
11535e111ed8SAndrew Rybchenko 		lane_bandwidth = 4000;
11545e111ed8SAndrew Rybchenko 		break;
11555e111ed8SAndrew Rybchenko 	case EFX_PCIE_LINK_SPEED_GEN3:
11565e111ed8SAndrew Rybchenko 		/* 8.0 Gb/s raw bandwidth with 128b/130b encoding */
11575e111ed8SAndrew Rybchenko 		lane_bandwidth = 7877;
11585e111ed8SAndrew Rybchenko 		break;
11595e111ed8SAndrew Rybchenko 	default:
11605e111ed8SAndrew Rybchenko 		rc = EINVAL;
11615e111ed8SAndrew Rybchenko 		goto fail2;
11625e111ed8SAndrew Rybchenko 	}
11635e111ed8SAndrew Rybchenko 
11645e111ed8SAndrew Rybchenko 	total_bandwidth = lane_bandwidth * pcie_link_width;
11655e111ed8SAndrew Rybchenko 	*bandwidth_mbpsp = total_bandwidth;
11665e111ed8SAndrew Rybchenko 
11675e111ed8SAndrew Rybchenko 	return (0);
11685e111ed8SAndrew Rybchenko 
11695e111ed8SAndrew Rybchenko fail2:
11705e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
11715e111ed8SAndrew Rybchenko fail1:
11725e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
11735e111ed8SAndrew Rybchenko 
11745e111ed8SAndrew Rybchenko 	return (rc);
11755e111ed8SAndrew Rybchenko }
11765e111ed8SAndrew Rybchenko 
11775e111ed8SAndrew Rybchenko #if EFSYS_OPT_FW_SUBVARIANT_AWARE
11785e111ed8SAndrew Rybchenko 
11795e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_nic_get_fw_subvariant(__in efx_nic_t * enp,__out efx_nic_fw_subvariant_t * subvariantp)11805e111ed8SAndrew Rybchenko efx_nic_get_fw_subvariant(
11815e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
11825e111ed8SAndrew Rybchenko 	__out		efx_nic_fw_subvariant_t *subvariantp)
11835e111ed8SAndrew Rybchenko {
11845e111ed8SAndrew Rybchenko 	efx_rc_t rc;
11855e111ed8SAndrew Rybchenko 	uint32_t value;
11865e111ed8SAndrew Rybchenko 
11875e111ed8SAndrew Rybchenko 	rc = efx_mcdi_get_nic_global(enp,
11885e111ed8SAndrew Rybchenko 	    MC_CMD_SET_NIC_GLOBAL_IN_FIRMWARE_SUBVARIANT, &value);
11895e111ed8SAndrew Rybchenko 	if (rc != 0)
11905e111ed8SAndrew Rybchenko 		goto fail1;
11915e111ed8SAndrew Rybchenko 
11925e111ed8SAndrew Rybchenko 	/* Mapping is not required since values match MCDI */
11935e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_NIC_FW_SUBVARIANT_DEFAULT ==
11945e111ed8SAndrew Rybchenko 	    MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_DEFAULT);
11955e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_NIC_FW_SUBVARIANT_NO_TX_CSUM ==
11965e111ed8SAndrew Rybchenko 	    MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_NO_TX_CSUM);
11975e111ed8SAndrew Rybchenko 
11985e111ed8SAndrew Rybchenko 	switch (value) {
11995e111ed8SAndrew Rybchenko 	case MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_DEFAULT:
12005e111ed8SAndrew Rybchenko 	case MC_CMD_SET_NIC_GLOBAL_IN_FW_SUBVARIANT_NO_TX_CSUM:
12015e111ed8SAndrew Rybchenko 		*subvariantp = value;
12025e111ed8SAndrew Rybchenko 		break;
12035e111ed8SAndrew Rybchenko 	default:
12045e111ed8SAndrew Rybchenko 		rc = EINVAL;
12055e111ed8SAndrew Rybchenko 		goto fail2;
12065e111ed8SAndrew Rybchenko 	}
12075e111ed8SAndrew Rybchenko 
12085e111ed8SAndrew Rybchenko 	return (0);
12095e111ed8SAndrew Rybchenko 
12105e111ed8SAndrew Rybchenko fail2:
12115e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
12125e111ed8SAndrew Rybchenko 
12135e111ed8SAndrew Rybchenko fail1:
12145e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
12155e111ed8SAndrew Rybchenko 
12165e111ed8SAndrew Rybchenko 	return (rc);
12175e111ed8SAndrew Rybchenko }
12185e111ed8SAndrew Rybchenko 
12195e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_nic_set_fw_subvariant(__in efx_nic_t * enp,__in efx_nic_fw_subvariant_t subvariant)12205e111ed8SAndrew Rybchenko efx_nic_set_fw_subvariant(
12215e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
12225e111ed8SAndrew Rybchenko 	__in		efx_nic_fw_subvariant_t subvariant)
12235e111ed8SAndrew Rybchenko {
12245e111ed8SAndrew Rybchenko 	efx_rc_t rc;
12255e111ed8SAndrew Rybchenko 
12265e111ed8SAndrew Rybchenko 	switch (subvariant) {
12275e111ed8SAndrew Rybchenko 	case EFX_NIC_FW_SUBVARIANT_DEFAULT:
12285e111ed8SAndrew Rybchenko 	case EFX_NIC_FW_SUBVARIANT_NO_TX_CSUM:
12295e111ed8SAndrew Rybchenko 		/* Mapping is not required since values match MCDI */
12305e111ed8SAndrew Rybchenko 		break;
12315e111ed8SAndrew Rybchenko 	default:
12325e111ed8SAndrew Rybchenko 		rc = EINVAL;
12335e111ed8SAndrew Rybchenko 		goto fail1;
12345e111ed8SAndrew Rybchenko 	}
12355e111ed8SAndrew Rybchenko 
12365e111ed8SAndrew Rybchenko 	rc = efx_mcdi_set_nic_global(enp,
12375e111ed8SAndrew Rybchenko 	    MC_CMD_SET_NIC_GLOBAL_IN_FIRMWARE_SUBVARIANT, subvariant);
12385e111ed8SAndrew Rybchenko 	if (rc != 0)
12395e111ed8SAndrew Rybchenko 		goto fail2;
12405e111ed8SAndrew Rybchenko 
12415e111ed8SAndrew Rybchenko 	return (0);
12425e111ed8SAndrew Rybchenko 
12435e111ed8SAndrew Rybchenko fail2:
12445e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
12455e111ed8SAndrew Rybchenko 
12465e111ed8SAndrew Rybchenko fail1:
12475e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
12485e111ed8SAndrew Rybchenko 
12495e111ed8SAndrew Rybchenko 	return (rc);
12505e111ed8SAndrew Rybchenko }
12515e111ed8SAndrew Rybchenko 
12525e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_FW_SUBVARIANT_AWARE */
12535e111ed8SAndrew Rybchenko 
12545e111ed8SAndrew Rybchenko 	__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)12555e111ed8SAndrew Rybchenko efx_nic_check_pcie_link_speed(
12565e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
12575e111ed8SAndrew Rybchenko 	__in		uint32_t pcie_link_width,
12585e111ed8SAndrew Rybchenko 	__in		uint32_t pcie_link_gen,
12595e111ed8SAndrew Rybchenko 	__out		efx_pcie_link_performance_t *resultp)
12605e111ed8SAndrew Rybchenko {
12615e111ed8SAndrew Rybchenko 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
12625e111ed8SAndrew Rybchenko 	uint32_t bandwidth;
12635e111ed8SAndrew Rybchenko 	efx_pcie_link_performance_t result;
12645e111ed8SAndrew Rybchenko 	efx_rc_t rc;
12655e111ed8SAndrew Rybchenko 
12665e111ed8SAndrew Rybchenko 	if ((encp->enc_required_pcie_bandwidth_mbps == 0) ||
12675e111ed8SAndrew Rybchenko 	    (pcie_link_width == 0) || (pcie_link_width == 32) ||
12685e111ed8SAndrew Rybchenko 	    (pcie_link_gen == 0)) {
12695e111ed8SAndrew Rybchenko 		/*
12705e111ed8SAndrew Rybchenko 		 * No usable info on what is required and/or in use. In virtual
12715e111ed8SAndrew Rybchenko 		 * machines, sometimes the PCIe link width is reported as 0 or
12725e111ed8SAndrew Rybchenko 		 * 32, or the speed as 0.
12735e111ed8SAndrew Rybchenko 		 */
12745e111ed8SAndrew Rybchenko 		result = EFX_PCIE_LINK_PERFORMANCE_UNKNOWN_BANDWIDTH;
12755e111ed8SAndrew Rybchenko 		goto out;
12765e111ed8SAndrew Rybchenko 	}
12775e111ed8SAndrew Rybchenko 
12785e111ed8SAndrew Rybchenko 	/* Calculate the available bandwidth in megabits per second */
12795e111ed8SAndrew Rybchenko 	rc = efx_nic_calculate_pcie_link_bandwidth(pcie_link_width,
12805e111ed8SAndrew Rybchenko 					    pcie_link_gen, &bandwidth);
12815e111ed8SAndrew Rybchenko 	if (rc != 0)
12825e111ed8SAndrew Rybchenko 		goto fail1;
12835e111ed8SAndrew Rybchenko 
12845e111ed8SAndrew Rybchenko 	if (bandwidth < encp->enc_required_pcie_bandwidth_mbps) {
12855e111ed8SAndrew Rybchenko 		result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_BANDWIDTH;
12865e111ed8SAndrew Rybchenko 	} else if (pcie_link_gen < encp->enc_max_pcie_link_gen) {
12875e111ed8SAndrew Rybchenko 		/* The link provides enough bandwidth but not optimal latency */
12885e111ed8SAndrew Rybchenko 		result = EFX_PCIE_LINK_PERFORMANCE_SUBOPTIMAL_LATENCY;
12895e111ed8SAndrew Rybchenko 	} else {
12905e111ed8SAndrew Rybchenko 		result = EFX_PCIE_LINK_PERFORMANCE_OPTIMAL;
12915e111ed8SAndrew Rybchenko 	}
12925e111ed8SAndrew Rybchenko 
12935e111ed8SAndrew Rybchenko out:
12945e111ed8SAndrew Rybchenko 	*resultp = result;
12955e111ed8SAndrew Rybchenko 
12965e111ed8SAndrew Rybchenko 	return (0);
12975e111ed8SAndrew Rybchenko 
12985e111ed8SAndrew Rybchenko fail1:
12995e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
13005e111ed8SAndrew Rybchenko 
13015e111ed8SAndrew Rybchenko 	return (rc);
13025e111ed8SAndrew Rybchenko }
1303*60fb370cSAndrew Rybchenko 
1304*60fb370cSAndrew Rybchenko /* Required en_eslp lock held */
1305*60fb370cSAndrew Rybchenko static __checkReturn	efx_rc_t
efx_nic_dma_config_regioned_find_region(__in const efx_nic_t * enp,__in efsys_dma_addr_t trgt_addr,__in size_t len,__out const efx_nic_dma_region_t ** regionp)1306*60fb370cSAndrew Rybchenko efx_nic_dma_config_regioned_find_region(
1307*60fb370cSAndrew Rybchenko 	__in		const efx_nic_t *enp,
1308*60fb370cSAndrew Rybchenko 	__in		efsys_dma_addr_t trgt_addr,
1309*60fb370cSAndrew Rybchenko 	__in		size_t len,
1310*60fb370cSAndrew Rybchenko 	__out		const efx_nic_dma_region_t **regionp)
1311*60fb370cSAndrew Rybchenko {
1312*60fb370cSAndrew Rybchenko 	const efx_nic_dma_region_info_t *region_info;
1313*60fb370cSAndrew Rybchenko 	const efx_nic_dma_region_t *region;
1314*60fb370cSAndrew Rybchenko 	unsigned int i;
1315*60fb370cSAndrew Rybchenko 	efx_rc_t rc;
1316*60fb370cSAndrew Rybchenko 
1317*60fb370cSAndrew Rybchenko 	if (efx_nic_cfg_get(enp)->enc_dma_mapping !=
1318*60fb370cSAndrew Rybchenko 	    EFX_NIC_DMA_MAPPING_REGIONED) {
1319*60fb370cSAndrew Rybchenko 		rc = EINVAL;
1320*60fb370cSAndrew Rybchenko 		goto fail1;
1321*60fb370cSAndrew Rybchenko 	}
1322*60fb370cSAndrew Rybchenko 
1323*60fb370cSAndrew Rybchenko 	region_info = &enp->en_dma.end_u.endu_region_info;
1324*60fb370cSAndrew Rybchenko 
1325*60fb370cSAndrew Rybchenko 	for (i = 0; i < region_info->endri_count; ++i) {
1326*60fb370cSAndrew Rybchenko 		efsys_dma_addr_t offset;
1327*60fb370cSAndrew Rybchenko 
1328*60fb370cSAndrew Rybchenko 		region = &region_info->endri_regions[i];
1329*60fb370cSAndrew Rybchenko 		if (region->endr_inuse == B_FALSE)
1330*60fb370cSAndrew Rybchenko 			continue;
1331*60fb370cSAndrew Rybchenko 
1332*60fb370cSAndrew Rybchenko 		if (trgt_addr < region->endr_trgt_base)
1333*60fb370cSAndrew Rybchenko 			continue;
1334*60fb370cSAndrew Rybchenko 
1335*60fb370cSAndrew Rybchenko 		EFSYS_ASSERT3U(region->endr_window_log2, <, 64);
1336*60fb370cSAndrew Rybchenko 		offset = trgt_addr - region->endr_trgt_base;
1337*60fb370cSAndrew Rybchenko 		if (offset + len > (1ULL << region->endr_window_log2))
1338*60fb370cSAndrew Rybchenko 			continue;
1339*60fb370cSAndrew Rybchenko 
1340*60fb370cSAndrew Rybchenko 		*regionp = region;
1341*60fb370cSAndrew Rybchenko 		return (0);
1342*60fb370cSAndrew Rybchenko 	}
1343*60fb370cSAndrew Rybchenko 
1344*60fb370cSAndrew Rybchenko 	rc = ENOENT;
1345*60fb370cSAndrew Rybchenko 	goto fail2;
1346*60fb370cSAndrew Rybchenko 
1347*60fb370cSAndrew Rybchenko fail2:
1348*60fb370cSAndrew Rybchenko 	EFSYS_PROBE(fail2);
1349*60fb370cSAndrew Rybchenko fail1:
1350*60fb370cSAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1351*60fb370cSAndrew Rybchenko 
1352*60fb370cSAndrew Rybchenko 	return (rc);
1353*60fb370cSAndrew Rybchenko }
1354*60fb370cSAndrew Rybchenko 
1355*60fb370cSAndrew Rybchenko static __checkReturn	efx_rc_t
efx_nic_dma_config_regioned_add_region(__in efx_nic_t * enp,__in efsys_dma_addr_t trgt_addr,__in size_t len,__out const efx_nic_dma_region_t ** regionp)1356*60fb370cSAndrew Rybchenko efx_nic_dma_config_regioned_add_region(
1357*60fb370cSAndrew Rybchenko 	__in		efx_nic_t *enp,
1358*60fb370cSAndrew Rybchenko 	__in		efsys_dma_addr_t trgt_addr,
1359*60fb370cSAndrew Rybchenko 	__in		size_t len,
1360*60fb370cSAndrew Rybchenko 	__out		const efx_nic_dma_region_t **regionp)
1361*60fb370cSAndrew Rybchenko {
1362*60fb370cSAndrew Rybchenko 	efx_nic_dma_region_info_t *region_info;
1363*60fb370cSAndrew Rybchenko 	efx_nic_dma_region_t *region;
1364*60fb370cSAndrew Rybchenko 	unsigned int i;
1365*60fb370cSAndrew Rybchenko 	efx_rc_t rc;
1366*60fb370cSAndrew Rybchenko 
1367*60fb370cSAndrew Rybchenko 	if (efx_nic_cfg_get(enp)->enc_dma_mapping !=
1368*60fb370cSAndrew Rybchenko 	    EFX_NIC_DMA_MAPPING_REGIONED) {
1369*60fb370cSAndrew Rybchenko 		rc = EINVAL;
1370*60fb370cSAndrew Rybchenko 		goto fail1;
1371*60fb370cSAndrew Rybchenko 	}
1372*60fb370cSAndrew Rybchenko 
1373*60fb370cSAndrew Rybchenko 	region_info = &enp->en_dma.end_u.endu_region_info;
1374*60fb370cSAndrew Rybchenko 
1375*60fb370cSAndrew Rybchenko 	for (i = 0; i < region_info->endri_count; ++i) {
1376*60fb370cSAndrew Rybchenko 		efsys_dma_addr_t trgt_base;
1377*60fb370cSAndrew Rybchenko 		efsys_dma_addr_t offset;
1378*60fb370cSAndrew Rybchenko 
1379*60fb370cSAndrew Rybchenko 		region = &region_info->endri_regions[i];
1380*60fb370cSAndrew Rybchenko 		if (region->endr_inuse == B_TRUE)
1381*60fb370cSAndrew Rybchenko 			continue;
1382*60fb370cSAndrew Rybchenko 
1383*60fb370cSAndrew Rybchenko 		/*
1384*60fb370cSAndrew Rybchenko 		 * Align target address base in accordance with
1385*60fb370cSAndrew Rybchenko 		 * the region requirements.
1386*60fb370cSAndrew Rybchenko 		 */
1387*60fb370cSAndrew Rybchenko 		EFSYS_ASSERT3U(region->endr_align_log2, <, 64);
1388*60fb370cSAndrew Rybchenko 		trgt_base = EFX_P2ALIGN(efsys_dma_addr_t, trgt_addr,
1389*60fb370cSAndrew Rybchenko 		    (1ULL << region->endr_align_log2));
1390*60fb370cSAndrew Rybchenko 
1391*60fb370cSAndrew Rybchenko 		offset = trgt_addr - trgt_base;
1392*60fb370cSAndrew Rybchenko 
1393*60fb370cSAndrew Rybchenko 		/* Check if region window is sufficient */
1394*60fb370cSAndrew Rybchenko 		EFSYS_ASSERT3U(region->endr_window_log2, <, 64);
1395*60fb370cSAndrew Rybchenko 		if (offset + len > (1ULL << region->endr_window_log2))
1396*60fb370cSAndrew Rybchenko 			continue;
1397*60fb370cSAndrew Rybchenko 
1398*60fb370cSAndrew Rybchenko 		region->endr_trgt_base = trgt_base;
1399*60fb370cSAndrew Rybchenko 		region->endr_inuse = B_TRUE;
1400*60fb370cSAndrew Rybchenko 
1401*60fb370cSAndrew Rybchenko 		*regionp = region;
1402*60fb370cSAndrew Rybchenko 		return (0);
1403*60fb370cSAndrew Rybchenko 	}
1404*60fb370cSAndrew Rybchenko 
1405*60fb370cSAndrew Rybchenko 	/* No suitable free region found */
1406*60fb370cSAndrew Rybchenko 	rc = ENOMEM;
1407*60fb370cSAndrew Rybchenko 	goto fail2;
1408*60fb370cSAndrew Rybchenko 
1409*60fb370cSAndrew Rybchenko fail2:
1410*60fb370cSAndrew Rybchenko 	EFSYS_PROBE(fail2);
1411*60fb370cSAndrew Rybchenko fail1:
1412*60fb370cSAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1413*60fb370cSAndrew Rybchenko 
1414*60fb370cSAndrew Rybchenko 	return (rc);
1415*60fb370cSAndrew Rybchenko }
1416*60fb370cSAndrew Rybchenko 
1417*60fb370cSAndrew Rybchenko static	__checkReturn	efx_rc_t
efx_nic_dma_config_regioned_add(__in efx_nic_t * enp,__in efsys_dma_addr_t trgt_addr,__in size_t len,__out_opt efsys_dma_addr_t * nic_basep,__out_opt efsys_dma_addr_t * trgt_basep,__out_opt size_t * map_lenp)1418*60fb370cSAndrew Rybchenko efx_nic_dma_config_regioned_add(
1419*60fb370cSAndrew Rybchenko 	__in		efx_nic_t *enp,
1420*60fb370cSAndrew Rybchenko 	__in		efsys_dma_addr_t trgt_addr,
1421*60fb370cSAndrew Rybchenko 	__in		size_t len,
1422*60fb370cSAndrew Rybchenko 	__out_opt	efsys_dma_addr_t *nic_basep,
1423*60fb370cSAndrew Rybchenko 	__out_opt	efsys_dma_addr_t *trgt_basep,
1424*60fb370cSAndrew Rybchenko 	__out_opt	size_t *map_lenp)
1425*60fb370cSAndrew Rybchenko {
1426*60fb370cSAndrew Rybchenko 	const efx_nic_dma_region_t *region;
1427*60fb370cSAndrew Rybchenko 	efsys_lock_state_t state;
1428*60fb370cSAndrew Rybchenko 	efx_rc_t rc;
1429*60fb370cSAndrew Rybchenko 
1430*60fb370cSAndrew Rybchenko 	EFSYS_LOCK(enp->en_eslp, state);
1431*60fb370cSAndrew Rybchenko 
1432*60fb370cSAndrew Rybchenko 	rc = efx_nic_dma_config_regioned_find_region(enp, trgt_addr, len,
1433*60fb370cSAndrew Rybchenko 	    &region);
1434*60fb370cSAndrew Rybchenko 	switch (rc) {
1435*60fb370cSAndrew Rybchenko 	case 0:
1436*60fb370cSAndrew Rybchenko 		/* Already covered by existing mapping */
1437*60fb370cSAndrew Rybchenko 		break;
1438*60fb370cSAndrew Rybchenko 	case ENOENT:
1439*60fb370cSAndrew Rybchenko 		/* No existing mapping found */
1440*60fb370cSAndrew Rybchenko 		rc = efx_nic_dma_config_regioned_add_region(enp,
1441*60fb370cSAndrew Rybchenko 		    trgt_addr, len, &region);
1442*60fb370cSAndrew Rybchenko 		if (rc != 0)
1443*60fb370cSAndrew Rybchenko 			goto fail1;
1444*60fb370cSAndrew Rybchenko 		break;
1445*60fb370cSAndrew Rybchenko 	default:
1446*60fb370cSAndrew Rybchenko 		goto fail2;
1447*60fb370cSAndrew Rybchenko 	}
1448*60fb370cSAndrew Rybchenko 
1449*60fb370cSAndrew Rybchenko 	if (nic_basep != NULL)
1450*60fb370cSAndrew Rybchenko 		*nic_basep = region->endr_nic_base;
1451*60fb370cSAndrew Rybchenko 	if (trgt_basep != NULL)
1452*60fb370cSAndrew Rybchenko 		*trgt_basep = region->endr_trgt_base;
1453*60fb370cSAndrew Rybchenko 	if (map_lenp != NULL)
1454*60fb370cSAndrew Rybchenko 		*map_lenp = 1ULL << region->endr_window_log2;
1455*60fb370cSAndrew Rybchenko 
1456*60fb370cSAndrew Rybchenko 	EFSYS_UNLOCK(enp->en_eslp, state);
1457*60fb370cSAndrew Rybchenko 
1458*60fb370cSAndrew Rybchenko 	return (0);
1459*60fb370cSAndrew Rybchenko 
1460*60fb370cSAndrew Rybchenko fail2:
1461*60fb370cSAndrew Rybchenko 	EFSYS_PROBE(fail2);
1462*60fb370cSAndrew Rybchenko fail1:
1463*60fb370cSAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1464*60fb370cSAndrew Rybchenko 
1465*60fb370cSAndrew Rybchenko 	EFSYS_UNLOCK(enp->en_eslp, state);
1466*60fb370cSAndrew Rybchenko 
1467*60fb370cSAndrew Rybchenko 	return (rc);
1468*60fb370cSAndrew Rybchenko }
1469*60fb370cSAndrew Rybchenko 
1470*60fb370cSAndrew Rybchenko 	 __checkReturn	efx_rc_t
efx_nic_dma_config_add(__in efx_nic_t * enp,__in efsys_dma_addr_t trgt_addr,__in size_t len,__out_opt efsys_dma_addr_t * nic_basep,__out_opt efsys_dma_addr_t * trgt_basep,__out_opt size_t * map_lenp)1471*60fb370cSAndrew Rybchenko efx_nic_dma_config_add(
1472*60fb370cSAndrew Rybchenko 	__in		efx_nic_t *enp,
1473*60fb370cSAndrew Rybchenko 	__in		efsys_dma_addr_t trgt_addr,
1474*60fb370cSAndrew Rybchenko 	__in		size_t len,
1475*60fb370cSAndrew Rybchenko 	__out_opt	efsys_dma_addr_t *nic_basep,
1476*60fb370cSAndrew Rybchenko 	__out_opt	efsys_dma_addr_t *trgt_basep,
1477*60fb370cSAndrew Rybchenko 	__out_opt	size_t *map_lenp)
1478*60fb370cSAndrew Rybchenko {
1479*60fb370cSAndrew Rybchenko 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
1480*60fb370cSAndrew Rybchenko 	efx_rc_t rc;
1481*60fb370cSAndrew Rybchenko 
1482*60fb370cSAndrew Rybchenko 	switch (encp->enc_dma_mapping) {
1483*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_MAPPING_FLAT:
1484*60fb370cSAndrew Rybchenko 		/* No mapping is required */
1485*60fb370cSAndrew Rybchenko 		if (nic_basep != NULL)
1486*60fb370cSAndrew Rybchenko 			*nic_basep = 0;
1487*60fb370cSAndrew Rybchenko 		if (trgt_basep != NULL)
1488*60fb370cSAndrew Rybchenko 			*trgt_basep = 0;
1489*60fb370cSAndrew Rybchenko 		if (map_lenp != NULL)
1490*60fb370cSAndrew Rybchenko 			*map_lenp = 0;
1491*60fb370cSAndrew Rybchenko 		break;
1492*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_MAPPING_REGIONED:
1493*60fb370cSAndrew Rybchenko 		rc = efx_nic_dma_config_regioned_add(enp, trgt_addr, len,
1494*60fb370cSAndrew Rybchenko 		    nic_basep, trgt_basep, map_lenp);
1495*60fb370cSAndrew Rybchenko 		if (rc != 0)
1496*60fb370cSAndrew Rybchenko 			goto fail1;
1497*60fb370cSAndrew Rybchenko 		break;
1498*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_MAPPING_UNKNOWN:
1499*60fb370cSAndrew Rybchenko 	default:
1500*60fb370cSAndrew Rybchenko 		rc = ENOTSUP;
1501*60fb370cSAndrew Rybchenko 		goto fail2;
1502*60fb370cSAndrew Rybchenko 	}
1503*60fb370cSAndrew Rybchenko 
1504*60fb370cSAndrew Rybchenko 	return (0);
1505*60fb370cSAndrew Rybchenko 
1506*60fb370cSAndrew Rybchenko fail2:
1507*60fb370cSAndrew Rybchenko 	EFSYS_PROBE(fail2);
1508*60fb370cSAndrew Rybchenko fail1:
1509*60fb370cSAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1510*60fb370cSAndrew Rybchenko 
1511*60fb370cSAndrew Rybchenko 	return (rc);
1512*60fb370cSAndrew Rybchenko }
1513*60fb370cSAndrew Rybchenko 
1514*60fb370cSAndrew Rybchenko static	 __checkReturn	efx_rc_t
efx_nic_dma_reconfigure_regioned(__in efx_nic_t * enp)1515*60fb370cSAndrew Rybchenko efx_nic_dma_reconfigure_regioned(
1516*60fb370cSAndrew Rybchenko 	__in		efx_nic_t *enp)
1517*60fb370cSAndrew Rybchenko {
1518*60fb370cSAndrew Rybchenko 	efx_rc_t rc;
1519*60fb370cSAndrew Rybchenko 
1520*60fb370cSAndrew Rybchenko 	rc = efx_mcdi_set_nic_addr_regions(enp,
1521*60fb370cSAndrew Rybchenko 	    &enp->en_dma.end_u.endu_region_info);
1522*60fb370cSAndrew Rybchenko 	if (rc != 0)
1523*60fb370cSAndrew Rybchenko 		goto fail1;
1524*60fb370cSAndrew Rybchenko 
1525*60fb370cSAndrew Rybchenko 	return (0);
1526*60fb370cSAndrew Rybchenko 
1527*60fb370cSAndrew Rybchenko fail1:
1528*60fb370cSAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1529*60fb370cSAndrew Rybchenko 
1530*60fb370cSAndrew Rybchenko 	return (rc);
1531*60fb370cSAndrew Rybchenko 
1532*60fb370cSAndrew Rybchenko }
1533*60fb370cSAndrew Rybchenko 
1534*60fb370cSAndrew Rybchenko 	 __checkReturn	efx_rc_t
efx_nic_dma_reconfigure(__in efx_nic_t * enp)1535*60fb370cSAndrew Rybchenko efx_nic_dma_reconfigure(
1536*60fb370cSAndrew Rybchenko 	__in		efx_nic_t *enp)
1537*60fb370cSAndrew Rybchenko {
1538*60fb370cSAndrew Rybchenko 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
1539*60fb370cSAndrew Rybchenko 	efx_rc_t rc;
1540*60fb370cSAndrew Rybchenko 
1541*60fb370cSAndrew Rybchenko 	switch (encp->enc_dma_mapping) {
1542*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_MAPPING_UNKNOWN:
1543*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_MAPPING_FLAT:
1544*60fb370cSAndrew Rybchenko 		/* Nothing to do */
1545*60fb370cSAndrew Rybchenko 		break;
1546*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_MAPPING_REGIONED:
1547*60fb370cSAndrew Rybchenko 		rc = efx_nic_dma_reconfigure_regioned(enp);
1548*60fb370cSAndrew Rybchenko 		if (rc != 0)
1549*60fb370cSAndrew Rybchenko 			goto fail1;
1550*60fb370cSAndrew Rybchenko 		break;
1551*60fb370cSAndrew Rybchenko 	default:
1552*60fb370cSAndrew Rybchenko 		rc = ENOTSUP;
1553*60fb370cSAndrew Rybchenko 		goto fail2;
1554*60fb370cSAndrew Rybchenko 	}
1555*60fb370cSAndrew Rybchenko 
1556*60fb370cSAndrew Rybchenko 	return (0);
1557*60fb370cSAndrew Rybchenko 
1558*60fb370cSAndrew Rybchenko fail2:
1559*60fb370cSAndrew Rybchenko 	EFSYS_PROBE(fail2);
1560*60fb370cSAndrew Rybchenko fail1:
1561*60fb370cSAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1562*60fb370cSAndrew Rybchenko 
1563*60fb370cSAndrew Rybchenko 	return (rc);
1564*60fb370cSAndrew Rybchenko }
1565*60fb370cSAndrew Rybchenko 
1566*60fb370cSAndrew Rybchenko static __checkReturn	efx_rc_t
efx_nic_dma_unknown_map(__in efx_nic_t * enp,__in efx_nic_dma_addr_type_t addr_type,__in efsys_dma_addr_t trgt_addr,__in size_t len,__out efsys_dma_addr_t * nic_addrp)1567*60fb370cSAndrew Rybchenko efx_nic_dma_unknown_map(
1568*60fb370cSAndrew Rybchenko 	__in		efx_nic_t *enp,
1569*60fb370cSAndrew Rybchenko 	__in		efx_nic_dma_addr_type_t addr_type,
1570*60fb370cSAndrew Rybchenko 	__in		efsys_dma_addr_t trgt_addr,
1571*60fb370cSAndrew Rybchenko 	__in		size_t len,
1572*60fb370cSAndrew Rybchenko 	__out		efsys_dma_addr_t *nic_addrp)
1573*60fb370cSAndrew Rybchenko {
1574*60fb370cSAndrew Rybchenko 	efx_rc_t rc;
1575*60fb370cSAndrew Rybchenko 
1576*60fb370cSAndrew Rybchenko 	/* This function may be called before the NIC has been probed. */
1577*60fb370cSAndrew Rybchenko 	if (enp->en_mod_flags & EFX_MOD_PROBE) {
1578*60fb370cSAndrew Rybchenko 		EFSYS_ASSERT3U(efx_nic_cfg_get(enp)->enc_dma_mapping, ==,
1579*60fb370cSAndrew Rybchenko 		    EFX_NIC_DMA_MAPPING_UNKNOWN);
1580*60fb370cSAndrew Rybchenko 	}
1581*60fb370cSAndrew Rybchenko 
1582*60fb370cSAndrew Rybchenko 	switch (addr_type) {
1583*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_ADDR_MCDI_BUF:
1584*60fb370cSAndrew Rybchenko 		/*
1585*60fb370cSAndrew Rybchenko 		 * MC cares about MCDI buffer mapping itself since it cannot
1586*60fb370cSAndrew Rybchenko 		 * be really mapped using MCDI because mapped MCDI
1587*60fb370cSAndrew Rybchenko 		 * buffer is required to execute MCDI commands.
1588*60fb370cSAndrew Rybchenko 		 */
1589*60fb370cSAndrew Rybchenko 		*nic_addrp = trgt_addr;
1590*60fb370cSAndrew Rybchenko 		break;
1591*60fb370cSAndrew Rybchenko 
1592*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_ADDR_MAC_STATS_BUF:
1593*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_ADDR_EVENT_RING:
1594*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_ADDR_RX_RING:
1595*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_ADDR_TX_RING:
1596*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_ADDR_RX_BUF:
1597*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_ADDR_TX_BUF:
1598*60fb370cSAndrew Rybchenko 		/* Mapping type must be discovered first */
1599*60fb370cSAndrew Rybchenko 		rc = EFAULT;
1600*60fb370cSAndrew Rybchenko 		goto fail1;
1601*60fb370cSAndrew Rybchenko 
1602*60fb370cSAndrew Rybchenko 	default:
1603*60fb370cSAndrew Rybchenko 		rc = EINVAL;
1604*60fb370cSAndrew Rybchenko 		goto fail2;
1605*60fb370cSAndrew Rybchenko 	}
1606*60fb370cSAndrew Rybchenko 
1607*60fb370cSAndrew Rybchenko 	return (0);
1608*60fb370cSAndrew Rybchenko 
1609*60fb370cSAndrew Rybchenko fail2:
1610*60fb370cSAndrew Rybchenko 	EFSYS_PROBE(fail2);
1611*60fb370cSAndrew Rybchenko fail1:
1612*60fb370cSAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1613*60fb370cSAndrew Rybchenko 
1614*60fb370cSAndrew Rybchenko 	return (rc);
1615*60fb370cSAndrew Rybchenko }
1616*60fb370cSAndrew Rybchenko 
1617*60fb370cSAndrew Rybchenko static __checkReturn	efx_rc_t
efx_nic_dma_flat_map(__in efx_nic_t * enp,__in efx_nic_dma_addr_type_t addr_type,__in efsys_dma_addr_t trgt_addr,__in size_t len,__out efsys_dma_addr_t * nic_addrp)1618*60fb370cSAndrew Rybchenko efx_nic_dma_flat_map(
1619*60fb370cSAndrew Rybchenko 	__in		efx_nic_t *enp,
1620*60fb370cSAndrew Rybchenko 	__in		efx_nic_dma_addr_type_t addr_type,
1621*60fb370cSAndrew Rybchenko 	__in		efsys_dma_addr_t trgt_addr,
1622*60fb370cSAndrew Rybchenko 	__in		size_t len,
1623*60fb370cSAndrew Rybchenko 	__out		efsys_dma_addr_t *nic_addrp)
1624*60fb370cSAndrew Rybchenko {
1625*60fb370cSAndrew Rybchenko 	_NOTE(ARGUNUSED(addr_type, len))
1626*60fb370cSAndrew Rybchenko 
1627*60fb370cSAndrew Rybchenko 	EFSYS_ASSERT3U(efx_nic_cfg_get(enp)->enc_dma_mapping, ==,
1628*60fb370cSAndrew Rybchenko 	    EFX_NIC_DMA_MAPPING_FLAT);
1629*60fb370cSAndrew Rybchenko 
1630*60fb370cSAndrew Rybchenko 	/* No re-mapping is required */
1631*60fb370cSAndrew Rybchenko 	*nic_addrp = trgt_addr;
1632*60fb370cSAndrew Rybchenko 
1633*60fb370cSAndrew Rybchenko 	return (0);
1634*60fb370cSAndrew Rybchenko }
1635*60fb370cSAndrew Rybchenko 
1636*60fb370cSAndrew Rybchenko static __checkReturn	efx_rc_t
efx_nic_dma_regioned_map(__in efx_nic_t * enp,__in efx_nic_dma_addr_type_t addr_type,__in efsys_dma_addr_t trgt_addr,__in size_t len,__out efsys_dma_addr_t * nic_addrp)1637*60fb370cSAndrew Rybchenko efx_nic_dma_regioned_map(
1638*60fb370cSAndrew Rybchenko 	__in		efx_nic_t *enp,
1639*60fb370cSAndrew Rybchenko 	__in		efx_nic_dma_addr_type_t addr_type,
1640*60fb370cSAndrew Rybchenko 	__in		efsys_dma_addr_t trgt_addr,
1641*60fb370cSAndrew Rybchenko 	__in		size_t len,
1642*60fb370cSAndrew Rybchenko 	__out		efsys_dma_addr_t *nic_addrp)
1643*60fb370cSAndrew Rybchenko {
1644*60fb370cSAndrew Rybchenko 	const efx_nic_dma_region_t *region;
1645*60fb370cSAndrew Rybchenko 	efsys_lock_state_t state;
1646*60fb370cSAndrew Rybchenko 	efx_rc_t rc;
1647*60fb370cSAndrew Rybchenko 
1648*60fb370cSAndrew Rybchenko 	if (efx_nic_cfg_get(enp)->enc_dma_mapping !=
1649*60fb370cSAndrew Rybchenko 	    EFX_NIC_DMA_MAPPING_REGIONED) {
1650*60fb370cSAndrew Rybchenko 		rc = EINVAL;
1651*60fb370cSAndrew Rybchenko 		goto fail1;
1652*60fb370cSAndrew Rybchenko 	}
1653*60fb370cSAndrew Rybchenko 
1654*60fb370cSAndrew Rybchenko 	switch (addr_type) {
1655*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_ADDR_MCDI_BUF:
1656*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_ADDR_MAC_STATS_BUF:
1657*60fb370cSAndrew Rybchenko 		/*
1658*60fb370cSAndrew Rybchenko 		 * MC cares about MCDI buffer mapping itself since it cannot
1659*60fb370cSAndrew Rybchenko 		 * be really mapped using MCDI because mapped MCDI buffer is
1660*60fb370cSAndrew Rybchenko 		 * required to execute MCDI commands. It is not a problem
1661*60fb370cSAndrew Rybchenko 		 * for MAC stats buffer, but since MC can care about mapping
1662*60fb370cSAndrew Rybchenko 		 * itself, it may be done for MAC stats buffer as well.
1663*60fb370cSAndrew Rybchenko 		 */
1664*60fb370cSAndrew Rybchenko 		*nic_addrp = trgt_addr;
1665*60fb370cSAndrew Rybchenko 		goto out;
1666*60fb370cSAndrew Rybchenko 
1667*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_ADDR_EVENT_RING:
1668*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_ADDR_RX_RING:
1669*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_ADDR_TX_RING:
1670*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_ADDR_RX_BUF:
1671*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_ADDR_TX_BUF:
1672*60fb370cSAndrew Rybchenko 		/* Rings and buffer addresses should be mapped */
1673*60fb370cSAndrew Rybchenko 		break;
1674*60fb370cSAndrew Rybchenko 
1675*60fb370cSAndrew Rybchenko 	default:
1676*60fb370cSAndrew Rybchenko 		rc = EINVAL;
1677*60fb370cSAndrew Rybchenko 		goto fail2;
1678*60fb370cSAndrew Rybchenko 	}
1679*60fb370cSAndrew Rybchenko 
1680*60fb370cSAndrew Rybchenko 	EFSYS_LOCK(enp->en_eslp, state);
1681*60fb370cSAndrew Rybchenko 
1682*60fb370cSAndrew Rybchenko 	rc = efx_nic_dma_config_regioned_find_region(enp, trgt_addr, len,
1683*60fb370cSAndrew Rybchenko 	    &region);
1684*60fb370cSAndrew Rybchenko 	if (rc != 0)
1685*60fb370cSAndrew Rybchenko 		goto fail3;
1686*60fb370cSAndrew Rybchenko 
1687*60fb370cSAndrew Rybchenko 	*nic_addrp = region->endr_nic_base +
1688*60fb370cSAndrew Rybchenko 		(trgt_addr - region->endr_trgt_base);
1689*60fb370cSAndrew Rybchenko 
1690*60fb370cSAndrew Rybchenko 	EFSYS_UNLOCK(enp->en_eslp, state);
1691*60fb370cSAndrew Rybchenko 
1692*60fb370cSAndrew Rybchenko out:
1693*60fb370cSAndrew Rybchenko 	return (0);
1694*60fb370cSAndrew Rybchenko 
1695*60fb370cSAndrew Rybchenko fail3:
1696*60fb370cSAndrew Rybchenko 	EFSYS_PROBE(fail3);
1697*60fb370cSAndrew Rybchenko 	EFSYS_UNLOCK(enp->en_eslp, state);
1698*60fb370cSAndrew Rybchenko fail2:
1699*60fb370cSAndrew Rybchenko 	EFSYS_PROBE(fail2);
1700*60fb370cSAndrew Rybchenko fail1:
1701*60fb370cSAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1702*60fb370cSAndrew Rybchenko 
1703*60fb370cSAndrew Rybchenko 	return (rc);
1704*60fb370cSAndrew Rybchenko }
1705*60fb370cSAndrew Rybchenko 
1706*60fb370cSAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_nic_dma_map(__in efx_nic_t * enp,__in efx_nic_dma_addr_type_t addr_type,__in efsys_dma_addr_t trgt_addr,__in size_t len,__out efsys_dma_addr_t * nic_addrp)1707*60fb370cSAndrew Rybchenko efx_nic_dma_map(
1708*60fb370cSAndrew Rybchenko 	__in		efx_nic_t *enp,
1709*60fb370cSAndrew Rybchenko 	__in		efx_nic_dma_addr_type_t addr_type,
1710*60fb370cSAndrew Rybchenko 	__in		efsys_dma_addr_t trgt_addr,
1711*60fb370cSAndrew Rybchenko 	__in		size_t len,
1712*60fb370cSAndrew Rybchenko 	__out		efsys_dma_addr_t *nic_addrp)
1713*60fb370cSAndrew Rybchenko {
1714*60fb370cSAndrew Rybchenko 	efx_nic_dma_mapping_t mapping;
1715*60fb370cSAndrew Rybchenko 	efx_rc_t rc;
1716*60fb370cSAndrew Rybchenko 
1717*60fb370cSAndrew Rybchenko 	/*
1718*60fb370cSAndrew Rybchenko 	 * We cannot check configuration of a NIC that hasn't been probed.
1719*60fb370cSAndrew Rybchenko 	 * Use EFX_NIC_DMA_MAPPING_UNKNOWN by default.
1720*60fb370cSAndrew Rybchenko 	 */
1721*60fb370cSAndrew Rybchenko 	if ((enp->en_mod_flags & EFX_MOD_PROBE) == 0)
1722*60fb370cSAndrew Rybchenko 		mapping = EFX_NIC_DMA_MAPPING_UNKNOWN;
1723*60fb370cSAndrew Rybchenko 	else
1724*60fb370cSAndrew Rybchenko 		mapping = efx_nic_cfg_get(enp)->enc_dma_mapping;
1725*60fb370cSAndrew Rybchenko 
1726*60fb370cSAndrew Rybchenko 	switch (mapping) {
1727*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_MAPPING_UNKNOWN:
1728*60fb370cSAndrew Rybchenko 		rc = efx_nic_dma_unknown_map(enp, addr_type, trgt_addr,
1729*60fb370cSAndrew Rybchenko 		    len, nic_addrp);
1730*60fb370cSAndrew Rybchenko 		if (rc != 0)
1731*60fb370cSAndrew Rybchenko 			goto fail1;
1732*60fb370cSAndrew Rybchenko 		break;
1733*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_MAPPING_FLAT:
1734*60fb370cSAndrew Rybchenko 		rc = efx_nic_dma_flat_map(enp, addr_type, trgt_addr,
1735*60fb370cSAndrew Rybchenko 		    len, nic_addrp);
1736*60fb370cSAndrew Rybchenko 		if (rc != 0)
1737*60fb370cSAndrew Rybchenko 			goto fail2;
1738*60fb370cSAndrew Rybchenko 		break;
1739*60fb370cSAndrew Rybchenko 	case EFX_NIC_DMA_MAPPING_REGIONED:
1740*60fb370cSAndrew Rybchenko 		rc = efx_nic_dma_regioned_map(enp, addr_type, trgt_addr,
1741*60fb370cSAndrew Rybchenko 		    len, nic_addrp);
1742*60fb370cSAndrew Rybchenko 		if (rc != 0)
1743*60fb370cSAndrew Rybchenko 			goto fail3;
1744*60fb370cSAndrew Rybchenko 		break;
1745*60fb370cSAndrew Rybchenko 	default:
1746*60fb370cSAndrew Rybchenko 		rc = ENOTSUP;
1747*60fb370cSAndrew Rybchenko 		goto fail4;
1748*60fb370cSAndrew Rybchenko 	}
1749*60fb370cSAndrew Rybchenko 
1750*60fb370cSAndrew Rybchenko 	return (0);
1751*60fb370cSAndrew Rybchenko 
1752*60fb370cSAndrew Rybchenko fail4:
1753*60fb370cSAndrew Rybchenko 	EFSYS_PROBE(fail4);
1754*60fb370cSAndrew Rybchenko fail3:
1755*60fb370cSAndrew Rybchenko 	EFSYS_PROBE(fail3);
1756*60fb370cSAndrew Rybchenko fail2:
1757*60fb370cSAndrew Rybchenko 	EFSYS_PROBE(fail2);
1758*60fb370cSAndrew Rybchenko fail1:
1759*60fb370cSAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1760*60fb370cSAndrew Rybchenko 
1761*60fb370cSAndrew Rybchenko 	return (rc);
1762*60fb370cSAndrew Rybchenko }
1763