1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright(c) 2019-2020 Xilinx, Inc.
4 * Copyright(c) 2007-2019 Solarflare Communications Inc.
13 #if EFSYS_OPT_SIENA || EFSYS_OPT_HUNTINGTON || EFSYS_OPT_RIVERHEAD
14 static const efx_tunnel_ops_t __efx_tunnel_dummy_ops = {
15 NULL, /* eto_reconfigure */
18 #endif /* EFSYS_OPT_SIENA || EFSYS_OPT_HUNTINGTON || EFSYS_OPT_RIVERHEAD */
20 #if EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
21 static __checkReturn boolean_t
22 ef10_udp_encap_supported(
25 static __checkReturn efx_rc_t
26 ef10_tunnel_reconfigure(
33 static const efx_tunnel_ops_t __efx_tunnel_ef10_ops = {
34 ef10_tunnel_reconfigure, /* eto_reconfigure */
35 ef10_tunnel_fini, /* eto_fini */
37 #endif /* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
39 static __checkReturn efx_rc_t
40 efx_mcdi_set_tunnel_encap_udp_ports(
42 __in efx_tunnel_cfg_t *etcp,
43 __in boolean_t unloading,
44 __out boolean_t *resetting)
47 EFX_MCDI_DECLARE_BUF(payload,
48 MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_LENMAX,
49 MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_LEN);
53 unsigned int entries_num;
58 entries_num = etcp->etc_udp_entries_num;
60 req.emr_cmd = MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS;
61 req.emr_in_buf = payload;
63 MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_LEN(entries_num);
64 req.emr_out_buf = payload;
65 req.emr_out_length = MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_LEN;
67 EFX_POPULATE_WORD_1(flags,
68 MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_UNLOADING,
69 (unloading == B_TRUE) ? 1 : 0);
70 MCDI_IN_SET_WORD(req, SET_TUNNEL_ENCAP_UDP_PORTS_IN_FLAGS,
71 EFX_WORD_FIELD(flags, EFX_WORD_0));
73 MCDI_IN_SET_WORD(req, SET_TUNNEL_ENCAP_UDP_PORTS_IN_NUM_ENTRIES,
76 for (i = 0; i < entries_num; ++i) {
77 uint16_t mcdi_udp_protocol;
79 switch (etcp->etc_udp_entries[i].etue_protocol) {
80 case EFX_TUNNEL_PROTOCOL_VXLAN:
81 mcdi_udp_protocol = TUNNEL_ENCAP_UDP_PORT_ENTRY_VXLAN;
83 case EFX_TUNNEL_PROTOCOL_GENEVE:
84 mcdi_udp_protocol = TUNNEL_ENCAP_UDP_PORT_ENTRY_GENEVE;
92 * UDP port is MCDI native little-endian in the request
93 * and EFX_POPULATE_DWORD cares about conversion from
94 * host/CPU byte order to little-endian.
96 EFX_STATIC_ASSERT(sizeof (efx_dword_t) ==
97 TUNNEL_ENCAP_UDP_PORT_ENTRY_LEN);
99 MCDI_IN2(req, efx_dword_t,
100 SET_TUNNEL_ENCAP_UDP_PORTS_IN_ENTRIES)[i],
101 TUNNEL_ENCAP_UDP_PORT_ENTRY_UDP_PORT,
102 etcp->etc_udp_entries[i].etue_port,
103 TUNNEL_ENCAP_UDP_PORT_ENTRY_PROTOCOL,
107 efx_mcdi_execute(enp, &req);
109 if (req.emr_rc != 0) {
114 if (req.emr_out_length_used !=
115 MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_LEN) {
120 *resetting = MCDI_OUT_WORD_FIELD(req,
121 SET_TUNNEL_ENCAP_UDP_PORTS_OUT_FLAGS,
122 SET_TUNNEL_ENCAP_UDP_PORTS_OUT_RESETTING);
133 EFSYS_PROBE1(fail1, efx_rc_t, rc);
138 __checkReturn efx_rc_t
142 efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
143 const efx_tunnel_ops_t *etop;
146 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
147 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
148 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TUNNEL));
150 EFX_STATIC_ASSERT(EFX_TUNNEL_MAXNENTRIES ==
151 MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_ENTRIES_MAXNUM);
153 switch (enp->en_family) {
155 case EFX_FAMILY_SIENA:
156 etop = &__efx_tunnel_dummy_ops;
158 #endif /* EFSYS_OPT_SIENA */
160 #if EFSYS_OPT_HUNTINGTON
161 case EFX_FAMILY_HUNTINGTON:
162 etop = &__efx_tunnel_dummy_ops;
164 #endif /* EFSYS_OPT_HUNTINGTON */
166 #if EFSYS_OPT_MEDFORD
167 case EFX_FAMILY_MEDFORD:
168 etop = &__efx_tunnel_ef10_ops;
170 #endif /* EFSYS_OPT_MEDFORD */
172 #if EFSYS_OPT_MEDFORD2
173 case EFX_FAMILY_MEDFORD2:
174 etop = &__efx_tunnel_ef10_ops;
176 #endif /* EFSYS_OPT_MEDFORD2 */
178 #if EFSYS_OPT_RIVERHEAD
179 case EFX_FAMILY_RIVERHEAD:
180 etop = &__efx_tunnel_dummy_ops;
182 #endif /* EFSYS_OPT_RIVERHEAD */
190 memset(etcp->etc_udp_entries, 0, sizeof (etcp->etc_udp_entries));
191 etcp->etc_udp_entries_num = 0;
194 enp->en_mod_flags |= EFX_MOD_TUNNEL;
199 EFSYS_PROBE1(fail1, efx_rc_t, rc);
202 enp->en_mod_flags &= ~EFX_MOD_TUNNEL;
211 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
212 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
213 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TUNNEL);
215 if (enp->en_etop->eto_fini != NULL)
216 enp->en_etop->eto_fini(enp);
219 enp->en_mod_flags &= ~EFX_MOD_TUNNEL;
222 static __checkReturn efx_rc_t
223 efx_tunnel_config_find_udp_tunnel_entry(
224 __in efx_tunnel_cfg_t *etcp,
226 __out unsigned int *entryp)
230 for (i = 0; i < etcp->etc_udp_entries_num; ++i) {
231 efx_tunnel_udp_entry_t *p = &etcp->etc_udp_entries[i];
233 if (p->etue_port == port) {
242 __checkReturn efx_rc_t
243 efx_tunnel_config_udp_add(
245 __in uint16_t port /* host/cpu-endian */,
246 __in efx_tunnel_protocol_t protocol)
248 const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
249 efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
250 efsys_lock_state_t state;
254 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TUNNEL);
256 if (protocol >= EFX_TUNNEL_NPROTOS) {
261 if ((encp->enc_tunnel_encapsulations_supported &
262 (1u << protocol)) == 0) {
267 EFSYS_LOCK(enp->en_eslp, state);
269 rc = efx_tunnel_config_find_udp_tunnel_entry(etcp, port, &entry);
275 if (etcp->etc_udp_entries_num ==
276 encp->enc_tunnel_config_udp_entries_max) {
281 etcp->etc_udp_entries[etcp->etc_udp_entries_num].etue_port = port;
282 etcp->etc_udp_entries[etcp->etc_udp_entries_num].etue_protocol =
285 etcp->etc_udp_entries_num++;
287 EFSYS_UNLOCK(enp->en_eslp, state);
296 EFSYS_UNLOCK(enp->en_eslp, state);
302 EFSYS_PROBE1(fail1, efx_rc_t, rc);
307 __checkReturn efx_rc_t
308 efx_tunnel_config_udp_remove(
310 __in uint16_t port /* host/cpu-endian */,
311 __in efx_tunnel_protocol_t protocol)
313 efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
314 efsys_lock_state_t state;
318 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TUNNEL);
320 EFSYS_LOCK(enp->en_eslp, state);
322 rc = efx_tunnel_config_find_udp_tunnel_entry(etcp, port, &entry);
326 if (etcp->etc_udp_entries[entry].etue_protocol != protocol) {
331 EFSYS_ASSERT3U(etcp->etc_udp_entries_num, >, 0);
332 etcp->etc_udp_entries_num--;
334 if (entry < etcp->etc_udp_entries_num) {
335 memmove(&etcp->etc_udp_entries[entry],
336 &etcp->etc_udp_entries[entry + 1],
337 (etcp->etc_udp_entries_num - entry) *
338 sizeof (etcp->etc_udp_entries[0]));
341 memset(&etcp->etc_udp_entries[etcp->etc_udp_entries_num], 0,
342 sizeof (etcp->etc_udp_entries[0]));
344 EFSYS_UNLOCK(enp->en_eslp, state);
352 EFSYS_PROBE1(fail1, efx_rc_t, rc);
353 EFSYS_UNLOCK(enp->en_eslp, state);
359 efx_tunnel_config_clear(
362 efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
363 efsys_lock_state_t state;
365 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TUNNEL);
367 EFSYS_LOCK(enp->en_eslp, state);
369 etcp->etc_udp_entries_num = 0;
370 memset(etcp->etc_udp_entries, 0, sizeof (etcp->etc_udp_entries));
372 EFSYS_UNLOCK(enp->en_eslp, state);
375 __checkReturn efx_rc_t
376 efx_tunnel_reconfigure(
379 const efx_tunnel_ops_t *etop = enp->en_etop;
382 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TUNNEL);
384 if (etop->eto_reconfigure == NULL) {
389 if ((rc = enp->en_etop->eto_reconfigure(enp)) != 0)
398 EFSYS_PROBE1(fail1, efx_rc_t, rc);
403 #if EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
404 static __checkReturn boolean_t
405 ef10_udp_encap_supported(
408 const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
409 uint32_t udp_tunnels_mask = 0;
411 udp_tunnels_mask |= (1u << EFX_TUNNEL_PROTOCOL_VXLAN);
412 udp_tunnels_mask |= (1u << EFX_TUNNEL_PROTOCOL_GENEVE);
414 return ((encp->enc_tunnel_encapsulations_supported &
415 udp_tunnels_mask) == 0 ? B_FALSE : B_TRUE);
418 static __checkReturn efx_rc_t
419 ef10_tunnel_reconfigure(
422 efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
424 boolean_t resetting = B_FALSE;
425 efsys_lock_state_t state;
426 efx_tunnel_cfg_t etc;
428 EFSYS_LOCK(enp->en_eslp, state);
429 memcpy(&etc, etcp, sizeof (etc));
430 EFSYS_UNLOCK(enp->en_eslp, state);
432 if (ef10_udp_encap_supported(enp) == B_FALSE) {
434 * It is OK to apply empty UDP tunnel ports when UDP
435 * tunnel encapsulations are not supported - just nothing
438 if (etc.etc_udp_entries_num == 0)
444 * All PCI functions can see a reset upon the
445 * MCDI request completion
447 rc = efx_mcdi_set_tunnel_encap_udp_ports(enp, &etc, B_FALSE,
451 * Do not fail if the access is denied when no
452 * tunnel encap UDP ports are configured.
454 if (rc != EACCES || etc.etc_udp_entries_num != 0)
459 * Although the caller should be able to handle MC reboot,
460 * it might come in handy to report the impending reboot
461 * by returning EAGAIN
463 return ((resetting) ? EAGAIN : 0);
469 EFSYS_PROBE1(fail1, efx_rc_t, rc);
480 if (ef10_udp_encap_supported(enp) != B_FALSE) {
482 * The UNLOADING flag allows the MC to suppress the datapath
483 * reset if it was set on the last call to
484 * MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS by all functions
486 (void) efx_mcdi_set_tunnel_encap_udp_ports(enp, NULL, B_TRUE,
490 #endif /* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
492 #endif /* EFSYS_OPT_TUNNEL */