xref: /dpdk/drivers/common/sfc_efx/base/efx_port.c (revision e5e5c12756d133e44456e64eafdc3a0e728b57d5)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019-2021 Xilinx, Inc.
4  * Copyright(c) 2009-2019 Solarflare Communications Inc.
5  */
6 
7 #include "efx.h"
8 #include "efx_impl.h"
9 
10 	__checkReturn	efx_rc_t
efx_port_init(__in efx_nic_t * enp)11 efx_port_init(
12 	__in		efx_nic_t *enp)
13 {
14 	efx_port_t *epp = &(enp->en_port);
15 	const efx_phy_ops_t *epop = epp->ep_epop;
16 	efx_rc_t rc;
17 
18 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
19 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
20 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
21 
22 	if (enp->en_mod_flags & EFX_MOD_PORT) {
23 		rc = EINVAL;
24 		goto fail1;
25 	}
26 
27 	enp->en_mod_flags |= EFX_MOD_PORT;
28 
29 	epp->ep_mac_type = EFX_MAC_INVALID;
30 	epp->ep_link_mode = EFX_LINK_UNKNOWN;
31 	epp->ep_mac_drain = B_TRUE;
32 
33 	/* Configure the MAC */
34 	if ((rc = efx_mac_select(enp)) != 0)
35 		goto fail1;
36 
37 	epp->ep_emop->emo_reconfigure(enp);
38 
39 	/* Pick up current phy capababilities */
40 	(void) efx_port_poll(enp, NULL);
41 
42 	/*
43 	 * Turn on the PHY if available, otherwise reset it, and
44 	 * reconfigure it with the current configuration.
45 	 */
46 	if (epop->epo_power != NULL) {
47 		if ((rc = epop->epo_power(enp, B_TRUE)) != 0)
48 			goto fail2;
49 	} else {
50 		if ((rc = epop->epo_reset(enp)) != 0)
51 			goto fail2;
52 	}
53 
54 	EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_PHY);
55 	enp->en_reset_flags &= ~EFX_RESET_PHY;
56 
57 	if ((rc = epop->epo_reconfigure(enp)) != 0)
58 		goto fail3;
59 
60 	return (0);
61 
62 fail3:
63 	EFSYS_PROBE(fail3);
64 fail2:
65 	EFSYS_PROBE(fail2);
66 fail1:
67 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
68 
69 	enp->en_mod_flags &= ~EFX_MOD_PORT;
70 
71 	return (rc);
72 }
73 
74 	__checkReturn	efx_rc_t
efx_port_poll(__in efx_nic_t * enp,__out_opt efx_link_mode_t * link_modep)75 efx_port_poll(
76 	__in		efx_nic_t *enp,
77 	__out_opt	efx_link_mode_t	*link_modep)
78 {
79 	efx_port_t *epp = &(enp->en_port);
80 	const efx_mac_ops_t *emop = epp->ep_emop;
81 	efx_link_mode_t ignore_link_mode;
82 	efx_rc_t rc;
83 
84 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
85 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
86 
87 	EFSYS_ASSERT(emop != NULL);
88 
89 	if (link_modep == NULL)
90 		link_modep = &ignore_link_mode;
91 
92 	if ((rc = emop->emo_poll(enp, link_modep)) != 0)
93 		goto fail1;
94 
95 	return (0);
96 
97 fail1:
98 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
99 
100 	return (rc);
101 }
102 
103 #if EFSYS_OPT_LOOPBACK
104 
105 	__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)106 efx_port_loopback_set(
107 	__in		efx_nic_t *enp,
108 	__in		efx_link_mode_t link_mode,
109 	__in		efx_loopback_type_t loopback_type)
110 {
111 	efx_port_t *epp = &(enp->en_port);
112 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
113 	const efx_mac_ops_t *emop = epp->ep_emop;
114 	efx_rc_t rc;
115 
116 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
117 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
118 	EFSYS_ASSERT(emop != NULL);
119 
120 	EFSYS_ASSERT(link_mode < EFX_LINK_NMODES);
121 
122 	if (EFX_TEST_QWORD_BIT(encp->enc_loopback_types[link_mode],
123 		(int)loopback_type) == 0) {
124 		rc = ENOTSUP;
125 		goto fail1;
126 	}
127 
128 	if (epp->ep_loopback_type == loopback_type &&
129 	    epp->ep_loopback_link_mode == link_mode)
130 		return (0);
131 
132 	if ((rc = emop->emo_loopback_set(enp, link_mode, loopback_type)) != 0)
133 		goto fail2;
134 
135 	return (0);
136 
137 fail2:
138 	EFSYS_PROBE(fail2);
139 fail1:
140 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
141 
142 	return (rc);
143 }
144 
145 #if EFSYS_OPT_NAMES
146 
147 static const char * const __efx_loopback_type_name[] = {
148 	"OFF",
149 	"DATA",
150 	"GMAC",
151 	"XGMII",
152 	"XGXS",
153 	"XAUI",
154 	"GMII",
155 	"SGMII",
156 	"XGBR",
157 	"XFI",
158 	"XAUI_FAR",
159 	"GMII_FAR",
160 	"SGMII_FAR",
161 	"XFI_FAR",
162 	"GPHY",
163 	"PHY_XS",
164 	"PCS",
165 	"PMA_PMD",
166 	"XPORT",
167 	"XGMII_WS",
168 	"XAUI_WS",
169 	"XAUI_WS_FAR",
170 	"XAUI_WS_NEAR",
171 	"GMII_WS",
172 	"XFI_WS",
173 	"XFI_WS_FAR",
174 	"PHYXS_WS",
175 	"PMA_INT",
176 	"SD_NEAR",
177 	"SD_FAR",
178 	"PMA_INT_WS",
179 	"SD_FEP2_WS",
180 	"SD_FEP1_5_WS",
181 	"SD_FEP_WS",
182 	"SD_FES_WS",
183 	"AOE_INT_NEAR",
184 	"DATA_WS",
185 	"FORCE_EXT_LINK",
186 };
187 
188 	__checkReturn	const char *
efx_loopback_type_name(__in efx_nic_t * enp,__in efx_loopback_type_t type)189 efx_loopback_type_name(
190 	__in		efx_nic_t *enp,
191 	__in		efx_loopback_type_t type)
192 {
193 	EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__efx_loopback_type_name) ==
194 	    EFX_LOOPBACK_NTYPES);
195 
196 	_NOTE(ARGUNUSED(enp))
197 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
198 	EFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES);
199 
200 	return (__efx_loopback_type_name[type]);
201 }
202 
203 #endif	/* EFSYS_OPT_NAMES */
204 
205 #endif	/* EFSYS_OPT_LOOPBACK */
206 
207 	__checkReturn	efx_rc_t
efx_port_vlan_strip_set(__in efx_nic_t * enp,__in boolean_t enabled)208 efx_port_vlan_strip_set(
209 	__in		efx_nic_t *enp,
210 	__in		boolean_t enabled)
211 {
212 	efx_port_t *epp = &(enp->en_port);
213 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
214 	uint32_t filter_count = 0;
215 	efx_rc_t rc;
216 
217 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
218 
219 	if (enabled && !encp->enc_rx_vlan_stripping_supported) {
220 		rc = ENOTSUP;
221 		goto fail1;
222 	}
223 
224 	if ((rc = efx_filter_get_count(enp, &filter_count)) != 0)
225 		goto fail2;
226 
227 	if (filter_count != 0) {
228 		rc = EINVAL;
229 		goto fail3;
230 	}
231 
232 	epp->ep_vlan_strip = enabled;
233 
234 	return (0);
235 
236 fail3:
237 	EFSYS_PROBE(fail3);
238 fail2:
239 	EFSYS_PROBE(fail2);
240 fail1:
241 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
242 
243 	return (rc);
244 }
245 
246 			void
efx_port_fini(__in efx_nic_t * enp)247 efx_port_fini(
248 	__in		efx_nic_t *enp)
249 {
250 	efx_port_t *epp = &(enp->en_port);
251 	const efx_phy_ops_t *epop = epp->ep_epop;
252 
253 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
254 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
255 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
256 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
257 
258 	EFSYS_ASSERT(epp->ep_mac_drain);
259 
260 	epp->ep_emop = NULL;
261 	epp->ep_mac_type = EFX_MAC_INVALID;
262 	epp->ep_mac_drain = B_FALSE;
263 
264 	/* Turn off the PHY */
265 	if (epop->epo_power != NULL)
266 		(void) epop->epo_power(enp, B_FALSE);
267 
268 	enp->en_mod_flags &= ~EFX_MOD_PORT;
269 }
270