xref: /dpdk/drivers/common/sfc_efx/base/efx_port.c (revision e5e5c12756d133e44456e64eafdc3a0e728b57d5)
15e111ed8SAndrew Rybchenko /* SPDX-License-Identifier: BSD-3-Clause
25e111ed8SAndrew Rybchenko  *
3672386c1SAndrew Rybchenko  * Copyright(c) 2019-2021 Xilinx, Inc.
45e111ed8SAndrew Rybchenko  * Copyright(c) 2009-2019 Solarflare Communications Inc.
55e111ed8SAndrew Rybchenko  */
65e111ed8SAndrew Rybchenko 
75e111ed8SAndrew Rybchenko #include "efx.h"
85e111ed8SAndrew Rybchenko #include "efx_impl.h"
95e111ed8SAndrew Rybchenko 
105e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_port_init(__in efx_nic_t * enp)115e111ed8SAndrew Rybchenko efx_port_init(
125e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
135e111ed8SAndrew Rybchenko {
145e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
155e111ed8SAndrew Rybchenko 	const efx_phy_ops_t *epop = epp->ep_epop;
165e111ed8SAndrew Rybchenko 	efx_rc_t rc;
175e111ed8SAndrew Rybchenko 
185e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
195e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
205e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
215e111ed8SAndrew Rybchenko 
225e111ed8SAndrew Rybchenko 	if (enp->en_mod_flags & EFX_MOD_PORT) {
235e111ed8SAndrew Rybchenko 		rc = EINVAL;
245e111ed8SAndrew Rybchenko 		goto fail1;
255e111ed8SAndrew Rybchenko 	}
265e111ed8SAndrew Rybchenko 
275e111ed8SAndrew Rybchenko 	enp->en_mod_flags |= EFX_MOD_PORT;
285e111ed8SAndrew Rybchenko 
295e111ed8SAndrew Rybchenko 	epp->ep_mac_type = EFX_MAC_INVALID;
305e111ed8SAndrew Rybchenko 	epp->ep_link_mode = EFX_LINK_UNKNOWN;
315e111ed8SAndrew Rybchenko 	epp->ep_mac_drain = B_TRUE;
325e111ed8SAndrew Rybchenko 
335e111ed8SAndrew Rybchenko 	/* Configure the MAC */
345e111ed8SAndrew Rybchenko 	if ((rc = efx_mac_select(enp)) != 0)
355e111ed8SAndrew Rybchenko 		goto fail1;
365e111ed8SAndrew Rybchenko 
375e111ed8SAndrew Rybchenko 	epp->ep_emop->emo_reconfigure(enp);
385e111ed8SAndrew Rybchenko 
395e111ed8SAndrew Rybchenko 	/* Pick up current phy capababilities */
405e111ed8SAndrew Rybchenko 	(void) efx_port_poll(enp, NULL);
415e111ed8SAndrew Rybchenko 
425e111ed8SAndrew Rybchenko 	/*
435e111ed8SAndrew Rybchenko 	 * Turn on the PHY if available, otherwise reset it, and
445e111ed8SAndrew Rybchenko 	 * reconfigure it with the current configuration.
455e111ed8SAndrew Rybchenko 	 */
465e111ed8SAndrew Rybchenko 	if (epop->epo_power != NULL) {
475e111ed8SAndrew Rybchenko 		if ((rc = epop->epo_power(enp, B_TRUE)) != 0)
485e111ed8SAndrew Rybchenko 			goto fail2;
495e111ed8SAndrew Rybchenko 	} else {
505e111ed8SAndrew Rybchenko 		if ((rc = epop->epo_reset(enp)) != 0)
515e111ed8SAndrew Rybchenko 			goto fail2;
525e111ed8SAndrew Rybchenko 	}
535e111ed8SAndrew Rybchenko 
545e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_PHY);
555e111ed8SAndrew Rybchenko 	enp->en_reset_flags &= ~EFX_RESET_PHY;
565e111ed8SAndrew Rybchenko 
575e111ed8SAndrew Rybchenko 	if ((rc = epop->epo_reconfigure(enp)) != 0)
585e111ed8SAndrew Rybchenko 		goto fail3;
595e111ed8SAndrew Rybchenko 
605e111ed8SAndrew Rybchenko 	return (0);
615e111ed8SAndrew Rybchenko 
625e111ed8SAndrew Rybchenko fail3:
635e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail3);
645e111ed8SAndrew Rybchenko fail2:
655e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
665e111ed8SAndrew Rybchenko fail1:
675e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
685e111ed8SAndrew Rybchenko 
695e111ed8SAndrew Rybchenko 	enp->en_mod_flags &= ~EFX_MOD_PORT;
705e111ed8SAndrew Rybchenko 
715e111ed8SAndrew Rybchenko 	return (rc);
725e111ed8SAndrew Rybchenko }
735e111ed8SAndrew Rybchenko 
745e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_port_poll(__in efx_nic_t * enp,__out_opt efx_link_mode_t * link_modep)755e111ed8SAndrew Rybchenko efx_port_poll(
765e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
775e111ed8SAndrew Rybchenko 	__out_opt	efx_link_mode_t	*link_modep)
785e111ed8SAndrew Rybchenko {
795e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
805e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
815e111ed8SAndrew Rybchenko 	efx_link_mode_t ignore_link_mode;
825e111ed8SAndrew Rybchenko 	efx_rc_t rc;
835e111ed8SAndrew Rybchenko 
845e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
855e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
865e111ed8SAndrew Rybchenko 
875e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(emop != NULL);
885e111ed8SAndrew Rybchenko 
895e111ed8SAndrew Rybchenko 	if (link_modep == NULL)
905e111ed8SAndrew Rybchenko 		link_modep = &ignore_link_mode;
915e111ed8SAndrew Rybchenko 
925e111ed8SAndrew Rybchenko 	if ((rc = emop->emo_poll(enp, link_modep)) != 0)
935e111ed8SAndrew Rybchenko 		goto fail1;
945e111ed8SAndrew Rybchenko 
955e111ed8SAndrew Rybchenko 	return (0);
965e111ed8SAndrew Rybchenko 
975e111ed8SAndrew Rybchenko fail1:
985e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
995e111ed8SAndrew Rybchenko 
1005e111ed8SAndrew Rybchenko 	return (rc);
1015e111ed8SAndrew Rybchenko }
1025e111ed8SAndrew Rybchenko 
1035e111ed8SAndrew Rybchenko #if EFSYS_OPT_LOOPBACK
1045e111ed8SAndrew Rybchenko 
1055e111ed8SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_port_loopback_set(__in efx_nic_t * enp,__in efx_link_mode_t link_mode,__in efx_loopback_type_t loopback_type)1065e111ed8SAndrew Rybchenko efx_port_loopback_set(
1075e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
1085e111ed8SAndrew Rybchenko 	__in		efx_link_mode_t link_mode,
1095e111ed8SAndrew Rybchenko 	__in		efx_loopback_type_t loopback_type)
1105e111ed8SAndrew Rybchenko {
1115e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
1125e111ed8SAndrew Rybchenko 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1135e111ed8SAndrew Rybchenko 	const efx_mac_ops_t *emop = epp->ep_emop;
1145e111ed8SAndrew Rybchenko 	efx_rc_t rc;
1155e111ed8SAndrew Rybchenko 
1165e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1175e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
1185e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(emop != NULL);
1195e111ed8SAndrew Rybchenko 
1205e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(link_mode < EFX_LINK_NMODES);
1215e111ed8SAndrew Rybchenko 
1225e111ed8SAndrew Rybchenko 	if (EFX_TEST_QWORD_BIT(encp->enc_loopback_types[link_mode],
1235e111ed8SAndrew Rybchenko 		(int)loopback_type) == 0) {
1245e111ed8SAndrew Rybchenko 		rc = ENOTSUP;
1255e111ed8SAndrew Rybchenko 		goto fail1;
1265e111ed8SAndrew Rybchenko 	}
1275e111ed8SAndrew Rybchenko 
1285e111ed8SAndrew Rybchenko 	if (epp->ep_loopback_type == loopback_type &&
1295e111ed8SAndrew Rybchenko 	    epp->ep_loopback_link_mode == link_mode)
1305e111ed8SAndrew Rybchenko 		return (0);
1315e111ed8SAndrew Rybchenko 
1325e111ed8SAndrew Rybchenko 	if ((rc = emop->emo_loopback_set(enp, link_mode, loopback_type)) != 0)
1335e111ed8SAndrew Rybchenko 		goto fail2;
1345e111ed8SAndrew Rybchenko 
1355e111ed8SAndrew Rybchenko 	return (0);
1365e111ed8SAndrew Rybchenko 
1375e111ed8SAndrew Rybchenko fail2:
1385e111ed8SAndrew Rybchenko 	EFSYS_PROBE(fail2);
1395e111ed8SAndrew Rybchenko fail1:
1405e111ed8SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1415e111ed8SAndrew Rybchenko 
1425e111ed8SAndrew Rybchenko 	return (rc);
1435e111ed8SAndrew Rybchenko }
1445e111ed8SAndrew Rybchenko 
1455e111ed8SAndrew Rybchenko #if EFSYS_OPT_NAMES
1465e111ed8SAndrew Rybchenko 
1475e111ed8SAndrew Rybchenko static const char * const __efx_loopback_type_name[] = {
1485e111ed8SAndrew Rybchenko 	"OFF",
1495e111ed8SAndrew Rybchenko 	"DATA",
1505e111ed8SAndrew Rybchenko 	"GMAC",
1515e111ed8SAndrew Rybchenko 	"XGMII",
1525e111ed8SAndrew Rybchenko 	"XGXS",
1535e111ed8SAndrew Rybchenko 	"XAUI",
1545e111ed8SAndrew Rybchenko 	"GMII",
1555e111ed8SAndrew Rybchenko 	"SGMII",
1565e111ed8SAndrew Rybchenko 	"XGBR",
1575e111ed8SAndrew Rybchenko 	"XFI",
1585e111ed8SAndrew Rybchenko 	"XAUI_FAR",
1595e111ed8SAndrew Rybchenko 	"GMII_FAR",
1605e111ed8SAndrew Rybchenko 	"SGMII_FAR",
1615e111ed8SAndrew Rybchenko 	"XFI_FAR",
1625e111ed8SAndrew Rybchenko 	"GPHY",
1635e111ed8SAndrew Rybchenko 	"PHY_XS",
1645e111ed8SAndrew Rybchenko 	"PCS",
1655e111ed8SAndrew Rybchenko 	"PMA_PMD",
1665e111ed8SAndrew Rybchenko 	"XPORT",
1675e111ed8SAndrew Rybchenko 	"XGMII_WS",
1685e111ed8SAndrew Rybchenko 	"XAUI_WS",
1695e111ed8SAndrew Rybchenko 	"XAUI_WS_FAR",
1705e111ed8SAndrew Rybchenko 	"XAUI_WS_NEAR",
1715e111ed8SAndrew Rybchenko 	"GMII_WS",
1725e111ed8SAndrew Rybchenko 	"XFI_WS",
1735e111ed8SAndrew Rybchenko 	"XFI_WS_FAR",
1745e111ed8SAndrew Rybchenko 	"PHYXS_WS",
1755e111ed8SAndrew Rybchenko 	"PMA_INT",
1765e111ed8SAndrew Rybchenko 	"SD_NEAR",
1775e111ed8SAndrew Rybchenko 	"SD_FAR",
1785e111ed8SAndrew Rybchenko 	"PMA_INT_WS",
1795e111ed8SAndrew Rybchenko 	"SD_FEP2_WS",
1805e111ed8SAndrew Rybchenko 	"SD_FEP1_5_WS",
1815e111ed8SAndrew Rybchenko 	"SD_FEP_WS",
1825e111ed8SAndrew Rybchenko 	"SD_FES_WS",
1835e111ed8SAndrew Rybchenko 	"AOE_INT_NEAR",
1845e111ed8SAndrew Rybchenko 	"DATA_WS",
1855e111ed8SAndrew Rybchenko 	"FORCE_EXT_LINK",
1865e111ed8SAndrew Rybchenko };
1875e111ed8SAndrew Rybchenko 
1885e111ed8SAndrew Rybchenko 	__checkReturn	const char *
efx_loopback_type_name(__in efx_nic_t * enp,__in efx_loopback_type_t type)1895e111ed8SAndrew Rybchenko efx_loopback_type_name(
1905e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp,
1915e111ed8SAndrew Rybchenko 	__in		efx_loopback_type_t type)
1925e111ed8SAndrew Rybchenko {
1935e111ed8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__efx_loopback_type_name) ==
1945e111ed8SAndrew Rybchenko 	    EFX_LOOPBACK_NTYPES);
1955e111ed8SAndrew Rybchenko 
1965e111ed8SAndrew Rybchenko 	_NOTE(ARGUNUSED(enp))
1975e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1985e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES);
1995e111ed8SAndrew Rybchenko 
2005e111ed8SAndrew Rybchenko 	return (__efx_loopback_type_name[type]);
2015e111ed8SAndrew Rybchenko }
2025e111ed8SAndrew Rybchenko 
2035e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_NAMES */
2045e111ed8SAndrew Rybchenko 
2055e111ed8SAndrew Rybchenko #endif	/* EFSYS_OPT_LOOPBACK */
2065e111ed8SAndrew Rybchenko 
207*e5e5c127SArtemii Morozov 	__checkReturn	efx_rc_t
efx_port_vlan_strip_set(__in efx_nic_t * enp,__in boolean_t enabled)208*e5e5c127SArtemii Morozov efx_port_vlan_strip_set(
209*e5e5c127SArtemii Morozov 	__in		efx_nic_t *enp,
210*e5e5c127SArtemii Morozov 	__in		boolean_t enabled)
211*e5e5c127SArtemii Morozov {
212*e5e5c127SArtemii Morozov 	efx_port_t *epp = &(enp->en_port);
213*e5e5c127SArtemii Morozov 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
214*e5e5c127SArtemii Morozov 	uint32_t filter_count = 0;
215*e5e5c127SArtemii Morozov 	efx_rc_t rc;
216*e5e5c127SArtemii Morozov 
217*e5e5c127SArtemii Morozov 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
218*e5e5c127SArtemii Morozov 
219*e5e5c127SArtemii Morozov 	if (enabled && !encp->enc_rx_vlan_stripping_supported) {
220*e5e5c127SArtemii Morozov 		rc = ENOTSUP;
221*e5e5c127SArtemii Morozov 		goto fail1;
222*e5e5c127SArtemii Morozov 	}
223*e5e5c127SArtemii Morozov 
224*e5e5c127SArtemii Morozov 	if ((rc = efx_filter_get_count(enp, &filter_count)) != 0)
225*e5e5c127SArtemii Morozov 		goto fail2;
226*e5e5c127SArtemii Morozov 
227*e5e5c127SArtemii Morozov 	if (filter_count != 0) {
228*e5e5c127SArtemii Morozov 		rc = EINVAL;
229*e5e5c127SArtemii Morozov 		goto fail3;
230*e5e5c127SArtemii Morozov 	}
231*e5e5c127SArtemii Morozov 
232*e5e5c127SArtemii Morozov 	epp->ep_vlan_strip = enabled;
233*e5e5c127SArtemii Morozov 
234*e5e5c127SArtemii Morozov 	return (0);
235*e5e5c127SArtemii Morozov 
236*e5e5c127SArtemii Morozov fail3:
237*e5e5c127SArtemii Morozov 	EFSYS_PROBE(fail3);
238*e5e5c127SArtemii Morozov fail2:
239*e5e5c127SArtemii Morozov 	EFSYS_PROBE(fail2);
240*e5e5c127SArtemii Morozov fail1:
241*e5e5c127SArtemii Morozov 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
242*e5e5c127SArtemii Morozov 
243*e5e5c127SArtemii Morozov 	return (rc);
244*e5e5c127SArtemii Morozov }
245*e5e5c127SArtemii Morozov 
2465e111ed8SAndrew Rybchenko 			void
efx_port_fini(__in efx_nic_t * enp)2475e111ed8SAndrew Rybchenko efx_port_fini(
2485e111ed8SAndrew Rybchenko 	__in		efx_nic_t *enp)
2495e111ed8SAndrew Rybchenko {
2505e111ed8SAndrew Rybchenko 	efx_port_t *epp = &(enp->en_port);
2515e111ed8SAndrew Rybchenko 	const efx_phy_ops_t *epop = epp->ep_epop;
2525e111ed8SAndrew Rybchenko 
2535e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2545e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
2555e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
2565e111ed8SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
2575e111ed8SAndrew Rybchenko 
2585e111ed8SAndrew Rybchenko 	EFSYS_ASSERT(epp->ep_mac_drain);
2595e111ed8SAndrew Rybchenko 
2605e111ed8SAndrew Rybchenko 	epp->ep_emop = NULL;
2615e111ed8SAndrew Rybchenko 	epp->ep_mac_type = EFX_MAC_INVALID;
2625e111ed8SAndrew Rybchenko 	epp->ep_mac_drain = B_FALSE;
2635e111ed8SAndrew Rybchenko 
2645e111ed8SAndrew Rybchenko 	/* Turn off the PHY */
2655e111ed8SAndrew Rybchenko 	if (epop->epo_power != NULL)
2665e111ed8SAndrew Rybchenko 		(void) epop->epo_power(enp, B_FALSE);
2675e111ed8SAndrew Rybchenko 
2685e111ed8SAndrew Rybchenko 	enp->en_mod_flags &= ~EFX_MOD_PORT;
2695e111ed8SAndrew Rybchenko }
270