1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright (c) 2007-2018 Solarflare Communications Inc.
13 #if EFSYS_OPT_SIENA || EFSYS_OPT_HUNTINGTON
14 static const efx_tunnel_ops_t __efx_tunnel_dummy_ops
= {
15 NULL
, /* eto_udp_encap_supported */
16 NULL
, /* eto_reconfigure */
18 #endif /* EFSYS_OPT_SIENA || EFSYS_OPT_HUNTINGTON */
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(
29 static const efx_tunnel_ops_t __efx_tunnel_ef10_ops
= {
30 ef10_udp_encap_supported
, /* eto_udp_encap_supported */
31 ef10_tunnel_reconfigure
, /* eto_reconfigure */
33 #endif /* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
35 static __checkReturn efx_rc_t
36 efx_mcdi_set_tunnel_encap_udp_ports(
38 __in efx_tunnel_cfg_t
*etcp
,
39 __in boolean_t unloading
,
40 __out boolean_t
*resetting
)
43 EFX_MCDI_DECLARE_BUF(payload
,
44 MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_LENMAX
,
45 MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_LEN
);
49 unsigned int entries_num
;
54 entries_num
= etcp
->etc_udp_entries_num
;
56 req
.emr_cmd
= MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS
;
57 req
.emr_in_buf
= payload
;
59 MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_LEN(entries_num
);
60 req
.emr_out_buf
= payload
;
61 req
.emr_out_length
= MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_LEN
;
63 EFX_POPULATE_WORD_1(flags
,
64 MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_UNLOADING
,
65 (unloading
== B_TRUE
) ? 1 : 0);
66 MCDI_IN_SET_WORD(req
, SET_TUNNEL_ENCAP_UDP_PORTS_IN_FLAGS
,
67 EFX_WORD_FIELD(flags
, EFX_WORD_0
));
69 MCDI_IN_SET_WORD(req
, SET_TUNNEL_ENCAP_UDP_PORTS_IN_NUM_ENTRIES
,
72 for (i
= 0; i
< entries_num
; ++i
) {
73 uint16_t mcdi_udp_protocol
;
75 switch (etcp
->etc_udp_entries
[i
].etue_protocol
) {
76 case EFX_TUNNEL_PROTOCOL_VXLAN
:
77 mcdi_udp_protocol
= TUNNEL_ENCAP_UDP_PORT_ENTRY_VXLAN
;
79 case EFX_TUNNEL_PROTOCOL_GENEVE
:
80 mcdi_udp_protocol
= TUNNEL_ENCAP_UDP_PORT_ENTRY_GENEVE
;
88 * UDP port is MCDI native little-endian in the request
89 * and EFX_POPULATE_DWORD cares about conversion from
90 * host/CPU byte order to little-endian.
92 EFX_STATIC_ASSERT(sizeof (efx_dword_t
) ==
93 TUNNEL_ENCAP_UDP_PORT_ENTRY_LEN
);
95 MCDI_IN2(req
, efx_dword_t
,
96 SET_TUNNEL_ENCAP_UDP_PORTS_IN_ENTRIES
)[i
],
97 TUNNEL_ENCAP_UDP_PORT_ENTRY_UDP_PORT
,
98 etcp
->etc_udp_entries
[i
].etue_port
,
99 TUNNEL_ENCAP_UDP_PORT_ENTRY_PROTOCOL
,
103 efx_mcdi_execute(enp
, &req
);
105 if (req
.emr_rc
!= 0) {
110 if (req
.emr_out_length_used
!=
111 MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_LEN
) {
116 *resetting
= MCDI_OUT_WORD_FIELD(req
,
117 SET_TUNNEL_ENCAP_UDP_PORTS_OUT_FLAGS
,
118 SET_TUNNEL_ENCAP_UDP_PORTS_OUT_RESETTING
);
129 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
134 __checkReturn efx_rc_t
138 efx_tunnel_cfg_t
*etcp
= &enp
->en_tunnel_cfg
;
139 const efx_tunnel_ops_t
*etop
;
142 EFSYS_ASSERT3U(enp
->en_magic
, ==, EFX_NIC_MAGIC
);
143 EFSYS_ASSERT3U(enp
->en_mod_flags
, &, EFX_MOD_PROBE
);
144 EFSYS_ASSERT(!(enp
->en_mod_flags
& EFX_MOD_TUNNEL
));
146 EFX_STATIC_ASSERT(EFX_TUNNEL_MAXNENTRIES
==
147 MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_ENTRIES_MAXNUM
);
149 switch (enp
->en_family
) {
151 case EFX_FAMILY_SIENA
:
152 etop
= &__efx_tunnel_dummy_ops
;
154 #endif /* EFSYS_OPT_SIENA */
156 #if EFSYS_OPT_HUNTINGTON
157 case EFX_FAMILY_HUNTINGTON
:
158 etop
= &__efx_tunnel_dummy_ops
;
160 #endif /* EFSYS_OPT_HUNTINGTON */
162 #if EFSYS_OPT_MEDFORD
163 case EFX_FAMILY_MEDFORD
:
164 etop
= &__efx_tunnel_ef10_ops
;
166 #endif /* EFSYS_OPT_MEDFORD */
168 #if EFSYS_OPT_MEDFORD2
169 case EFX_FAMILY_MEDFORD2
:
170 etop
= &__efx_tunnel_ef10_ops
;
172 #endif /* EFSYS_OPT_MEDFORD2 */
180 memset(etcp
->etc_udp_entries
, 0, sizeof (etcp
->etc_udp_entries
));
181 etcp
->etc_udp_entries_num
= 0;
184 enp
->en_mod_flags
|= EFX_MOD_TUNNEL
;
189 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
192 enp
->en_mod_flags
&= ~EFX_MOD_TUNNEL
;
203 EFSYS_ASSERT3U(enp
->en_magic
, ==, EFX_NIC_MAGIC
);
204 EFSYS_ASSERT3U(enp
->en_mod_flags
, &, EFX_MOD_PROBE
);
205 EFSYS_ASSERT3U(enp
->en_mod_flags
, &, EFX_MOD_TUNNEL
);
207 if ((enp
->en_etop
->eto_udp_encap_supported
!= NULL
) &&
208 enp
->en_etop
->eto_udp_encap_supported(enp
)) {
210 * The UNLOADING flag allows the MC to suppress the datapath
211 * reset if it was set on the last call to
212 * MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS by all functions
214 (void) efx_mcdi_set_tunnel_encap_udp_ports(enp
, NULL
, B_TRUE
,
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
;
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
,
453 * Although the caller should be able to handle MC reboot,
454 * it might come in handy to report the impending reboot
455 * by returning EAGAIN
457 return ((resetting
) ? EAGAIN
: 0);
463 EFSYS_PROBE1(fail1
, efx_rc_t
, rc
);
467 #endif /* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
469 #endif /* EFSYS_OPT_TUNNEL */