xref: /dpdk/drivers/common/sfc_efx/base/efx_mac.c (revision 718263c4f4692457f439bc957876e561870b02f9)
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 #if EFSYS_OPT_SIENA
115e111ed8SAndrew Rybchenko 
125e111ed8SAndrew Rybchenko static	__checkReturn	efx_rc_t
135e111ed8SAndrew Rybchenko siena_mac_multicast_list_set(
145e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp);
155e111ed8SAndrew Rybchenko 
165e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
175e111ed8SAndrew Rybchenko 
185e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA
195e111ed8SAndrew Rybchenko static const efx_mac_ops_t	__efx_mac_siena_ops = {
205e111ed8SAndrew Rybchenko 	siena_mac_poll,				/* emo_poll */
215e111ed8SAndrew Rybchenko 	siena_mac_up,				/* emo_up */
225e111ed8SAndrew Rybchenko 	siena_mac_reconfigure,			/* emo_addr_set */
235e111ed8SAndrew Rybchenko 	siena_mac_reconfigure,			/* emo_pdu_set */
245e111ed8SAndrew Rybchenko 	siena_mac_pdu_get,			/* emo_pdu_get */
255e111ed8SAndrew Rybchenko 	siena_mac_reconfigure,			/* emo_reconfigure */
265e111ed8SAndrew Rybchenko 	siena_mac_multicast_list_set,		/* emo_multicast_list_set */
275e111ed8SAndrew Rybchenko 	NULL,					/* emo_filter_set_default_rxq */
285e111ed8SAndrew Rybchenko 	NULL,				/* emo_filter_default_rxq_clear */
295e111ed8SAndrew Rybchenko #if EFSYS_OPT_LOOPBACK
305e111ed8SAndrew Rybchenko 	siena_mac_loopback_set,			/* emo_loopback_set */
315e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_LOOPBACK */
325e111ed8SAndrew Rybchenko #if EFSYS_OPT_MAC_STATS
335e111ed8SAndrew Rybchenko 	siena_mac_stats_get_mask,		/* emo_stats_get_mask */
345e111ed8SAndrew Rybchenko 	efx_mcdi_mac_stats_clear,		/* emo_stats_clear */
355e111ed8SAndrew Rybchenko 	efx_mcdi_mac_stats_upload,		/* emo_stats_upload */
365e111ed8SAndrew Rybchenko 	efx_mcdi_mac_stats_periodic,		/* emo_stats_periodic */
375e111ed8SAndrew Rybchenko 	siena_mac_stats_update			/* emo_stats_update */
385e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_MAC_STATS */
395e111ed8SAndrew Rybchenko };
405e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_SIENA */
415e111ed8SAndrew Rybchenko 
425e111ed8SAndrew Rybchenko #if EFX_OPTS_EF10()
435e111ed8SAndrew Rybchenko static const efx_mac_ops_t	__efx_mac_ef10_ops = {
445e111ed8SAndrew Rybchenko 	ef10_mac_poll,				/* emo_poll */
455e111ed8SAndrew Rybchenko 	ef10_mac_up,				/* emo_up */
465e111ed8SAndrew Rybchenko 	ef10_mac_addr_set,			/* emo_addr_set */
475e111ed8SAndrew Rybchenko 	ef10_mac_pdu_set,			/* emo_pdu_set */
485e111ed8SAndrew Rybchenko 	ef10_mac_pdu_get,			/* emo_pdu_get */
495e111ed8SAndrew Rybchenko 	ef10_mac_reconfigure,			/* emo_reconfigure */
505e111ed8SAndrew Rybchenko 	ef10_mac_multicast_list_set,		/* emo_multicast_list_set */
515e111ed8SAndrew Rybchenko 	ef10_mac_filter_default_rxq_set,	/* emo_filter_default_rxq_set */
525e111ed8SAndrew Rybchenko 	ef10_mac_filter_default_rxq_clear,
535e111ed8SAndrew Rybchenko 					/* emo_filter_default_rxq_clear */
545e111ed8SAndrew Rybchenko #if EFSYS_OPT_LOOPBACK
555e111ed8SAndrew Rybchenko 	ef10_mac_loopback_set,			/* emo_loopback_set */
565e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_LOOPBACK */
575e111ed8SAndrew Rybchenko #if EFSYS_OPT_MAC_STATS
585e111ed8SAndrew Rybchenko 	ef10_mac_stats_get_mask,		/* emo_stats_get_mask */
595e111ed8SAndrew Rybchenko 	efx_mcdi_mac_stats_clear,		/* emo_stats_clear */
605e111ed8SAndrew Rybchenko 	efx_mcdi_mac_stats_upload,		/* emo_stats_upload */
615e111ed8SAndrew Rybchenko 	efx_mcdi_mac_stats_periodic,		/* emo_stats_periodic */
625e111ed8SAndrew Rybchenko 	ef10_mac_stats_update			/* emo_stats_update */
635e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_MAC_STATS */
645e111ed8SAndrew Rybchenko };
655e111ed8SAndrew Rybchenko #endif	/* EFX_OPTS_EF10() */
665e111ed8SAndrew Rybchenko 
67de0d268fSAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD
68de0d268fSAndrew Rybchenko static const efx_mac_ops_t	__efx_mac_rhead_ops = {
69de0d268fSAndrew Rybchenko 	ef10_mac_poll,				/* emo_poll */
70de0d268fSAndrew Rybchenko 	ef10_mac_up,				/* emo_up */
71de0d268fSAndrew Rybchenko 	ef10_mac_addr_set,			/* emo_addr_set */
72de0d268fSAndrew Rybchenko 	ef10_mac_pdu_set,			/* emo_pdu_set */
73de0d268fSAndrew Rybchenko 	ef10_mac_pdu_get,			/* emo_pdu_get */
74de0d268fSAndrew Rybchenko 	ef10_mac_reconfigure,			/* emo_reconfigure */
75de0d268fSAndrew Rybchenko 	ef10_mac_multicast_list_set,		/* emo_multicast_list_set */
76de0d268fSAndrew Rybchenko 	ef10_mac_filter_default_rxq_set,	/* emo_filter_default_rxq_set */
77de0d268fSAndrew Rybchenko 	ef10_mac_filter_default_rxq_clear,
78de0d268fSAndrew Rybchenko 					/* emo_filter_default_rxq_clear */
79de0d268fSAndrew Rybchenko #if EFSYS_OPT_LOOPBACK
80de0d268fSAndrew Rybchenko 	ef10_mac_loopback_set,			/* emo_loopback_set */
81de0d268fSAndrew Rybchenko #endif	/* EFSYS_OPT_LOOPBACK */
82de0d268fSAndrew Rybchenko #if EFSYS_OPT_MAC_STATS
83de0d268fSAndrew Rybchenko 	ef10_mac_stats_get_mask,		/* emo_stats_get_mask */
84de0d268fSAndrew Rybchenko 	efx_mcdi_mac_stats_clear,		/* emo_stats_clear */
85de0d268fSAndrew Rybchenko 	efx_mcdi_mac_stats_upload,		/* emo_stats_upload */
86de0d268fSAndrew Rybchenko 	efx_mcdi_mac_stats_periodic,		/* emo_stats_periodic */
87de0d268fSAndrew Rybchenko 	ef10_mac_stats_update			/* emo_stats_update */
88de0d268fSAndrew Rybchenko #endif	/* EFSYS_OPT_MAC_STATS */
89de0d268fSAndrew Rybchenko };
90de0d268fSAndrew Rybchenko #endif	/* EFSYS_OPT_RIVERHEAD */
91de0d268fSAndrew Rybchenko 
925e111ed8SAndrew Rybchenko 	__checkReturn			efx_rc_t
efx_mac_pdu_set(__in efx_nic_t * enp,__in size_t pdu)935e111ed8SAndrew Rybchenko efx_mac_pdu_set(
945e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
955e111ed8SAndrew Rybchenko 	__in				size_t pdu)
965e111ed8SAndrew Rybchenko {
975e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
985e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
995e111ed8SAndrew Rybchenko 	uint32_t old_pdu;
1005e111ed8SAndrew Rybchenko 	efx_rc_t rc;
1015e111ed8SAndrew Rybchenko 
1025e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1035e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
1045e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(emop != NULL);
1055e111ed8SAndrew Rybchenko 
1065e111ed8SAndrew Rybchenko 	if (pdu < EFX_MAC_PDU_MIN) {
1075e111ed8SAndrew Rybchenko 		rc = EINVAL;
1085e111ed8SAndrew Rybchenko 		goto fail1;
1095e111ed8SAndrew Rybchenko 	}
1105e111ed8SAndrew Rybchenko 
1115e111ed8SAndrew Rybchenko 	if (pdu > EFX_MAC_PDU_MAX) {
1125e111ed8SAndrew Rybchenko 		rc = EINVAL;
1135e111ed8SAndrew Rybchenko 		goto fail2;
1145e111ed8SAndrew Rybchenko 	}
1155e111ed8SAndrew Rybchenko 
1165e111ed8SAndrew Rybchenko 	old_pdu = epp->ep_mac_pdu;
1175e111ed8SAndrew Rybchenko 	epp->ep_mac_pdu = (uint32_t)pdu;
1185e111ed8SAndrew Rybchenko 	if ((rc = emop->emo_pdu_set(enp)) != 0)
1195e111ed8SAndrew Rybchenko 		goto fail3;
1205e111ed8SAndrew Rybchenko 
1215e111ed8SAndrew Rybchenko 	return (0);
1225e111ed8SAndrew Rybchenko 
1235e111ed8SAndrew Rybchenko fail3:
1245e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
1255e111ed8SAndrew Rybchenko 
1265e111ed8SAndrew Rybchenko 	epp->ep_mac_pdu = old_pdu;
1275e111ed8SAndrew Rybchenko 
1285e111ed8SAndrew Rybchenko fail2:
1295e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
1305e111ed8SAndrew Rybchenko fail1:
1315e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1325e111ed8SAndrew Rybchenko 
1335e111ed8SAndrew Rybchenko 	return (rc);
1345e111ed8SAndrew Rybchenko }
1355e111ed8SAndrew Rybchenko 
1365e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_mac_pdu_get(__in efx_nic_t * enp,__out size_t * pdu)1375e111ed8SAndrew Rybchenko efx_mac_pdu_get(
1385e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
1395e111ed8SAndrew Rybchenko 	__out		size_t *pdu)
1405e111ed8SAndrew Rybchenko {
1415e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
1425e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
1435e111ed8SAndrew Rybchenko 	efx_rc_t rc;
1445e111ed8SAndrew Rybchenko 
1455e111ed8SAndrew Rybchenko 	if ((rc = emop->emo_pdu_get(enp, pdu)) != 0)
1465e111ed8SAndrew Rybchenko 		goto fail1;
1475e111ed8SAndrew Rybchenko 
1485e111ed8SAndrew Rybchenko 	return (0);
1495e111ed8SAndrew Rybchenko 
1505e111ed8SAndrew Rybchenko fail1:
1515e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1525e111ed8SAndrew Rybchenko 
1535e111ed8SAndrew Rybchenko 	return (rc);
1545e111ed8SAndrew Rybchenko }
1555e111ed8SAndrew Rybchenko 
1565e111ed8SAndrew Rybchenko 	__checkReturn			efx_rc_t
efx_mac_addr_set(__in efx_nic_t * enp,__in uint8_t * addr)1575e111ed8SAndrew Rybchenko efx_mac_addr_set(
1585e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
1595e111ed8SAndrew Rybchenko 	__in				uint8_t *addr)
1605e111ed8SAndrew Rybchenko {
1615e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
1625e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
1635e111ed8SAndrew Rybchenko 	uint8_t old_addr[6];
1645e111ed8SAndrew Rybchenko 	uint32_t oui;
1655e111ed8SAndrew Rybchenko 	efx_rc_t rc;
1665e111ed8SAndrew Rybchenko 
1675e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1685e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
1695e111ed8SAndrew Rybchenko 
1705e111ed8SAndrew Rybchenko 	if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
1715e111ed8SAndrew Rybchenko 		rc = EINVAL;
1725e111ed8SAndrew Rybchenko 		goto fail1;
1735e111ed8SAndrew Rybchenko 	}
1745e111ed8SAndrew Rybchenko 
1755e111ed8SAndrew Rybchenko 	oui = addr[0] << 16 | addr[1] << 8 | addr[2];
1765e111ed8SAndrew Rybchenko 	if (oui == 0x000000) {
1775e111ed8SAndrew Rybchenko 		rc = EINVAL;
1785e111ed8SAndrew Rybchenko 		goto fail2;
1795e111ed8SAndrew Rybchenko 	}
1805e111ed8SAndrew Rybchenko 
1815e111ed8SAndrew Rybchenko 	EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
1825e111ed8SAndrew Rybchenko 	EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
1835e111ed8SAndrew Rybchenko 	if ((rc = emop->emo_addr_set(enp)) != 0)
1845e111ed8SAndrew Rybchenko 		goto fail3;
1855e111ed8SAndrew Rybchenko 
1865e111ed8SAndrew Rybchenko 	return (0);
1875e111ed8SAndrew Rybchenko 
1885e111ed8SAndrew Rybchenko fail3:
1895e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
1905e111ed8SAndrew Rybchenko 
1915e111ed8SAndrew Rybchenko 	EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
1925e111ed8SAndrew Rybchenko 
1935e111ed8SAndrew Rybchenko fail2:
1945e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
1955e111ed8SAndrew Rybchenko fail1:
1965e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1975e111ed8SAndrew Rybchenko 
1985e111ed8SAndrew Rybchenko 	return (rc);
1995e111ed8SAndrew Rybchenko }
2005e111ed8SAndrew Rybchenko 
2015e111ed8SAndrew Rybchenko 	__checkReturn			efx_rc_t
efx_mac_filter_set(__in efx_nic_t * enp,__in boolean_t all_unicst,__in boolean_t mulcst,__in boolean_t all_mulcst,__in boolean_t brdcst)2025e111ed8SAndrew Rybchenko efx_mac_filter_set(
2035e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
2045e111ed8SAndrew Rybchenko 	__in				boolean_t all_unicst,
2055e111ed8SAndrew Rybchenko 	__in				boolean_t mulcst,
2065e111ed8SAndrew Rybchenko 	__in				boolean_t all_mulcst,
2075e111ed8SAndrew Rybchenko 	__in				boolean_t brdcst)
2085e111ed8SAndrew Rybchenko {
2095e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
2105e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
2115e111ed8SAndrew Rybchenko 	boolean_t old_all_unicst;
2125e111ed8SAndrew Rybchenko 	boolean_t old_mulcst;
2135e111ed8SAndrew Rybchenko 	boolean_t old_all_mulcst;
2145e111ed8SAndrew Rybchenko 	boolean_t old_brdcst;
2155e111ed8SAndrew Rybchenko 	efx_rc_t rc;
2165e111ed8SAndrew Rybchenko 
2175e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2185e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
2195e111ed8SAndrew Rybchenko 
2205e111ed8SAndrew Rybchenko 	old_all_unicst = epp->ep_all_unicst;
2215e111ed8SAndrew Rybchenko 	old_mulcst = epp->ep_mulcst;
2225e111ed8SAndrew Rybchenko 	old_all_mulcst = epp->ep_all_mulcst;
2235e111ed8SAndrew Rybchenko 	old_brdcst = epp->ep_brdcst;
2245e111ed8SAndrew Rybchenko 
2255e111ed8SAndrew Rybchenko 	epp->ep_all_unicst = all_unicst;
2265e111ed8SAndrew Rybchenko 	epp->ep_mulcst = mulcst;
2275e111ed8SAndrew Rybchenko 	epp->ep_all_mulcst = all_mulcst;
2285e111ed8SAndrew Rybchenko 	epp->ep_brdcst = brdcst;
2295e111ed8SAndrew Rybchenko 
2305e111ed8SAndrew Rybchenko 	if ((rc = emop->emo_reconfigure(enp)) != 0)
2315e111ed8SAndrew Rybchenko 		goto fail1;
2325e111ed8SAndrew Rybchenko 
2335e111ed8SAndrew Rybchenko 	return (0);
2345e111ed8SAndrew Rybchenko 
2355e111ed8SAndrew Rybchenko fail1:
2365e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
2375e111ed8SAndrew Rybchenko 
2385e111ed8SAndrew Rybchenko 	epp->ep_all_unicst = old_all_unicst;
2395e111ed8SAndrew Rybchenko 	epp->ep_mulcst = old_mulcst;
2405e111ed8SAndrew Rybchenko 	epp->ep_all_mulcst = old_all_mulcst;
2415e111ed8SAndrew Rybchenko 	epp->ep_brdcst = old_brdcst;
2425e111ed8SAndrew Rybchenko 
2435e111ed8SAndrew Rybchenko 	return (rc);
2445e111ed8SAndrew Rybchenko }
2455e111ed8SAndrew Rybchenko 
2465e111ed8SAndrew Rybchenko 					void
efx_mac_filter_get_all_ucast_mcast(__in efx_nic_t * enp,__out boolean_t * all_unicst,__out boolean_t * all_mulcst)2475e111ed8SAndrew Rybchenko efx_mac_filter_get_all_ucast_mcast(
2485e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
2495e111ed8SAndrew Rybchenko 	__out				boolean_t *all_unicst,
2505e111ed8SAndrew Rybchenko 	__out				boolean_t *all_mulcst)
2515e111ed8SAndrew Rybchenko {
2525e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
2535e111ed8SAndrew Rybchenko 
2545e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2555e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
2565e111ed8SAndrew Rybchenko 
2575e111ed8SAndrew Rybchenko 	*all_unicst = epp->ep_all_unicst_inserted;
2585e111ed8SAndrew Rybchenko 	*all_mulcst = epp->ep_all_mulcst_inserted;
2595e111ed8SAndrew Rybchenko }
2605e111ed8SAndrew Rybchenko 
2615e111ed8SAndrew Rybchenko 	__checkReturn			efx_rc_t
efx_mac_drain(__in efx_nic_t * enp,__in boolean_t enabled)2625e111ed8SAndrew Rybchenko efx_mac_drain(
2635e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
2645e111ed8SAndrew Rybchenko 	__in				boolean_t enabled)
2655e111ed8SAndrew Rybchenko {
2665e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
2675e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
2685e111ed8SAndrew Rybchenko 	efx_rc_t rc;
2695e111ed8SAndrew Rybchenko 
2705e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2715e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
2725e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(emop != NULL);
2735e111ed8SAndrew Rybchenko 
2745e111ed8SAndrew Rybchenko 	if (epp->ep_mac_drain == enabled)
2755e111ed8SAndrew Rybchenko 		return (0);
2765e111ed8SAndrew Rybchenko 
2775e111ed8SAndrew Rybchenko 	epp->ep_mac_drain = enabled;
2785e111ed8SAndrew Rybchenko 
2795e111ed8SAndrew Rybchenko 	if ((rc = emop->emo_reconfigure(enp)) != 0)
2805e111ed8SAndrew Rybchenko 		goto fail1;
2815e111ed8SAndrew Rybchenko 
2825e111ed8SAndrew Rybchenko 	return (0);
2835e111ed8SAndrew Rybchenko 
2845e111ed8SAndrew Rybchenko fail1:
2855e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
2865e111ed8SAndrew Rybchenko 
2875e111ed8SAndrew Rybchenko 	return (rc);
2885e111ed8SAndrew Rybchenko }
2895e111ed8SAndrew Rybchenko 
2905e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_mac_up(__in efx_nic_t * enp,__out boolean_t * mac_upp)2915e111ed8SAndrew Rybchenko efx_mac_up(
2925e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
2935e111ed8SAndrew Rybchenko 	__out		boolean_t *mac_upp)
2945e111ed8SAndrew Rybchenko {
2955e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
2965e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
2975e111ed8SAndrew Rybchenko 	efx_rc_t rc;
2985e111ed8SAndrew Rybchenko 
2995e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
3005e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
3015e111ed8SAndrew Rybchenko 
3025e111ed8SAndrew Rybchenko 	if ((rc = emop->emo_up(enp, mac_upp)) != 0)
3035e111ed8SAndrew Rybchenko 		goto fail1;
3045e111ed8SAndrew Rybchenko 
3055e111ed8SAndrew Rybchenko 	return (0);
3065e111ed8SAndrew Rybchenko 
3075e111ed8SAndrew Rybchenko fail1:
3085e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
3095e111ed8SAndrew Rybchenko 
3105e111ed8SAndrew Rybchenko 	return (rc);
3115e111ed8SAndrew Rybchenko }
3125e111ed8SAndrew Rybchenko 
3135e111ed8SAndrew Rybchenko 	__checkReturn			efx_rc_t
efx_mac_fcntl_set(__in efx_nic_t * enp,__in unsigned int fcntl,__in boolean_t autoneg)3145e111ed8SAndrew Rybchenko efx_mac_fcntl_set(
3155e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
3165e111ed8SAndrew Rybchenko 	__in				unsigned int fcntl,
3175e111ed8SAndrew Rybchenko 	__in				boolean_t autoneg)
3185e111ed8SAndrew Rybchenko {
3195e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
3205e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
3215e111ed8SAndrew Rybchenko 	const efx_phy_ops_t *epop = epp->ep_epop;
3225e111ed8SAndrew Rybchenko 	unsigned int old_fcntl;
3235e111ed8SAndrew Rybchenko 	boolean_t old_autoneg;
3245e111ed8SAndrew Rybchenko 	unsigned int old_adv_cap;
3255e111ed8SAndrew Rybchenko 	efx_rc_t rc;
3265e111ed8SAndrew Rybchenko 
3275e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
3285e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
3295e111ed8SAndrew Rybchenko 
3305e111ed8SAndrew Rybchenko 	if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
3315e111ed8SAndrew Rybchenko 		rc = EINVAL;
3325e111ed8SAndrew Rybchenko 		goto fail1;
3335e111ed8SAndrew Rybchenko 	}
3345e111ed8SAndrew Rybchenko 
3355e111ed8SAndrew Rybchenko 	/*
3365e111ed8SAndrew Rybchenko 	 * Ignore a request to set flow control auto-negotiation
3375e111ed8SAndrew Rybchenko 	 * if the PHY doesn't support it.
3385e111ed8SAndrew Rybchenko 	 */
3395e111ed8SAndrew Rybchenko 	if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
3405e111ed8SAndrew Rybchenko 		autoneg = B_FALSE;
3415e111ed8SAndrew Rybchenko 
3425e111ed8SAndrew Rybchenko 	old_fcntl = epp->ep_fcntl;
3435e111ed8SAndrew Rybchenko 	old_autoneg = epp->ep_fcntl_autoneg;
3445e111ed8SAndrew Rybchenko 	old_adv_cap = epp->ep_adv_cap_mask;
3455e111ed8SAndrew Rybchenko 
3465e111ed8SAndrew Rybchenko 	epp->ep_fcntl = fcntl;
3475e111ed8SAndrew Rybchenko 	epp->ep_fcntl_autoneg = autoneg;
3485e111ed8SAndrew Rybchenko 
3495e111ed8SAndrew Rybchenko 	/*
3505e111ed8SAndrew Rybchenko 	 * Always encode the flow control settings in the advertised
3515e111ed8SAndrew Rybchenko 	 * capabilities even if we are not trying to auto-negotiate
3525e111ed8SAndrew Rybchenko 	 * them and reconfigure both the PHY and the MAC.
3535e111ed8SAndrew Rybchenko 	 */
3545e111ed8SAndrew Rybchenko 	if (fcntl & EFX_FCNTL_RESPOND)
3555e111ed8SAndrew Rybchenko 		epp->ep_adv_cap_mask |=    (1 << EFX_PHY_CAP_PAUSE |
3565e111ed8SAndrew Rybchenko 					    1 << EFX_PHY_CAP_ASYM);
3575e111ed8SAndrew Rybchenko 	else
3585e111ed8SAndrew Rybchenko 		epp->ep_adv_cap_mask &=   ~(1 << EFX_PHY_CAP_PAUSE |
3595e111ed8SAndrew Rybchenko 					    1 << EFX_PHY_CAP_ASYM);
3605e111ed8SAndrew Rybchenko 
3615e111ed8SAndrew Rybchenko 	if (fcntl & EFX_FCNTL_GENERATE)
3625e111ed8SAndrew Rybchenko 		epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
3635e111ed8SAndrew Rybchenko 
3645e111ed8SAndrew Rybchenko 	if ((rc = epop->epo_reconfigure(enp)) != 0)
3655e111ed8SAndrew Rybchenko 		goto fail2;
3665e111ed8SAndrew Rybchenko 
3675e111ed8SAndrew Rybchenko 	if ((rc = emop->emo_reconfigure(enp)) != 0)
3685e111ed8SAndrew Rybchenko 		goto fail3;
3695e111ed8SAndrew Rybchenko 
3705e111ed8SAndrew Rybchenko 	return (0);
3715e111ed8SAndrew Rybchenko 
3725e111ed8SAndrew Rybchenko fail3:
3735e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
3745e111ed8SAndrew Rybchenko 
3755e111ed8SAndrew Rybchenko fail2:
3765e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
3775e111ed8SAndrew Rybchenko 
3785e111ed8SAndrew Rybchenko 	epp->ep_fcntl = old_fcntl;
3795e111ed8SAndrew Rybchenko 	epp->ep_fcntl_autoneg = old_autoneg;
3805e111ed8SAndrew Rybchenko 	epp->ep_adv_cap_mask = old_adv_cap;
3815e111ed8SAndrew Rybchenko 
3825e111ed8SAndrew Rybchenko fail1:
3835e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
3845e111ed8SAndrew Rybchenko 
3855e111ed8SAndrew Rybchenko 	return (rc);
3865e111ed8SAndrew Rybchenko }
3875e111ed8SAndrew Rybchenko 
3885e111ed8SAndrew Rybchenko 			void
efx_mac_fcntl_get(__in efx_nic_t * enp,__out unsigned int * fcntl_wantedp,__out unsigned int * fcntl_linkp)3895e111ed8SAndrew Rybchenko efx_mac_fcntl_get(
3905e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
3915e111ed8SAndrew Rybchenko 	__out		unsigned int *fcntl_wantedp,
3925e111ed8SAndrew Rybchenko 	__out		unsigned int *fcntl_linkp)
3935e111ed8SAndrew Rybchenko {
3945e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
3955e111ed8SAndrew Rybchenko 	unsigned int wanted = 0;
3965e111ed8SAndrew Rybchenko 
3975e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
3985e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
3995e111ed8SAndrew Rybchenko 
4005e111ed8SAndrew Rybchenko 	/*
4015e111ed8SAndrew Rybchenko 	 * Decode the requested flow control settings from the PHY
4025e111ed8SAndrew Rybchenko 	 * advertised capabilities.
4035e111ed8SAndrew Rybchenko 	 */
4045e111ed8SAndrew Rybchenko 	if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
4055e111ed8SAndrew Rybchenko 		wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
4065e111ed8SAndrew Rybchenko 	if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
4075e111ed8SAndrew Rybchenko 		wanted ^= EFX_FCNTL_GENERATE;
4085e111ed8SAndrew Rybchenko 
4095e111ed8SAndrew Rybchenko 	*fcntl_linkp = epp->ep_fcntl;
4105e111ed8SAndrew Rybchenko 	*fcntl_wantedp = wanted;
4115e111ed8SAndrew Rybchenko }
4125e111ed8SAndrew Rybchenko 
4135e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
4145e111ed8SAndrew Rybchenko efx_mac_multicast_list_set(
4155e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
4165e111ed8SAndrew Rybchenko 	__in_ecount(6*count)		uint8_t const *addrs,
4175e111ed8SAndrew Rybchenko 	__in				int count)
4185e111ed8SAndrew Rybchenko {
4195e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
4205e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
4215e111ed8SAndrew Rybchenko 	uint8_t	*old_mulcst_addr_list = NULL;
4225e111ed8SAndrew Rybchenko 	uint32_t old_mulcst_addr_count;
4235e111ed8SAndrew Rybchenko 	efx_rc_t rc;
4245e111ed8SAndrew Rybchenko 
4255e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
4265e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
4275e111ed8SAndrew Rybchenko 
4285e111ed8SAndrew Rybchenko 	if (count > EFX_MAC_MULTICAST_LIST_MAX) {
4295e111ed8SAndrew Rybchenko 		rc = EINVAL;
4305e111ed8SAndrew Rybchenko 		goto fail1;
4315e111ed8SAndrew Rybchenko 	}
4325e111ed8SAndrew Rybchenko 
4335e111ed8SAndrew Rybchenko 	old_mulcst_addr_count = epp->ep_mulcst_addr_count;
4345e111ed8SAndrew Rybchenko 	if (old_mulcst_addr_count > 0) {
4355e111ed8SAndrew Rybchenko 		/* Allocate memory to store old list (instead of using stack) */
4365e111ed8SAndrew Rybchenko 		EFSYS_KMEM_ALLOC(enp->en_esip,
4375e111ed8SAndrew Rybchenko 				old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
4385e111ed8SAndrew Rybchenko 				old_mulcst_addr_list);
4395e111ed8SAndrew Rybchenko 		if (old_mulcst_addr_list == NULL) {
4405e111ed8SAndrew Rybchenko 			rc = ENOMEM;
4415e111ed8SAndrew Rybchenko 			goto fail2;
4425e111ed8SAndrew Rybchenko 		}
4435e111ed8SAndrew Rybchenko 
4445e111ed8SAndrew Rybchenko 		/* Save the old list in case we need to rollback */
4455e111ed8SAndrew Rybchenko 		memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
4465e111ed8SAndrew Rybchenko 			old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
4475e111ed8SAndrew Rybchenko 	}
4485e111ed8SAndrew Rybchenko 
4495e111ed8SAndrew Rybchenko 	/* Store the new list */
4505e111ed8SAndrew Rybchenko 	memcpy(epp->ep_mulcst_addr_list, addrs,
4515e111ed8SAndrew Rybchenko 		count * EFX_MAC_ADDR_LEN);
4525e111ed8SAndrew Rybchenko 	epp->ep_mulcst_addr_count = count;
4535e111ed8SAndrew Rybchenko 
4545e111ed8SAndrew Rybchenko 	if ((rc = emop->emo_multicast_list_set(enp)) != 0)
4555e111ed8SAndrew Rybchenko 		goto fail3;
4565e111ed8SAndrew Rybchenko 
4575e111ed8SAndrew Rybchenko 	if (old_mulcst_addr_count > 0) {
4585e111ed8SAndrew Rybchenko 		EFSYS_KMEM_FREE(enp->en_esip,
4595e111ed8SAndrew Rybchenko 				old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
4605e111ed8SAndrew Rybchenko 				old_mulcst_addr_list);
4615e111ed8SAndrew Rybchenko 	}
4625e111ed8SAndrew Rybchenko 
4635e111ed8SAndrew Rybchenko 	return (0);
4645e111ed8SAndrew Rybchenko 
4655e111ed8SAndrew Rybchenko fail3:
4665e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
4675e111ed8SAndrew Rybchenko 
4685e111ed8SAndrew Rybchenko 	/* Restore original list on failure */
4695e111ed8SAndrew Rybchenko 	epp->ep_mulcst_addr_count = old_mulcst_addr_count;
4705e111ed8SAndrew Rybchenko 	if (old_mulcst_addr_count > 0) {
4715e111ed8SAndrew Rybchenko 		memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
4725e111ed8SAndrew Rybchenko 			old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
4735e111ed8SAndrew Rybchenko 
4745e111ed8SAndrew Rybchenko 		EFSYS_KMEM_FREE(enp->en_esip,
4755e111ed8SAndrew Rybchenko 				old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
4765e111ed8SAndrew Rybchenko 				old_mulcst_addr_list);
4775e111ed8SAndrew Rybchenko 	}
4785e111ed8SAndrew Rybchenko 
4795e111ed8SAndrew Rybchenko fail2:
4805e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
4815e111ed8SAndrew Rybchenko 
4825e111ed8SAndrew Rybchenko fail1:
4835e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
4845e111ed8SAndrew Rybchenko 
4855e111ed8SAndrew Rybchenko 	return (rc);
4865e111ed8SAndrew Rybchenko 
4875e111ed8SAndrew Rybchenko }
4885e111ed8SAndrew Rybchenko 
4895e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_mac_filter_default_rxq_set(__in efx_nic_t * enp,__in efx_rxq_t * erp,__in boolean_t using_rss)4905e111ed8SAndrew Rybchenko efx_mac_filter_default_rxq_set(
4915e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
4925e111ed8SAndrew Rybchenko 	__in		efx_rxq_t *erp,
4935e111ed8SAndrew Rybchenko 	__in		boolean_t using_rss)
4945e111ed8SAndrew Rybchenko {
4955e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
4965e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
4975e111ed8SAndrew Rybchenko 	efx_rc_t rc;
4985e111ed8SAndrew Rybchenko 
4995e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
5005e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
5015e111ed8SAndrew Rybchenko 
5025e111ed8SAndrew Rybchenko 	if (emop->emo_filter_default_rxq_set != NULL) {
5035e111ed8SAndrew Rybchenko 		rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
5045e111ed8SAndrew Rybchenko 		if (rc != 0)
5055e111ed8SAndrew Rybchenko 			goto fail1;
5065e111ed8SAndrew Rybchenko 	}
5075e111ed8SAndrew Rybchenko 
5085e111ed8SAndrew Rybchenko 	return (0);
5095e111ed8SAndrew Rybchenko 
5105e111ed8SAndrew Rybchenko fail1:
5115e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
5125e111ed8SAndrew Rybchenko 
5135e111ed8SAndrew Rybchenko 	return (rc);
5145e111ed8SAndrew Rybchenko }
5155e111ed8SAndrew Rybchenko 
5165e111ed8SAndrew Rybchenko 			void
efx_mac_filter_default_rxq_clear(__in efx_nic_t * enp)5175e111ed8SAndrew Rybchenko efx_mac_filter_default_rxq_clear(
5185e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
5195e111ed8SAndrew Rybchenko {
5205e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
5215e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
5225e111ed8SAndrew Rybchenko 
5235e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
5245e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
5255e111ed8SAndrew Rybchenko 
5265e111ed8SAndrew Rybchenko 	if (emop->emo_filter_default_rxq_clear != NULL)
5275e111ed8SAndrew Rybchenko 		emop->emo_filter_default_rxq_clear(enp);
5285e111ed8SAndrew Rybchenko }
5295e111ed8SAndrew Rybchenko 
530*718263c4SRoman Zhukov 	__checkReturn	efx_rc_t
efx_mac_include_fcs_set(__in efx_nic_t * enp,__in boolean_t enabled)531*718263c4SRoman Zhukov efx_mac_include_fcs_set(
532*718263c4SRoman Zhukov 	__in		efx_nic_t *enp,
533*718263c4SRoman Zhukov 	__in		boolean_t enabled)
534*718263c4SRoman Zhukov {
535*718263c4SRoman Zhukov 	efx_port_t *epp = &(enp->en_port);
536*718263c4SRoman Zhukov 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
537*718263c4SRoman Zhukov 	const efx_mac_ops_t *emop = epp->ep_emop;
538*718263c4SRoman Zhukov 	efx_rc_t rc;
539*718263c4SRoman Zhukov 
540*718263c4SRoman Zhukov 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
541*718263c4SRoman Zhukov 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
542*718263c4SRoman Zhukov 	EFSYS_ASSERT(emop != NULL);
543*718263c4SRoman Zhukov 
544*718263c4SRoman Zhukov 	if (enabled && !encp->enc_rx_include_fcs_supported) {
545*718263c4SRoman Zhukov 		rc = ENOTSUP;
546*718263c4SRoman Zhukov 		goto fail1;
547*718263c4SRoman Zhukov 	}
548*718263c4SRoman Zhukov 
549*718263c4SRoman Zhukov 	/*
550*718263c4SRoman Zhukov 	 * Enabling 'include FCS' changes link control state and affects
551*718263c4SRoman Zhukov 	 * behaviour for all PCI functions on the port, so to avoid this it
552*718263c4SRoman Zhukov 	 * can be enabled only if the PCI function is exclusive port user
553*718263c4SRoman Zhukov 	 */
554*718263c4SRoman Zhukov 	if (enabled && encp->enc_port_usage != EFX_PORT_USAGE_EXCLUSIVE) {
555*718263c4SRoman Zhukov 		rc = EACCES;
556*718263c4SRoman Zhukov 		goto fail2;
557*718263c4SRoman Zhukov 	}
558*718263c4SRoman Zhukov 
559*718263c4SRoman Zhukov 	if (epp->ep_include_fcs != enabled) {
560*718263c4SRoman Zhukov 		epp->ep_include_fcs = enabled;
561*718263c4SRoman Zhukov 
562*718263c4SRoman Zhukov 		rc = emop->emo_reconfigure(enp);
563*718263c4SRoman Zhukov 		if (rc != 0)
564*718263c4SRoman Zhukov 			goto fail3;
565*718263c4SRoman Zhukov 	}
566*718263c4SRoman Zhukov 
567*718263c4SRoman Zhukov 	return 0;
568*718263c4SRoman Zhukov 
569*718263c4SRoman Zhukov fail3:
570*718263c4SRoman Zhukov 	EFSYS_PROBE(fail3);
571*718263c4SRoman Zhukov fail2:
572*718263c4SRoman Zhukov 	EFSYS_PROBE(fail2);
573*718263c4SRoman Zhukov fail1:
574*718263c4SRoman Zhukov 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
575*718263c4SRoman Zhukov 
576*718263c4SRoman Zhukov 	return rc;
577*718263c4SRoman Zhukov }
5785e111ed8SAndrew Rybchenko 
5795e111ed8SAndrew Rybchenko #if EFSYS_OPT_MAC_STATS
5805e111ed8SAndrew Rybchenko 
5815e111ed8SAndrew Rybchenko #if EFSYS_OPT_NAMES
5825e111ed8SAndrew Rybchenko 
5835e111ed8SAndrew Rybchenko /* START MKCONFIG GENERATED EfxMacStatNamesBlock 1a45a82fcfb30c1b */
5845e111ed8SAndrew Rybchenko static const char * const __efx_mac_stat_name[] = {
5855e111ed8SAndrew Rybchenko 	"rx_octets",
5865e111ed8SAndrew Rybchenko 	"rx_pkts",
5875e111ed8SAndrew Rybchenko 	"rx_unicst_pkts",
5885e111ed8SAndrew Rybchenko 	"rx_multicst_pkts",
5895e111ed8SAndrew Rybchenko 	"rx_brdcst_pkts",
5905e111ed8SAndrew Rybchenko 	"rx_pause_pkts",
5915e111ed8SAndrew Rybchenko 	"rx_le_64_pkts",
5925e111ed8SAndrew Rybchenko 	"rx_65_to_127_pkts",
5935e111ed8SAndrew Rybchenko 	"rx_128_to_255_pkts",
5945e111ed8SAndrew Rybchenko 	"rx_256_to_511_pkts",
5955e111ed8SAndrew Rybchenko 	"rx_512_to_1023_pkts",
5965e111ed8SAndrew Rybchenko 	"rx_1024_to_15xx_pkts",
5975e111ed8SAndrew Rybchenko 	"rx_ge_15xx_pkts",
5985e111ed8SAndrew Rybchenko 	"rx_errors",
5995e111ed8SAndrew Rybchenko 	"rx_fcs_errors",
6005e111ed8SAndrew Rybchenko 	"rx_drop_events",
6015e111ed8SAndrew Rybchenko 	"rx_false_carrier_errors",
6025e111ed8SAndrew Rybchenko 	"rx_symbol_errors",
6035e111ed8SAndrew Rybchenko 	"rx_align_errors",
6045e111ed8SAndrew Rybchenko 	"rx_internal_errors",
6055e111ed8SAndrew Rybchenko 	"rx_jabber_pkts",
6065e111ed8SAndrew Rybchenko 	"rx_lane0_char_err",
6075e111ed8SAndrew Rybchenko 	"rx_lane1_char_err",
6085e111ed8SAndrew Rybchenko 	"rx_lane2_char_err",
6095e111ed8SAndrew Rybchenko 	"rx_lane3_char_err",
6105e111ed8SAndrew Rybchenko 	"rx_lane0_disp_err",
6115e111ed8SAndrew Rybchenko 	"rx_lane1_disp_err",
6125e111ed8SAndrew Rybchenko 	"rx_lane2_disp_err",
6135e111ed8SAndrew Rybchenko 	"rx_lane3_disp_err",
6145e111ed8SAndrew Rybchenko 	"rx_match_fault",
6155e111ed8SAndrew Rybchenko 	"rx_nodesc_drop_cnt",
6165e111ed8SAndrew Rybchenko 	"tx_octets",
6175e111ed8SAndrew Rybchenko 	"tx_pkts",
6185e111ed8SAndrew Rybchenko 	"tx_unicst_pkts",
6195e111ed8SAndrew Rybchenko 	"tx_multicst_pkts",
6205e111ed8SAndrew Rybchenko 	"tx_brdcst_pkts",
6215e111ed8SAndrew Rybchenko 	"tx_pause_pkts",
6225e111ed8SAndrew Rybchenko 	"tx_le_64_pkts",
6235e111ed8SAndrew Rybchenko 	"tx_65_to_127_pkts",
6245e111ed8SAndrew Rybchenko 	"tx_128_to_255_pkts",
6255e111ed8SAndrew Rybchenko 	"tx_256_to_511_pkts",
6265e111ed8SAndrew Rybchenko 	"tx_512_to_1023_pkts",
6275e111ed8SAndrew Rybchenko 	"tx_1024_to_15xx_pkts",
6285e111ed8SAndrew Rybchenko 	"tx_ge_15xx_pkts",
6295e111ed8SAndrew Rybchenko 	"tx_errors",
6305e111ed8SAndrew Rybchenko 	"tx_sgl_col_pkts",
6315e111ed8SAndrew Rybchenko 	"tx_mult_col_pkts",
6325e111ed8SAndrew Rybchenko 	"tx_ex_col_pkts",
6335e111ed8SAndrew Rybchenko 	"tx_late_col_pkts",
6345e111ed8SAndrew Rybchenko 	"tx_def_pkts",
6355e111ed8SAndrew Rybchenko 	"tx_ex_def_pkts",
6365e111ed8SAndrew Rybchenko 	"pm_trunc_bb_overflow",
6375e111ed8SAndrew Rybchenko 	"pm_discard_bb_overflow",
6385e111ed8SAndrew Rybchenko 	"pm_trunc_vfifo_full",
6395e111ed8SAndrew Rybchenko 	"pm_discard_vfifo_full",
6405e111ed8SAndrew Rybchenko 	"pm_trunc_qbb",
6415e111ed8SAndrew Rybchenko 	"pm_discard_qbb",
6425e111ed8SAndrew Rybchenko 	"pm_discard_mapping",
6435e111ed8SAndrew Rybchenko 	"rxdp_q_disabled_pkts",
6445e111ed8SAndrew Rybchenko 	"rxdp_di_dropped_pkts",
6455e111ed8SAndrew Rybchenko 	"rxdp_streaming_pkts",
6465e111ed8SAndrew Rybchenko 	"rxdp_hlb_fetch",
6475e111ed8SAndrew Rybchenko 	"rxdp_hlb_wait",
6485e111ed8SAndrew Rybchenko 	"vadapter_rx_unicast_packets",
6495e111ed8SAndrew Rybchenko 	"vadapter_rx_unicast_bytes",
6505e111ed8SAndrew Rybchenko 	"vadapter_rx_multicast_packets",
6515e111ed8SAndrew Rybchenko 	"vadapter_rx_multicast_bytes",
6525e111ed8SAndrew Rybchenko 	"vadapter_rx_broadcast_packets",
6535e111ed8SAndrew Rybchenko 	"vadapter_rx_broadcast_bytes",
6545e111ed8SAndrew Rybchenko 	"vadapter_rx_bad_packets",
6555e111ed8SAndrew Rybchenko 	"vadapter_rx_bad_bytes",
6565e111ed8SAndrew Rybchenko 	"vadapter_rx_overflow",
6575e111ed8SAndrew Rybchenko 	"vadapter_tx_unicast_packets",
6585e111ed8SAndrew Rybchenko 	"vadapter_tx_unicast_bytes",
6595e111ed8SAndrew Rybchenko 	"vadapter_tx_multicast_packets",
6605e111ed8SAndrew Rybchenko 	"vadapter_tx_multicast_bytes",
6615e111ed8SAndrew Rybchenko 	"vadapter_tx_broadcast_packets",
6625e111ed8SAndrew Rybchenko 	"vadapter_tx_broadcast_bytes",
6635e111ed8SAndrew Rybchenko 	"vadapter_tx_bad_packets",
6645e111ed8SAndrew Rybchenko 	"vadapter_tx_bad_bytes",
6655e111ed8SAndrew Rybchenko 	"vadapter_tx_overflow",
6665e111ed8SAndrew Rybchenko 	"fec_uncorrected_errors",
6675e111ed8SAndrew Rybchenko 	"fec_corrected_errors",
6685e111ed8SAndrew Rybchenko 	"fec_corrected_symbols_lane0",
6695e111ed8SAndrew Rybchenko 	"fec_corrected_symbols_lane1",
6705e111ed8SAndrew Rybchenko 	"fec_corrected_symbols_lane2",
6715e111ed8SAndrew Rybchenko 	"fec_corrected_symbols_lane3",
6725e111ed8SAndrew Rybchenko 	"ctpio_vi_busy_fallback",
6735e111ed8SAndrew Rybchenko 	"ctpio_long_write_success",
6745e111ed8SAndrew Rybchenko 	"ctpio_missing_dbell_fail",
6755e111ed8SAndrew Rybchenko 	"ctpio_overflow_fail",
6765e111ed8SAndrew Rybchenko 	"ctpio_underflow_fail",
6775e111ed8SAndrew Rybchenko 	"ctpio_timeout_fail",
6785e111ed8SAndrew Rybchenko 	"ctpio_noncontig_wr_fail",
6795e111ed8SAndrew Rybchenko 	"ctpio_frm_clobber_fail",
6805e111ed8SAndrew Rybchenko 	"ctpio_invalid_wr_fail",
6815e111ed8SAndrew Rybchenko 	"ctpio_vi_clobber_fallback",
6825e111ed8SAndrew Rybchenko 	"ctpio_unqualified_fallback",
6835e111ed8SAndrew Rybchenko 	"ctpio_runt_fallback",
6845e111ed8SAndrew Rybchenko 	"ctpio_success",
6855e111ed8SAndrew Rybchenko 	"ctpio_fallback",
6865e111ed8SAndrew Rybchenko 	"ctpio_poison",
6875e111ed8SAndrew Rybchenko 	"ctpio_erase",
6885e111ed8SAndrew Rybchenko 	"rxdp_scatter_disabled_trunc",
6895e111ed8SAndrew Rybchenko 	"rxdp_hlb_idle",
6905e111ed8SAndrew Rybchenko 	"rxdp_hlb_timeout",
6915e111ed8SAndrew Rybchenko };
6925e111ed8SAndrew Rybchenko /* END MKCONFIG GENERATED EfxMacStatNamesBlock */
6935e111ed8SAndrew Rybchenko 
6945e111ed8SAndrew Rybchenko 	__checkReturn			const char *
efx_mac_stat_name(__in efx_nic_t * enp,__in unsigned int id)6955e111ed8SAndrew Rybchenko efx_mac_stat_name(
6965e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
6975e111ed8SAndrew Rybchenko 	__in				unsigned int id)
6985e111ed8SAndrew Rybchenko {
6995e111ed8SAndrew Rybchenko 	_NOTE(ARGUNUSED(enp))
7005e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
7015e111ed8SAndrew Rybchenko 
7025e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
7035e111ed8SAndrew Rybchenko 	return (__efx_mac_stat_name[id]);
7045e111ed8SAndrew Rybchenko }
7055e111ed8SAndrew Rybchenko 
7065e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_NAMES */
7075e111ed8SAndrew Rybchenko 
7085e111ed8SAndrew Rybchenko static					efx_rc_t
efx_mac_stats_mask_add_range(__inout_bcount (mask_size)uint32_t * maskp,__in size_t mask_size,__in const struct efx_mac_stats_range * rngp)7095e111ed8SAndrew Rybchenko efx_mac_stats_mask_add_range(
7105e111ed8SAndrew Rybchenko 	__inout_bcount(mask_size)	uint32_t *maskp,
7115e111ed8SAndrew Rybchenko 	__in				size_t mask_size,
7125e111ed8SAndrew Rybchenko 	__in				const struct efx_mac_stats_range *rngp)
7135e111ed8SAndrew Rybchenko {
7145e111ed8SAndrew Rybchenko 	unsigned int mask_npages = mask_size / sizeof (*maskp);
7155e111ed8SAndrew Rybchenko 	unsigned int el;
7165e111ed8SAndrew Rybchenko 	unsigned int el_min;
7175e111ed8SAndrew Rybchenko 	unsigned int el_max;
7185e111ed8SAndrew Rybchenko 	unsigned int low;
7195e111ed8SAndrew Rybchenko 	unsigned int high;
7205e111ed8SAndrew Rybchenko 	unsigned int width;
7215e111ed8SAndrew Rybchenko 	efx_rc_t rc;
7225e111ed8SAndrew Rybchenko 
7235e111ed8SAndrew Rybchenko 	if ((mask_npages * EFX_MAC_STATS_MASK_BITS_PER_PAGE) <=
7245e111ed8SAndrew Rybchenko 	    (unsigned int)rngp->last) {
7255e111ed8SAndrew Rybchenko 		rc = EINVAL;
7265e111ed8SAndrew Rybchenko 		goto fail1;
7275e111ed8SAndrew Rybchenko 	}
7285e111ed8SAndrew Rybchenko 
7295e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(rngp->first, <=, rngp->last);
7305e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(rngp->last, <, EFX_MAC_NSTATS);
7315e111ed8SAndrew Rybchenko 
7325e111ed8SAndrew Rybchenko 	for (el = 0; el < mask_npages; ++el) {
7335e111ed8SAndrew Rybchenko 		el_min = el * EFX_MAC_STATS_MASK_BITS_PER_PAGE;
7345e111ed8SAndrew Rybchenko 		el_max =
7355e111ed8SAndrew Rybchenko 		    el_min + (EFX_MAC_STATS_MASK_BITS_PER_PAGE - 1);
7365e111ed8SAndrew Rybchenko 		if ((unsigned int)rngp->first > el_max ||
7375e111ed8SAndrew Rybchenko 		    (unsigned int)rngp->last < el_min)
7385e111ed8SAndrew Rybchenko 			continue;
7395e111ed8SAndrew Rybchenko 		low = MAX((unsigned int)rngp->first, el_min);
7405e111ed8SAndrew Rybchenko 		high = MIN((unsigned int)rngp->last, el_max);
7415e111ed8SAndrew Rybchenko 		width = high - low + 1;
7425e111ed8SAndrew Rybchenko 		maskp[el] |=
7435e111ed8SAndrew Rybchenko 		    (width == EFX_MAC_STATS_MASK_BITS_PER_PAGE) ?
7445e111ed8SAndrew Rybchenko 		    (~0ULL) : (((1ULL << width) - 1) << (low - el_min));
7455e111ed8SAndrew Rybchenko 	}
7465e111ed8SAndrew Rybchenko 
7475e111ed8SAndrew Rybchenko 	return (0);
7485e111ed8SAndrew Rybchenko 
7495e111ed8SAndrew Rybchenko fail1:
7505e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
7515e111ed8SAndrew Rybchenko 
7525e111ed8SAndrew Rybchenko 	return (rc);
7535e111ed8SAndrew Rybchenko }
7545e111ed8SAndrew Rybchenko 
7555e111ed8SAndrew Rybchenko 					efx_rc_t
efx_mac_stats_mask_add_ranges(__inout_bcount (mask_size)uint32_t * maskp,__in size_t mask_size,__in_ecount (rng_count)const struct efx_mac_stats_range * rngp,__in unsigned int rng_count)7565e111ed8SAndrew Rybchenko efx_mac_stats_mask_add_ranges(
7575e111ed8SAndrew Rybchenko 	__inout_bcount(mask_size)	uint32_t *maskp,
7585e111ed8SAndrew Rybchenko 	__in				size_t mask_size,
7595e111ed8SAndrew Rybchenko 	__in_ecount(rng_count)		const struct efx_mac_stats_range *rngp,
7605e111ed8SAndrew Rybchenko 	__in				unsigned int rng_count)
7615e111ed8SAndrew Rybchenko {
7625e111ed8SAndrew Rybchenko 	unsigned int i;
7635e111ed8SAndrew Rybchenko 	efx_rc_t rc;
7645e111ed8SAndrew Rybchenko 
7655e111ed8SAndrew Rybchenko 	for (i = 0; i < rng_count; ++i) {
7665e111ed8SAndrew Rybchenko 		if ((rc = efx_mac_stats_mask_add_range(maskp, mask_size,
7675e111ed8SAndrew Rybchenko 		    &rngp[i])) != 0)
7685e111ed8SAndrew Rybchenko 			goto fail1;
7695e111ed8SAndrew Rybchenko 	}
7705e111ed8SAndrew Rybchenko 
7715e111ed8SAndrew Rybchenko 	return (0);
7725e111ed8SAndrew Rybchenko 
7735e111ed8SAndrew Rybchenko fail1:
7745e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
7755e111ed8SAndrew Rybchenko 
7765e111ed8SAndrew Rybchenko 	return (rc);
7775e111ed8SAndrew Rybchenko }
7785e111ed8SAndrew Rybchenko 
7795e111ed8SAndrew Rybchenko 	__checkReturn			efx_rc_t
efx_mac_stats_get_mask(__in efx_nic_t * enp,__out_bcount (mask_size)uint32_t * maskp,__in size_t mask_size)7805e111ed8SAndrew Rybchenko efx_mac_stats_get_mask(
7815e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
7825e111ed8SAndrew Rybchenko 	__out_bcount(mask_size)		uint32_t *maskp,
7835e111ed8SAndrew Rybchenko 	__in				size_t mask_size)
7845e111ed8SAndrew Rybchenko {
7855e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
7865e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
7875e111ed8SAndrew Rybchenko 	efx_rc_t rc;
7885e111ed8SAndrew Rybchenko 
7895e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
7905e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
7915e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(maskp != NULL);
7925e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(mask_size % sizeof (maskp[0]) == 0);
7935e111ed8SAndrew Rybchenko 
7945e111ed8SAndrew Rybchenko 	(void) memset(maskp, 0, mask_size);
7955e111ed8SAndrew Rybchenko 
7965e111ed8SAndrew Rybchenko 	if ((rc = emop->emo_stats_get_mask(enp, maskp, mask_size)) != 0)
7975e111ed8SAndrew Rybchenko 		goto fail1;
7985e111ed8SAndrew Rybchenko 
7995e111ed8SAndrew Rybchenko 	return (0);
8005e111ed8SAndrew Rybchenko 
8015e111ed8SAndrew Rybchenko fail1:
8025e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
8035e111ed8SAndrew Rybchenko 
8045e111ed8SAndrew Rybchenko 	return (rc);
8055e111ed8SAndrew Rybchenko }
8065e111ed8SAndrew Rybchenko 
8075e111ed8SAndrew Rybchenko 	__checkReturn			efx_rc_t
efx_mac_stats_clear(__in efx_nic_t * enp)8085e111ed8SAndrew Rybchenko efx_mac_stats_clear(
8095e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp)
8105e111ed8SAndrew Rybchenko {
8115e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
8125e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
8135e111ed8SAndrew Rybchenko 	efx_rc_t rc;
8145e111ed8SAndrew Rybchenko 
8155e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
8165e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
8175e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(emop != NULL);
8185e111ed8SAndrew Rybchenko 
8195e111ed8SAndrew Rybchenko 	if ((rc = emop->emo_stats_clear(enp)) != 0)
8205e111ed8SAndrew Rybchenko 		goto fail1;
8215e111ed8SAndrew Rybchenko 
8225e111ed8SAndrew Rybchenko 	return (0);
8235e111ed8SAndrew Rybchenko 
8245e111ed8SAndrew Rybchenko fail1:
8255e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
8265e111ed8SAndrew Rybchenko 
8275e111ed8SAndrew Rybchenko 	return (rc);
8285e111ed8SAndrew Rybchenko }
8295e111ed8SAndrew Rybchenko 
8305e111ed8SAndrew Rybchenko 	__checkReturn			efx_rc_t
efx_mac_stats_upload(__in efx_nic_t * enp,__in efsys_mem_t * esmp)8315e111ed8SAndrew Rybchenko efx_mac_stats_upload(
8325e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
8335e111ed8SAndrew Rybchenko 	__in				efsys_mem_t *esmp)
8345e111ed8SAndrew Rybchenko {
8355e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
8365e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
8375e111ed8SAndrew Rybchenko 	efx_rc_t rc;
8385e111ed8SAndrew Rybchenko 
8395e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
8405e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
8415e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(emop != NULL);
8425e111ed8SAndrew Rybchenko 
8435e111ed8SAndrew Rybchenko 	if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
8445e111ed8SAndrew Rybchenko 		goto fail1;
8455e111ed8SAndrew Rybchenko 
8465e111ed8SAndrew Rybchenko 	return (0);
8475e111ed8SAndrew Rybchenko 
8485e111ed8SAndrew Rybchenko fail1:
8495e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
8505e111ed8SAndrew Rybchenko 
8515e111ed8SAndrew Rybchenko 	return (rc);
8525e111ed8SAndrew Rybchenko }
8535e111ed8SAndrew Rybchenko 
8545e111ed8SAndrew Rybchenko 	__checkReturn			efx_rc_t
efx_mac_stats_periodic(__in efx_nic_t * enp,__in efsys_mem_t * esmp,__in uint16_t period_ms,__in boolean_t events)8555e111ed8SAndrew Rybchenko efx_mac_stats_periodic(
8565e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
8575e111ed8SAndrew Rybchenko 	__in				efsys_mem_t *esmp,
8585e111ed8SAndrew Rybchenko 	__in				uint16_t period_ms,
8595e111ed8SAndrew Rybchenko 	__in				boolean_t events)
8605e111ed8SAndrew Rybchenko {
8615e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
8625e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
8635e111ed8SAndrew Rybchenko 	efx_rc_t rc;
8645e111ed8SAndrew Rybchenko 
8655e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
8665e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
8675e111ed8SAndrew Rybchenko 
8685e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(emop != NULL);
8695e111ed8SAndrew Rybchenko 
8705e111ed8SAndrew Rybchenko 	if (emop->emo_stats_periodic == NULL) {
8715e111ed8SAndrew Rybchenko 		rc = EINVAL;
8725e111ed8SAndrew Rybchenko 		goto fail1;
8735e111ed8SAndrew Rybchenko 	}
8745e111ed8SAndrew Rybchenko 
8755e111ed8SAndrew Rybchenko 	if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
8765e111ed8SAndrew Rybchenko 		goto fail2;
8775e111ed8SAndrew Rybchenko 
8785e111ed8SAndrew Rybchenko 	return (0);
8795e111ed8SAndrew Rybchenko 
8805e111ed8SAndrew Rybchenko fail2:
8815e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
8825e111ed8SAndrew Rybchenko fail1:
8835e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
8845e111ed8SAndrew Rybchenko 
8855e111ed8SAndrew Rybchenko 	return (rc);
8865e111ed8SAndrew Rybchenko }
8875e111ed8SAndrew Rybchenko 
8885e111ed8SAndrew Rybchenko 
8895e111ed8SAndrew Rybchenko 	__checkReturn			efx_rc_t
efx_mac_stats_update(__in efx_nic_t * enp,__in efsys_mem_t * esmp,__inout_ecount (EFX_MAC_NSTATS)efsys_stat_t * essp,__inout_opt uint32_t * generationp)8905e111ed8SAndrew Rybchenko efx_mac_stats_update(
8915e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp,
8925e111ed8SAndrew Rybchenko 	__in				efsys_mem_t *esmp,
8935e111ed8SAndrew Rybchenko 	__inout_ecount(EFX_MAC_NSTATS)	efsys_stat_t *essp,
8945e111ed8SAndrew Rybchenko 	__inout_opt			uint32_t *generationp)
8955e111ed8SAndrew Rybchenko {
8965e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
8975e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
8985e111ed8SAndrew Rybchenko 	efx_rc_t rc;
8995e111ed8SAndrew Rybchenko 
9005e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
9015e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
9025e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(emop != NULL);
9035e111ed8SAndrew Rybchenko 
9045e111ed8SAndrew Rybchenko 	rc = emop->emo_stats_update(enp, esmp, essp, generationp);
9055e111ed8SAndrew Rybchenko 
9065e111ed8SAndrew Rybchenko 	return (rc);
9075e111ed8SAndrew Rybchenko }
9085e111ed8SAndrew Rybchenko 
9095e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_MAC_STATS */
9105e111ed8SAndrew Rybchenko 
9115e111ed8SAndrew Rybchenko 	__checkReturn			efx_rc_t
efx_mac_select(__in efx_nic_t * enp)9125e111ed8SAndrew Rybchenko efx_mac_select(
9135e111ed8SAndrew Rybchenko 	__in				efx_nic_t *enp)
9145e111ed8SAndrew Rybchenko {
9155e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
9165e111ed8SAndrew Rybchenko 	efx_mac_type_t type = EFX_MAC_INVALID;
9175e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop;
9185e111ed8SAndrew Rybchenko 	int rc = EINVAL;
9195e111ed8SAndrew Rybchenko 
9205e111ed8SAndrew Rybchenko 	switch (enp->en_family) {
9215e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA
9225e111ed8SAndrew Rybchenko 	case EFX_FAMILY_SIENA:
9235e111ed8SAndrew Rybchenko 		emop = &__efx_mac_siena_ops;
9245e111ed8SAndrew Rybchenko 		type = EFX_MAC_SIENA;
9255e111ed8SAndrew Rybchenko 		break;
9265e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
9275e111ed8SAndrew Rybchenko 
9285e111ed8SAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
9295e111ed8SAndrew Rybchenko 	case EFX_FAMILY_HUNTINGTON:
9305e111ed8SAndrew Rybchenko 		emop = &__efx_mac_ef10_ops;
9315e111ed8SAndrew Rybchenko 		type = EFX_MAC_HUNTINGTON;
9325e111ed8SAndrew Rybchenko 		break;
9335e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */
9345e111ed8SAndrew Rybchenko 
9355e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD
9365e111ed8SAndrew Rybchenko 	case EFX_FAMILY_MEDFORD:
9375e111ed8SAndrew Rybchenko 		emop = &__efx_mac_ef10_ops;
9385e111ed8SAndrew Rybchenko 		type = EFX_MAC_MEDFORD;
9395e111ed8SAndrew Rybchenko 		break;
9405e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */
9415e111ed8SAndrew Rybchenko 
9425e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
9435e111ed8SAndrew Rybchenko 	case EFX_FAMILY_MEDFORD2:
9445e111ed8SAndrew Rybchenko 		emop = &__efx_mac_ef10_ops;
9455e111ed8SAndrew Rybchenko 		type = EFX_MAC_MEDFORD2;
9465e111ed8SAndrew Rybchenko 		break;
9475e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD2 */
9485e111ed8SAndrew Rybchenko 
949de0d268fSAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD
950de0d268fSAndrew Rybchenko 	case EFX_FAMILY_RIVERHEAD:
951de0d268fSAndrew Rybchenko 		emop = &__efx_mac_rhead_ops;
952de0d268fSAndrew Rybchenko 		type = EFX_MAC_RIVERHEAD;
953de0d268fSAndrew Rybchenko 		break;
954de0d268fSAndrew Rybchenko #endif /* EFSYS_OPT_RIVERHEAD */
955de0d268fSAndrew Rybchenko 
9565e111ed8SAndrew Rybchenko 	default:
9575e111ed8SAndrew Rybchenko 		rc = EINVAL;
9585e111ed8SAndrew Rybchenko 		goto fail1;
9595e111ed8SAndrew Rybchenko 	}
9605e111ed8SAndrew Rybchenko 
9615e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(type != EFX_MAC_INVALID);
9625e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
9635e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(emop != NULL);
9645e111ed8SAndrew Rybchenko 
9655e111ed8SAndrew Rybchenko 	epp->ep_emop = emop;
9665e111ed8SAndrew Rybchenko 	epp->ep_mac_type = type;
9675e111ed8SAndrew Rybchenko 
9685e111ed8SAndrew Rybchenko 	return (0);
9695e111ed8SAndrew Rybchenko 
9705e111ed8SAndrew Rybchenko fail1:
9715e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
9725e111ed8SAndrew Rybchenko 
9735e111ed8SAndrew Rybchenko 	return (rc);
9745e111ed8SAndrew Rybchenko }
9755e111ed8SAndrew Rybchenko 
9765e111ed8SAndrew Rybchenko 
9775e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA
9785e111ed8SAndrew Rybchenko 
9795e111ed8SAndrew Rybchenko #define	EFX_MAC_HASH_BITS	(1 << 8)
9805e111ed8SAndrew Rybchenko 
9815e111ed8SAndrew Rybchenko /* Compute the multicast hash as used on Falcon and Siena. */
9825e111ed8SAndrew Rybchenko static	void
9835e111ed8SAndrew Rybchenko siena_mac_multicast_hash_compute(
9845e111ed8SAndrew Rybchenko 	__in_ecount(6*count)		uint8_t const *addrs,
9855e111ed8SAndrew Rybchenko 	__in				int count,
9865e111ed8SAndrew Rybchenko 	__out				efx_oword_t *hash_low,
9875e111ed8SAndrew Rybchenko 	__out				efx_oword_t *hash_high)
9885e111ed8SAndrew Rybchenko {
9895e111ed8SAndrew Rybchenko 	uint32_t crc, index;
9905e111ed8SAndrew Rybchenko 	int i;
9915e111ed8SAndrew Rybchenko 
9925e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(hash_low != NULL);
9935e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(hash_high != NULL);
9945e111ed8SAndrew Rybchenko 
9955e111ed8SAndrew Rybchenko 	EFX_ZERO_OWORD(*hash_low);
9965e111ed8SAndrew Rybchenko 	EFX_ZERO_OWORD(*hash_high);
9975e111ed8SAndrew Rybchenko 
9985e111ed8SAndrew Rybchenko 	for (i = 0; i < count; i++) {
9995e111ed8SAndrew Rybchenko 		/* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */
10005e111ed8SAndrew Rybchenko 		crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN);
10015e111ed8SAndrew Rybchenko 		index = crc % EFX_MAC_HASH_BITS;
10025e111ed8SAndrew Rybchenko 		if (index < 128) {
10035e111ed8SAndrew Rybchenko 			EFX_SET_OWORD_BIT(*hash_low, index);
10045e111ed8SAndrew Rybchenko 		} else {
10055e111ed8SAndrew Rybchenko 			EFX_SET_OWORD_BIT(*hash_high, index - 128);
10065e111ed8SAndrew Rybchenko 		}
10075e111ed8SAndrew Rybchenko 
10085e111ed8SAndrew Rybchenko 		addrs += EFX_MAC_ADDR_LEN;
10095e111ed8SAndrew Rybchenko 	}
10105e111ed8SAndrew Rybchenko }
10115e111ed8SAndrew Rybchenko 
10125e111ed8SAndrew Rybchenko static	__checkReturn	efx_rc_t
siena_mac_multicast_list_set(__in efx_nic_t * enp)10135e111ed8SAndrew Rybchenko siena_mac_multicast_list_set(
10145e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
10155e111ed8SAndrew Rybchenko {
10165e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
10175e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
10185e111ed8SAndrew Rybchenko 	efx_oword_t old_hash[2];
10195e111ed8SAndrew Rybchenko 	efx_rc_t rc;
10205e111ed8SAndrew Rybchenko 
10215e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
10225e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
10235e111ed8SAndrew Rybchenko 
10245e111ed8SAndrew Rybchenko 	memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
10255e111ed8SAndrew Rybchenko 
10265e111ed8SAndrew Rybchenko 	siena_mac_multicast_hash_compute(
10275e111ed8SAndrew Rybchenko 	    epp->ep_mulcst_addr_list,
10285e111ed8SAndrew Rybchenko 	    epp->ep_mulcst_addr_count,
10295e111ed8SAndrew Rybchenko 	    &epp->ep_multicst_hash[0],
10305e111ed8SAndrew Rybchenko 	    &epp->ep_multicst_hash[1]);
10315e111ed8SAndrew Rybchenko 
10325e111ed8SAndrew Rybchenko 	if ((rc = emop->emo_reconfigure(enp)) != 0)
10335e111ed8SAndrew Rybchenko 		goto fail1;
10345e111ed8SAndrew Rybchenko 
10355e111ed8SAndrew Rybchenko 	return (0);
10365e111ed8SAndrew Rybchenko 
10375e111ed8SAndrew Rybchenko fail1:
10385e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
10395e111ed8SAndrew Rybchenko 
10405e111ed8SAndrew Rybchenko 	memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
10415e111ed8SAndrew Rybchenko 
10425e111ed8SAndrew Rybchenko 	return (rc);
10435e111ed8SAndrew Rybchenko }
10445e111ed8SAndrew Rybchenko 
10455e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
1046