xref: /dpdk/drivers/common/sfc_efx/base/efx_evb.c (revision 672386c1e9e1f64f7aa3b1360ad22dc737ea8d72)
15e111ed8SAndrew Rybchenko /* SPDX-License-Identifier: BSD-3-Clause
25e111ed8SAndrew Rybchenko  *
3*672386c1SAndrew Rybchenko  * Copyright(c) 2019-2021 Xilinx, Inc.
45e111ed8SAndrew Rybchenko  * Copyright(c) 2018-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 #if EFSYS_OPT_EVB
125e111ed8SAndrew Rybchenko 
135e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA
145e111ed8SAndrew Rybchenko static const efx_evb_ops_t	__efx_evb_dummy_ops = {
155e111ed8SAndrew Rybchenko 	NULL,		/* eeo_init */
165e111ed8SAndrew Rybchenko 	NULL,		/* eeo_fini */
175e111ed8SAndrew Rybchenko 	NULL,		/* eeo_vswitch_alloc */
185e111ed8SAndrew Rybchenko 	NULL,		/* eeo_vswitch_free */
195e111ed8SAndrew Rybchenko 	NULL,		/* eeo_vport_alloc */
205e111ed8SAndrew Rybchenko 	NULL,		/* eeo_vport_free */
215e111ed8SAndrew Rybchenko 	NULL,		/* eeo_vport_mac_addr_add */
225e111ed8SAndrew Rybchenko 	NULL,		/* eeo_vport_mac_addr_del */
235e111ed8SAndrew Rybchenko 	NULL,		/* eeo_vadaptor_alloc */
245e111ed8SAndrew Rybchenko 	NULL,		/* eeo_vadaptor_free */
255e111ed8SAndrew Rybchenko 	NULL,		/* eeo_vport_assign */
265e111ed8SAndrew Rybchenko 	NULL,		/* eeo_vport_reconfigure */
275e111ed8SAndrew Rybchenko 	NULL,		/* eeo_vport_stats */
285e111ed8SAndrew Rybchenko };
295e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
305e111ed8SAndrew Rybchenko 
315e111ed8SAndrew Rybchenko #if EFX_OPTS_EF10()
325e111ed8SAndrew Rybchenko static const efx_evb_ops_t	__efx_evb_ef10_ops = {
335e111ed8SAndrew Rybchenko 	ef10_evb_init,			/* eeo_init */
345e111ed8SAndrew Rybchenko 	ef10_evb_fini,			/* eeo_fini */
355e111ed8SAndrew Rybchenko 	ef10_evb_vswitch_alloc,		/* eeo_vswitch_alloc */
365e111ed8SAndrew Rybchenko 	ef10_evb_vswitch_free,		/* eeo_vswitch_free */
375e111ed8SAndrew Rybchenko 	ef10_evb_vport_alloc,		/* eeo_vport_alloc */
385e111ed8SAndrew Rybchenko 	ef10_evb_vport_free,		/* eeo_vport_free */
395e111ed8SAndrew Rybchenko 	ef10_evb_vport_mac_addr_add,	/* eeo_vport_mac_addr_add */
405e111ed8SAndrew Rybchenko 	ef10_evb_vport_mac_addr_del,	/* eeo_vport_mac_addr_del */
415e111ed8SAndrew Rybchenko 	ef10_evb_vadaptor_alloc,	/* eeo_vadaptor_alloc */
425e111ed8SAndrew Rybchenko 	ef10_evb_vadaptor_free,		/* eeo_vadaptor_free */
435e111ed8SAndrew Rybchenko 	ef10_evb_vport_assign,		/* eeo_vport_assign */
445e111ed8SAndrew Rybchenko 	ef10_evb_vport_reconfigure,	/* eeo_vport_reconfigure */
455e111ed8SAndrew Rybchenko 	ef10_evb_vport_stats,		/* eeo_vport_stats */
465e111ed8SAndrew Rybchenko };
475e111ed8SAndrew Rybchenko #endif /* EFX_OPTS_EF10() */
485e111ed8SAndrew Rybchenko 
4962d6aaa1SAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD
5062d6aaa1SAndrew Rybchenko static const efx_evb_ops_t	__efx_evb_rhead_ops = {
5162d6aaa1SAndrew Rybchenko 	ef10_evb_init,			/* eeo_init */
5262d6aaa1SAndrew Rybchenko 	ef10_evb_fini,			/* eeo_fini */
5362d6aaa1SAndrew Rybchenko 	ef10_evb_vswitch_alloc,		/* eeo_vswitch_alloc */
5462d6aaa1SAndrew Rybchenko 	ef10_evb_vswitch_free,		/* eeo_vswitch_free */
5562d6aaa1SAndrew Rybchenko 	ef10_evb_vport_alloc,		/* eeo_vport_alloc */
5662d6aaa1SAndrew Rybchenko 	ef10_evb_vport_free,		/* eeo_vport_free */
5762d6aaa1SAndrew Rybchenko 	ef10_evb_vport_mac_addr_add,	/* eeo_vport_mac_addr_add */
5862d6aaa1SAndrew Rybchenko 	ef10_evb_vport_mac_addr_del,	/* eeo_vport_mac_addr_del */
5962d6aaa1SAndrew Rybchenko 	ef10_evb_vadaptor_alloc,	/* eeo_vadaptor_alloc */
6062d6aaa1SAndrew Rybchenko 	ef10_evb_vadaptor_free,		/* eeo_vadaptor_free */
6162d6aaa1SAndrew Rybchenko 	ef10_evb_vport_assign,		/* eeo_vport_assign */
6262d6aaa1SAndrew Rybchenko 	ef10_evb_vport_reconfigure,	/* eeo_vport_reconfigure */
6362d6aaa1SAndrew Rybchenko 	ef10_evb_vport_stats,		/* eeo_vport_stats */
6462d6aaa1SAndrew Rybchenko };
6562d6aaa1SAndrew Rybchenko #endif /* EFSYS_OPT_RIVERHEAD */
6662d6aaa1SAndrew Rybchenko 
675e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_evb_init(__in efx_nic_t * enp)685e111ed8SAndrew Rybchenko efx_evb_init(
695e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
705e111ed8SAndrew Rybchenko {
715e111ed8SAndrew Rybchenko 	const efx_evb_ops_t *eeop;
725e111ed8SAndrew Rybchenko 	efx_rc_t rc;
735e111ed8SAndrew Rybchenko 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
745e111ed8SAndrew Rybchenko 
755e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
765e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
775e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EVB));
785e111ed8SAndrew Rybchenko 
795e111ed8SAndrew Rybchenko 	switch (enp->en_family) {
805e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA
815e111ed8SAndrew Rybchenko 	case EFX_FAMILY_SIENA:
825e111ed8SAndrew Rybchenko 		eeop = &__efx_evb_dummy_ops;
835e111ed8SAndrew Rybchenko 		break;
845e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
855e111ed8SAndrew Rybchenko 
865e111ed8SAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
875e111ed8SAndrew Rybchenko 	case EFX_FAMILY_HUNTINGTON:
885e111ed8SAndrew Rybchenko 		eeop = &__efx_evb_ef10_ops;
895e111ed8SAndrew Rybchenko 		break;
905e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */
915e111ed8SAndrew Rybchenko 
925e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD
935e111ed8SAndrew Rybchenko 	case EFX_FAMILY_MEDFORD:
945e111ed8SAndrew Rybchenko 		eeop = &__efx_evb_ef10_ops;
955e111ed8SAndrew Rybchenko 		break;
965e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */
975e111ed8SAndrew Rybchenko 
985e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
995e111ed8SAndrew Rybchenko 	case EFX_FAMILY_MEDFORD2:
1005e111ed8SAndrew Rybchenko 		eeop = &__efx_evb_ef10_ops;
1015e111ed8SAndrew Rybchenko 		break;
1025e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD2 */
1035e111ed8SAndrew Rybchenko 
10462d6aaa1SAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD
10562d6aaa1SAndrew Rybchenko 	case EFX_FAMILY_RIVERHEAD:
10662d6aaa1SAndrew Rybchenko 		eeop = &__efx_evb_rhead_ops;
10762d6aaa1SAndrew Rybchenko 		break;
10862d6aaa1SAndrew Rybchenko #endif /* EFSYS_OPT_RIVERHEAD */
10962d6aaa1SAndrew Rybchenko 
1105e111ed8SAndrew Rybchenko 	default:
1115e111ed8SAndrew Rybchenko 		EFSYS_ASSERT(0);
1125e111ed8SAndrew Rybchenko 		rc = ENOTSUP;
1135e111ed8SAndrew Rybchenko 		goto fail1;
1145e111ed8SAndrew Rybchenko 	}
1155e111ed8SAndrew Rybchenko 
1165e111ed8SAndrew Rybchenko 	if (!encp->enc_datapath_cap_evb || !eeop->eeo_init) {
1175e111ed8SAndrew Rybchenko 		rc = ENOTSUP;
1185e111ed8SAndrew Rybchenko 		goto fail2;
1195e111ed8SAndrew Rybchenko 	}
1205e111ed8SAndrew Rybchenko 
1215e111ed8SAndrew Rybchenko 	if ((rc = eeop->eeo_init(enp)) != 0)
1225e111ed8SAndrew Rybchenko 		goto fail3;
1235e111ed8SAndrew Rybchenko 
1245e111ed8SAndrew Rybchenko 	enp->en_eeop = eeop;
1255e111ed8SAndrew Rybchenko 	enp->en_mod_flags |= EFX_MOD_EVB;
1265e111ed8SAndrew Rybchenko 	return (0);
1275e111ed8SAndrew Rybchenko 
1285e111ed8SAndrew Rybchenko fail3:
1295e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
1305e111ed8SAndrew Rybchenko fail2:
1315e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
1325e111ed8SAndrew Rybchenko fail1:
1335e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1345e111ed8SAndrew Rybchenko 
1355e111ed8SAndrew Rybchenko 	return (rc);
1365e111ed8SAndrew Rybchenko }
1375e111ed8SAndrew Rybchenko 
1385e111ed8SAndrew Rybchenko 			void
efx_evb_fini(__in efx_nic_t * enp)1395e111ed8SAndrew Rybchenko efx_evb_fini(
1405e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
1415e111ed8SAndrew Rybchenko {
1425e111ed8SAndrew Rybchenko 	const efx_evb_ops_t *eeop = enp->en_eeop;
1435e111ed8SAndrew Rybchenko 
1445e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1455e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
1465e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
1475e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
1485e111ed8SAndrew Rybchenko 
1495e111ed8SAndrew Rybchenko 	if (eeop && eeop->eeo_fini)
1505e111ed8SAndrew Rybchenko 		eeop->eeo_fini(enp);
1515e111ed8SAndrew Rybchenko 
1525e111ed8SAndrew Rybchenko 	enp->en_eeop = NULL;
1535e111ed8SAndrew Rybchenko 	enp->en_mod_flags &= ~EFX_MOD_EVB;
1545e111ed8SAndrew Rybchenko }
1555e111ed8SAndrew Rybchenko 
1565e111ed8SAndrew Rybchenko /*
1575e111ed8SAndrew Rybchenko  * efx_is_zero_eth_addr returns TRUE if the passed MAC address has all bytes
1585e111ed8SAndrew Rybchenko  * equal to zero. A vport is assigned a MAC address after creation and this
1595e111ed8SAndrew Rybchenko  * function checks if that has happened. It is called in the clean-up function
1605e111ed8SAndrew Rybchenko  * before calling eeo_vport_mac_addr_del to ensure that the vport actually had
1615e111ed8SAndrew Rybchenko  * an allocated MAC address.
1625e111ed8SAndrew Rybchenko  */
1635e111ed8SAndrew Rybchenko 
1645e111ed8SAndrew Rybchenko __checkReturn				boolean_t
efx_is_zero_eth_addr(__in_bcount (EFX_MAC_ADDR_LEN)const uint8_t * addrp)1655e111ed8SAndrew Rybchenko efx_is_zero_eth_addr(
1665e111ed8SAndrew Rybchenko 	__in_bcount(EFX_MAC_ADDR_LEN)	const uint8_t *addrp)
1675e111ed8SAndrew Rybchenko {
1685e111ed8SAndrew Rybchenko 	return (!(addrp[0] | addrp[1] | addrp[2] |
1695e111ed8SAndrew Rybchenko 		addrp[3] | addrp[4] | addrp[5]));
1705e111ed8SAndrew Rybchenko }
1715e111ed8SAndrew Rybchenko 
1725e111ed8SAndrew Rybchenko static			void
efx_evb_free_vport(__in efx_nic_t * enp,__in efx_vswitch_id_t vswitch_id,__inout efx_vport_config_t * configp)1735e111ed8SAndrew Rybchenko efx_evb_free_vport(
1745e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
1755e111ed8SAndrew Rybchenko 	__in		efx_vswitch_id_t vswitch_id,
1765e111ed8SAndrew Rybchenko 	__inout		efx_vport_config_t *configp)
1775e111ed8SAndrew Rybchenko {
1785e111ed8SAndrew Rybchenko 	const efx_evb_ops_t *eeop = enp->en_eeop;
1795e111ed8SAndrew Rybchenko 
1805e111ed8SAndrew Rybchenko 	/* If any callback fails, continue clean-up with others functions */
1815e111ed8SAndrew Rybchenko 	if (EFX_VPORT_PCI_FUNCTION_IS_PF(configp)) {
1825e111ed8SAndrew Rybchenko 		/* free vadaptor */
1835e111ed8SAndrew Rybchenko 		if ((configp->evc_vport_id != EFX_VPORT_ID_INVALID) &&
1845e111ed8SAndrew Rybchenko 		    (eeop->eeo_vadaptor_free(enp, vswitch_id,
1855e111ed8SAndrew Rybchenko 		    configp->evc_vport_id) != 0)) {
1865e111ed8SAndrew Rybchenko 			EFSYS_PROBE2(eeo_vadaptor_free,
1875e111ed8SAndrew Rybchenko 			    uint16_t, configp->evc_function,
1885e111ed8SAndrew Rybchenko 			    uint32_t, configp->evc_vport_id);
1895e111ed8SAndrew Rybchenko 		}
1905e111ed8SAndrew Rybchenko 	} else {
1915e111ed8SAndrew Rybchenko 		if (configp->evc_vport_assigned == B_TRUE) {
1925e111ed8SAndrew Rybchenko 			if (eeop->eeo_vport_assign(enp, vswitch_id,
1935e111ed8SAndrew Rybchenko 			    EVB_PORT_ID_NULL,
1945e111ed8SAndrew Rybchenko 			    configp->evc_function) != 0) {
1955e111ed8SAndrew Rybchenko 				EFSYS_PROBE1(eeo_vport_assign,
1965e111ed8SAndrew Rybchenko 				    uint16_t, configp->evc_function);
1975e111ed8SAndrew Rybchenko 			}
1985e111ed8SAndrew Rybchenko 			configp->evc_vport_assigned = B_FALSE;
1995e111ed8SAndrew Rybchenko 		}
2005e111ed8SAndrew Rybchenko 	}
2015e111ed8SAndrew Rybchenko 
2025e111ed8SAndrew Rybchenko 	/*
2035e111ed8SAndrew Rybchenko 	 * Call eeo_vport_mac_addr_del after checking that this vport is
2045e111ed8SAndrew Rybchenko 	 * actually allocated a MAC address in call to efx_evb_configure_vport
2055e111ed8SAndrew Rybchenko 	 */
2065e111ed8SAndrew Rybchenko 	if (!efx_is_zero_eth_addr(configp->evc_mac_addr)) {
2075e111ed8SAndrew Rybchenko 		if (eeop->eeo_vport_mac_addr_del(enp, vswitch_id,
2085e111ed8SAndrew Rybchenko 		    configp->evc_vport_id,
2095e111ed8SAndrew Rybchenko 		    configp->evc_mac_addr) != 0) {
2105e111ed8SAndrew Rybchenko 			EFSYS_PROBE1(eeo_vport_mac_addr_del,
2115e111ed8SAndrew Rybchenko 			    uint16_t, configp->evc_function);
2125e111ed8SAndrew Rybchenko 		}
2135e111ed8SAndrew Rybchenko 		memset(configp->evc_mac_addr, 0x00, EFX_MAC_ADDR_LEN);
2145e111ed8SAndrew Rybchenko 	}
2155e111ed8SAndrew Rybchenko 
2165e111ed8SAndrew Rybchenko 	if (configp->evc_vport_id != EFX_VPORT_ID_INVALID) {
2175e111ed8SAndrew Rybchenko 		if (eeop->eeo_vport_free(enp, vswitch_id,
2185e111ed8SAndrew Rybchenko 		    configp->evc_vport_id) != 0) {
2195e111ed8SAndrew Rybchenko 			EFSYS_PROBE1(eeo_vport_free,
2205e111ed8SAndrew Rybchenko 			    uint16_t, configp->evc_function);
2215e111ed8SAndrew Rybchenko 		}
2225e111ed8SAndrew Rybchenko 		configp->evc_vport_id = EFX_VPORT_ID_INVALID;
2235e111ed8SAndrew Rybchenko 	}
2245e111ed8SAndrew Rybchenko }
2255e111ed8SAndrew Rybchenko 
2265e111ed8SAndrew Rybchenko static					void
efx_evb_free_vports(__in efx_nic_t * enp,__in efx_vswitch_id_t vswitch_id,__in uint32_t num_vports,__inout_ecount (num_vports)efx_vport_config_t * vport_configp)2275e111ed8SAndrew Rybchenko efx_evb_free_vports(
2285e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
2295e111ed8SAndrew Rybchenko 	__in				efx_vswitch_id_t vswitch_id,
2305e111ed8SAndrew Rybchenko 	__in				uint32_t num_vports,
2315e111ed8SAndrew Rybchenko 	__inout_ecount(num_vports)	efx_vport_config_t *vport_configp)
2325e111ed8SAndrew Rybchenko {
2335e111ed8SAndrew Rybchenko 	efx_vport_config_t *configp;
2345e111ed8SAndrew Rybchenko 	uint32_t i;
2355e111ed8SAndrew Rybchenko 
2365e111ed8SAndrew Rybchenko 	if (vport_configp == NULL) {
2375e111ed8SAndrew Rybchenko 		EFSYS_PROBE(null_vport_config);
2385e111ed8SAndrew Rybchenko 		return;
2395e111ed8SAndrew Rybchenko 	}
2405e111ed8SAndrew Rybchenko 
2415e111ed8SAndrew Rybchenko 	for (i = 0; i < num_vports; i++) {
2425e111ed8SAndrew Rybchenko 		configp = vport_configp + i;
2435e111ed8SAndrew Rybchenko 		efx_evb_free_vport(enp, vswitch_id, configp);
2445e111ed8SAndrew Rybchenko 	}
2455e111ed8SAndrew Rybchenko }
2465e111ed8SAndrew Rybchenko 
2475e111ed8SAndrew Rybchenko static	__checkReturn	efx_rc_t
efx_evb_configure_vport(__in efx_nic_t * enp,__in efx_vswitch_id_t vswitch_id,__in const efx_evb_ops_t * eeop,__inout efx_vport_config_t * configp)2485e111ed8SAndrew Rybchenko efx_evb_configure_vport(
2495e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
2505e111ed8SAndrew Rybchenko 	__in		efx_vswitch_id_t vswitch_id,
2515e111ed8SAndrew Rybchenko 	__in		const efx_evb_ops_t *eeop,
2525e111ed8SAndrew Rybchenko 	__inout		efx_vport_config_t *configp)
2535e111ed8SAndrew Rybchenko {
2545e111ed8SAndrew Rybchenko 	efx_rc_t rc;
2555e111ed8SAndrew Rybchenko 	efx_vport_id_t vport_id;
2565e111ed8SAndrew Rybchenko 
2575e111ed8SAndrew Rybchenko 	if ((rc = eeop->eeo_vport_alloc(enp, vswitch_id,
2585e111ed8SAndrew Rybchenko 			EFX_VPORT_TYPE_NORMAL, configp->evc_vid,
2595e111ed8SAndrew Rybchenko 			configp->evc_vlan_restrict, &vport_id)) != 0)
2605e111ed8SAndrew Rybchenko 		goto fail1;
2615e111ed8SAndrew Rybchenko 
2625e111ed8SAndrew Rybchenko 	configp->evc_vport_id = vport_id;
2635e111ed8SAndrew Rybchenko 
2645e111ed8SAndrew Rybchenko 	if ((rc = eeop->eeo_vport_mac_addr_add(enp, vswitch_id,
2655e111ed8SAndrew Rybchenko 			configp->evc_vport_id,
2665e111ed8SAndrew Rybchenko 			configp->evc_mac_addr)) != 0)
2675e111ed8SAndrew Rybchenko 		goto fail2;
2685e111ed8SAndrew Rybchenko 
2695e111ed8SAndrew Rybchenko 	if (EFX_VPORT_PCI_FUNCTION_IS_PF(configp)) {
2705e111ed8SAndrew Rybchenko 		if ((rc = eeop->eeo_vadaptor_alloc(enp, vswitch_id,
2715e111ed8SAndrew Rybchenko 				configp->evc_vport_id)) != 0)
2725e111ed8SAndrew Rybchenko 			goto fail3;
2735e111ed8SAndrew Rybchenko 	} else {
2745e111ed8SAndrew Rybchenko 		if ((rc = eeop->eeo_vport_assign(enp, vswitch_id,
2755e111ed8SAndrew Rybchenko 				configp->evc_vport_id,
2765e111ed8SAndrew Rybchenko 				configp->evc_function)) != 0)
2775e111ed8SAndrew Rybchenko 			goto fail4;
2785e111ed8SAndrew Rybchenko 		configp->evc_vport_assigned = B_TRUE;
2795e111ed8SAndrew Rybchenko 	}
2805e111ed8SAndrew Rybchenko 
2815e111ed8SAndrew Rybchenko 	return (0);
2825e111ed8SAndrew Rybchenko 
2835e111ed8SAndrew Rybchenko fail4:
2845e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail4);
2855e111ed8SAndrew Rybchenko fail3:
2865e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
2875e111ed8SAndrew Rybchenko fail2:
2885e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
2895e111ed8SAndrew Rybchenko fail1:
2905e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
2915e111ed8SAndrew Rybchenko 
2925e111ed8SAndrew Rybchenko 	return (rc);
2935e111ed8SAndrew Rybchenko }
2945e111ed8SAndrew Rybchenko 
2955e111ed8SAndrew Rybchenko 	__checkReturn			efx_rc_t
efx_evb_vswitch_create(__in efx_nic_t * enp,__in uint32_t num_vports,__inout_ecount (num_vports)efx_vport_config_t * vport_configp,__deref_out efx_vswitch_t ** evpp)2965e111ed8SAndrew Rybchenko efx_evb_vswitch_create(
2975e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
2985e111ed8SAndrew Rybchenko 	__in				uint32_t num_vports,
2995e111ed8SAndrew Rybchenko 	__inout_ecount(num_vports)	efx_vport_config_t *vport_configp,
3005e111ed8SAndrew Rybchenko 	__deref_out			efx_vswitch_t **evpp)
3015e111ed8SAndrew Rybchenko {
3025e111ed8SAndrew Rybchenko 	efx_vswitch_t *evp;
3035e111ed8SAndrew Rybchenko 	efx_rc_t rc;
3045e111ed8SAndrew Rybchenko 	efx_vswitch_id_t vswitch_id;
3055e111ed8SAndrew Rybchenko 	efx_vport_config_t *configp;
3065e111ed8SAndrew Rybchenko 	const efx_evb_ops_t *eeop = enp->en_eeop;
3075e111ed8SAndrew Rybchenko 	uint32_t i;
3085e111ed8SAndrew Rybchenko 
3095e111ed8SAndrew Rybchenko 	/* vport_configp is a caller allocated array filled in with vports
3105e111ed8SAndrew Rybchenko 	 * configuration. Index 0 carries the PF vport configuration and next
3115e111ed8SAndrew Rybchenko 	 * num_vports - 1 indices carry VFs configuration.
3125e111ed8SAndrew Rybchenko 	 */
3135e111ed8SAndrew Rybchenko 	EFSYS_ASSERT((num_vports != 0) && (vport_configp != NULL) &&
3145e111ed8SAndrew Rybchenko 		(evpp != NULL));
3155e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
3165e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
3175e111ed8SAndrew Rybchenko 
3185e111ed8SAndrew Rybchenko 	if ((eeop->eeo_vswitch_alloc == NULL) ||
3195e111ed8SAndrew Rybchenko 	    (eeop->eeo_vport_alloc == NULL) ||
3205e111ed8SAndrew Rybchenko 	    (eeop->eeo_vport_free == NULL) ||
3215e111ed8SAndrew Rybchenko 	    (eeop->eeo_vport_mac_addr_add == NULL) ||
3225e111ed8SAndrew Rybchenko 	    (eeop->eeo_vport_mac_addr_del == NULL) ||
3235e111ed8SAndrew Rybchenko 	    (eeop->eeo_vadaptor_alloc == NULL) ||
3245e111ed8SAndrew Rybchenko 	    (eeop->eeo_vadaptor_free == NULL) ||
3255e111ed8SAndrew Rybchenko 	    (eeop->eeo_vport_assign == NULL) ||
3265e111ed8SAndrew Rybchenko 	    (eeop->eeo_vswitch_free == NULL)) {
3275e111ed8SAndrew Rybchenko 		rc = ENOTSUP;
3285e111ed8SAndrew Rybchenko 		goto fail1;
3295e111ed8SAndrew Rybchenko 	}
3305e111ed8SAndrew Rybchenko 
3315e111ed8SAndrew Rybchenko 	/* Allocate a vSwitch object */
3325e111ed8SAndrew Rybchenko 	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_vswitch_t), evp);
3335e111ed8SAndrew Rybchenko 
3345e111ed8SAndrew Rybchenko 	if (evp == NULL) {
3355e111ed8SAndrew Rybchenko 		rc = ENOMEM;
3365e111ed8SAndrew Rybchenko 		goto fail2;
3375e111ed8SAndrew Rybchenko 	}
3385e111ed8SAndrew Rybchenko 
3395e111ed8SAndrew Rybchenko 	if ((rc = eeop->eeo_vswitch_alloc(enp, &vswitch_id)) != 0)
3405e111ed8SAndrew Rybchenko 		goto fail3;
3415e111ed8SAndrew Rybchenko 
3425e111ed8SAndrew Rybchenko 	evp->ev_enp = enp;
3435e111ed8SAndrew Rybchenko 	evp->ev_num_vports = num_vports;
3445e111ed8SAndrew Rybchenko 	evp->ev_evcp = vport_configp;
3455e111ed8SAndrew Rybchenko 	evp->ev_vswitch_id = vswitch_id;
3465e111ed8SAndrew Rybchenko 
3475e111ed8SAndrew Rybchenko 	for (i = 0; i < num_vports; i++) {
3485e111ed8SAndrew Rybchenko 		configp = vport_configp + i;
3495e111ed8SAndrew Rybchenko 
3505e111ed8SAndrew Rybchenko 		if ((rc = efx_evb_configure_vport(enp, vswitch_id, eeop,
3515e111ed8SAndrew Rybchenko 				configp)) != 0)
3525e111ed8SAndrew Rybchenko 			goto fail4;
3535e111ed8SAndrew Rybchenko 	}
3545e111ed8SAndrew Rybchenko 
3555e111ed8SAndrew Rybchenko 	enp->en_vswitchp = evp;
3565e111ed8SAndrew Rybchenko 	*evpp = evp;
3575e111ed8SAndrew Rybchenko 	return (0);
3585e111ed8SAndrew Rybchenko 
3595e111ed8SAndrew Rybchenko fail4:
3605e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail4);
3615e111ed8SAndrew Rybchenko 	efx_evb_free_vports(enp, vswitch_id, i + 1, vport_configp);
3625e111ed8SAndrew Rybchenko 	/* Free the vSwitch */
3635e111ed8SAndrew Rybchenko 	eeop->eeo_vswitch_free(enp, vswitch_id);
3645e111ed8SAndrew Rybchenko 
3655e111ed8SAndrew Rybchenko fail3:
3665e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
3675e111ed8SAndrew Rybchenko 	/* Free the vSwitch object */
3685e111ed8SAndrew Rybchenko 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp);
3695e111ed8SAndrew Rybchenko 
3705e111ed8SAndrew Rybchenko fail2:
3715e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
3725e111ed8SAndrew Rybchenko 
3735e111ed8SAndrew Rybchenko fail1:
3745e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
3755e111ed8SAndrew Rybchenko 
3765e111ed8SAndrew Rybchenko 	return (rc);
3775e111ed8SAndrew Rybchenko }
3785e111ed8SAndrew Rybchenko 
3795e111ed8SAndrew Rybchenko 	__checkReturn			efx_rc_t
efx_evb_vport_mac_set(__in efx_nic_t * enp,__in efx_vswitch_t * evp,__in efx_vport_id_t vport_id,__in_bcount (EFX_MAC_ADDR_LEN)uint8_t * addrp)3805e111ed8SAndrew Rybchenko efx_evb_vport_mac_set(
3815e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
3825e111ed8SAndrew Rybchenko 	__in				efx_vswitch_t *evp,
3835e111ed8SAndrew Rybchenko 	__in				efx_vport_id_t vport_id,
3845e111ed8SAndrew Rybchenko 	__in_bcount(EFX_MAC_ADDR_LEN)	uint8_t *addrp)
3855e111ed8SAndrew Rybchenko {
3865e111ed8SAndrew Rybchenko 	const efx_evb_ops_t *eeop = enp->en_eeop;
3875e111ed8SAndrew Rybchenko 	efx_rc_t rc;
3885e111ed8SAndrew Rybchenko 
3895e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
3905e111ed8SAndrew Rybchenko 
3915e111ed8SAndrew Rybchenko 	if (eeop->eeo_vport_reconfigure == NULL) {
3925e111ed8SAndrew Rybchenko 		rc = ENOTSUP;
3935e111ed8SAndrew Rybchenko 		goto fail1;
3945e111ed8SAndrew Rybchenko 	}
3955e111ed8SAndrew Rybchenko 
3965e111ed8SAndrew Rybchenko 	if (addrp == NULL) {
3975e111ed8SAndrew Rybchenko 		rc = EINVAL;
3985e111ed8SAndrew Rybchenko 		goto fail2;
3995e111ed8SAndrew Rybchenko 	}
4005e111ed8SAndrew Rybchenko 
4015e111ed8SAndrew Rybchenko 	rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
4025e111ed8SAndrew Rybchenko 		NULL, addrp, NULL);
4035e111ed8SAndrew Rybchenko 	if (rc != 0)
4045e111ed8SAndrew Rybchenko 		goto fail3;
4055e111ed8SAndrew Rybchenko 
4065e111ed8SAndrew Rybchenko 	return (0);
4075e111ed8SAndrew Rybchenko 
4085e111ed8SAndrew Rybchenko fail3:
4095e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
4105e111ed8SAndrew Rybchenko fail2:
4115e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
4125e111ed8SAndrew Rybchenko fail1:
4135e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
4145e111ed8SAndrew Rybchenko 	return (rc);
4155e111ed8SAndrew Rybchenko }
4165e111ed8SAndrew Rybchenko 
4175e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_evb_vport_vlan_set(__in efx_nic_t * enp,__in efx_vswitch_t * evp,__in efx_vport_id_t vport_id,__in uint16_t vid)4185e111ed8SAndrew Rybchenko efx_evb_vport_vlan_set(
4195e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
4205e111ed8SAndrew Rybchenko 	__in		efx_vswitch_t *evp,
4215e111ed8SAndrew Rybchenko 	__in		efx_vport_id_t vport_id,
4225e111ed8SAndrew Rybchenko 	__in		uint16_t vid)
4235e111ed8SAndrew Rybchenko {
4245e111ed8SAndrew Rybchenko 	const efx_evb_ops_t *eeop = enp->en_eeop;
4255e111ed8SAndrew Rybchenko 	efx_rc_t rc;
4265e111ed8SAndrew Rybchenko 
4275e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
4285e111ed8SAndrew Rybchenko 
4295e111ed8SAndrew Rybchenko 	if (eeop->eeo_vport_reconfigure == NULL) {
4305e111ed8SAndrew Rybchenko 		rc = ENOTSUP;
4315e111ed8SAndrew Rybchenko 		goto fail1;
4325e111ed8SAndrew Rybchenko 	}
4335e111ed8SAndrew Rybchenko 
4345e111ed8SAndrew Rybchenko 	rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
4355e111ed8SAndrew Rybchenko 		&vid, NULL, NULL);
4365e111ed8SAndrew Rybchenko 	if (rc != 0)
4375e111ed8SAndrew Rybchenko 		goto fail2;
4385e111ed8SAndrew Rybchenko 
4395e111ed8SAndrew Rybchenko 	return (0);
4405e111ed8SAndrew Rybchenko 
4415e111ed8SAndrew Rybchenko fail2:
4425e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
4435e111ed8SAndrew Rybchenko fail1:
4445e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
4455e111ed8SAndrew Rybchenko 	return (rc);
4465e111ed8SAndrew Rybchenko }
4475e111ed8SAndrew Rybchenko 
4485e111ed8SAndrew Rybchenko 	__checkReturn			efx_rc_t
efx_evb_vport_reset(__in efx_nic_t * enp,__in efx_vswitch_t * evp,__in efx_vport_id_t vport_id,__in_bcount (EFX_MAC_ADDR_LEN)uint8_t * addrp,__in uint16_t vid,__out boolean_t * is_fn_resetp)4495e111ed8SAndrew Rybchenko efx_evb_vport_reset(
4505e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
4515e111ed8SAndrew Rybchenko 	__in				efx_vswitch_t *evp,
4525e111ed8SAndrew Rybchenko 	__in				efx_vport_id_t vport_id,
4535e111ed8SAndrew Rybchenko 	__in_bcount(EFX_MAC_ADDR_LEN)	uint8_t *addrp,
4545e111ed8SAndrew Rybchenko 	__in				uint16_t vid,
4555e111ed8SAndrew Rybchenko 	__out				boolean_t *is_fn_resetp)
4565e111ed8SAndrew Rybchenko {
4575e111ed8SAndrew Rybchenko 	const efx_evb_ops_t *eeop = enp->en_eeop;
4585e111ed8SAndrew Rybchenko 	efx_rc_t rc;
4595e111ed8SAndrew Rybchenko 
4605e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
4615e111ed8SAndrew Rybchenko 
4625e111ed8SAndrew Rybchenko 	if (eeop->eeo_vport_reconfigure == NULL) {
4635e111ed8SAndrew Rybchenko 		rc = ENOTSUP;
4645e111ed8SAndrew Rybchenko 		goto fail1;
4655e111ed8SAndrew Rybchenko 	}
4665e111ed8SAndrew Rybchenko 
4675e111ed8SAndrew Rybchenko 	if (is_fn_resetp == NULL) {
4685e111ed8SAndrew Rybchenko 		rc = EINVAL;
4695e111ed8SAndrew Rybchenko 		goto fail2;
4705e111ed8SAndrew Rybchenko 	}
4715e111ed8SAndrew Rybchenko 
4725e111ed8SAndrew Rybchenko 	rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
4735e111ed8SAndrew Rybchenko 		&vid, addrp, is_fn_resetp);
4745e111ed8SAndrew Rybchenko 	if (rc != 0)
4755e111ed8SAndrew Rybchenko 		goto fail3;
4765e111ed8SAndrew Rybchenko 
4775e111ed8SAndrew Rybchenko 	return (0);
4785e111ed8SAndrew Rybchenko 
4795e111ed8SAndrew Rybchenko fail3:
4805e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
4815e111ed8SAndrew Rybchenko fail2:
4825e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
4835e111ed8SAndrew Rybchenko fail1:
4845e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
4855e111ed8SAndrew Rybchenko 	return (rc);
4865e111ed8SAndrew Rybchenko }
4875e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_evb_vswitch_destroy(__in efx_nic_t * enp,__in efx_vswitch_t * evp)4885e111ed8SAndrew Rybchenko efx_evb_vswitch_destroy(
4895e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
4905e111ed8SAndrew Rybchenko 	__in		efx_vswitch_t *evp)
4915e111ed8SAndrew Rybchenko {
4925e111ed8SAndrew Rybchenko 	const efx_evb_ops_t *eeop = enp->en_eeop;
4935e111ed8SAndrew Rybchenko 	efx_vswitch_id_t vswitch_id;
4945e111ed8SAndrew Rybchenko 	efx_rc_t rc;
4955e111ed8SAndrew Rybchenko 
4965e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(evp != NULL);
4975e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
4985e111ed8SAndrew Rybchenko 
4995e111ed8SAndrew Rybchenko 	if ((eeop->eeo_vport_mac_addr_del == NULL) ||
5005e111ed8SAndrew Rybchenko 	    (eeop->eeo_vadaptor_free == NULL) ||
5015e111ed8SAndrew Rybchenko 	    (eeop->eeo_vport_assign == NULL) ||
5025e111ed8SAndrew Rybchenko 	    (eeop->eeo_vport_free == NULL) ||
5035e111ed8SAndrew Rybchenko 	    (eeop->eeo_vswitch_free == NULL)) {
5045e111ed8SAndrew Rybchenko 		rc = ENOTSUP;
5055e111ed8SAndrew Rybchenko 		goto fail1;
5065e111ed8SAndrew Rybchenko 	}
5075e111ed8SAndrew Rybchenko 
5085e111ed8SAndrew Rybchenko 	vswitch_id  = evp->ev_vswitch_id;
5095e111ed8SAndrew Rybchenko 	efx_evb_free_vports(enp, vswitch_id,
5105e111ed8SAndrew Rybchenko 		evp->ev_num_vports, evp->ev_evcp);
5115e111ed8SAndrew Rybchenko 
5125e111ed8SAndrew Rybchenko 	/* Free the vSwitch object */
5135e111ed8SAndrew Rybchenko 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp);
5145e111ed8SAndrew Rybchenko 	enp->en_vswitchp = NULL;
5155e111ed8SAndrew Rybchenko 
5165e111ed8SAndrew Rybchenko 	/* Free the vSwitch */
5175e111ed8SAndrew Rybchenko 	if ((rc = eeop->eeo_vswitch_free(enp, vswitch_id)) != 0)
5185e111ed8SAndrew Rybchenko 		goto fail2;
5195e111ed8SAndrew Rybchenko 
5205e111ed8SAndrew Rybchenko 	return (0);
5215e111ed8SAndrew Rybchenko 
5225e111ed8SAndrew Rybchenko fail2:
5235e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
5245e111ed8SAndrew Rybchenko 
5255e111ed8SAndrew Rybchenko fail1:
5265e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
5275e111ed8SAndrew Rybchenko 	return (rc);
5285e111ed8SAndrew Rybchenko }
5295e111ed8SAndrew Rybchenko 
5305e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_evb_vport_stats(__in efx_nic_t * enp,__in efx_vswitch_t * evp,__in efx_vport_id_t vport_id,__out efsys_mem_t * stats_bufferp)5315e111ed8SAndrew Rybchenko efx_evb_vport_stats(
5325e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
5335e111ed8SAndrew Rybchenko 	__in		efx_vswitch_t *evp,
5345e111ed8SAndrew Rybchenko 	__in		efx_vport_id_t vport_id,
5355e111ed8SAndrew Rybchenko 	__out		efsys_mem_t *stats_bufferp)
5365e111ed8SAndrew Rybchenko {
5375e111ed8SAndrew Rybchenko 	efx_rc_t rc;
5385e111ed8SAndrew Rybchenko 	const efx_evb_ops_t *eeop = enp->en_eeop;
5395e111ed8SAndrew Rybchenko 
5405e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
5415e111ed8SAndrew Rybchenko 
5425e111ed8SAndrew Rybchenko 	if (eeop->eeo_vport_stats == NULL) {
5435e111ed8SAndrew Rybchenko 		rc = ENOTSUP;
5445e111ed8SAndrew Rybchenko 		goto fail1;
5455e111ed8SAndrew Rybchenko 	}
5465e111ed8SAndrew Rybchenko 
5475e111ed8SAndrew Rybchenko 	if (stats_bufferp == NULL) {
5485e111ed8SAndrew Rybchenko 		rc = EINVAL;
5495e111ed8SAndrew Rybchenko 		goto fail2;
5505e111ed8SAndrew Rybchenko 	}
5515e111ed8SAndrew Rybchenko 
5525e111ed8SAndrew Rybchenko 	rc = eeop->eeo_vport_stats(enp, evp->ev_vswitch_id,
5535e111ed8SAndrew Rybchenko 		vport_id, stats_bufferp);
5545e111ed8SAndrew Rybchenko 	if (rc != 0)
5555e111ed8SAndrew Rybchenko 		goto fail3;
5565e111ed8SAndrew Rybchenko 
5575e111ed8SAndrew Rybchenko 	return (0);
5585e111ed8SAndrew Rybchenko 
5595e111ed8SAndrew Rybchenko fail3:
5605e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
5615e111ed8SAndrew Rybchenko fail2:
5625e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
5635e111ed8SAndrew Rybchenko fail1:
5645e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
5655e111ed8SAndrew Rybchenko 	return (rc);
5665e111ed8SAndrew Rybchenko }
5675e111ed8SAndrew Rybchenko 
5685e111ed8SAndrew Rybchenko #endif
569