1d874d2a1SIgor Romanov /* SPDX-License-Identifier: BSD-3-Clause
2d874d2a1SIgor Romanov *
3*672386c1SAndrew Rybchenko * Copyright(c) 2021 Xilinx, Inc.
4d874d2a1SIgor Romanov */
5d874d2a1SIgor Romanov
6d874d2a1SIgor Romanov #include "efx.h"
7d874d2a1SIgor Romanov #include "efx_impl.h"
8d874d2a1SIgor Romanov
9d874d2a1SIgor Romanov #if EFSYS_OPT_RIVERHEAD && EFSYS_OPT_TUNNEL
10d874d2a1SIgor Romanov
11d874d2a1SIgor Romanov /* Match by Ether-type */
12d874d2a1SIgor Romanov #define EFX_VNIC_ENCAP_RULE_MATCH_ETHER_TYPE \
13d874d2a1SIgor Romanov (1u << MC_CMD_VNIC_ENCAP_RULE_ADD_IN_MATCH_ETHER_TYPE_LBN)
14d874d2a1SIgor Romanov /* Match by outer VLAN ID */
15d874d2a1SIgor Romanov #define EFX_VNIC_ENCAP_RULE_MATCH_OUTER_VID \
16d874d2a1SIgor Romanov (1u << MC_CMD_VNIC_ENCAP_RULE_ADD_IN_MATCH_OUTER_VLAN_LBN)
17d874d2a1SIgor Romanov /* Match by local IP host address */
18d874d2a1SIgor Romanov #define EFX_VNIC_ENCAP_RULE_MATCH_LOC_HOST \
19d874d2a1SIgor Romanov (1u << MC_CMD_VNIC_ENCAP_RULE_ADD_IN_MATCH_DST_IP_LBN)
20d874d2a1SIgor Romanov /* Match by IP transport protocol */
21d874d2a1SIgor Romanov #define EFX_VNIC_ENCAP_RULE_MATCH_IP_PROTO \
22d874d2a1SIgor Romanov (1u << MC_CMD_VNIC_ENCAP_RULE_ADD_IN_MATCH_IP_PROTO_LBN)
23d874d2a1SIgor Romanov /* Match by local TCP/UDP port */
24d874d2a1SIgor Romanov #define EFX_VNIC_ENCAP_RULE_MATCH_LOC_PORT \
25d874d2a1SIgor Romanov (1u << MC_CMD_VNIC_ENCAP_RULE_ADD_IN_MATCH_DST_PORT_LBN)
26d874d2a1SIgor Romanov
27d874d2a1SIgor Romanov /*
28d874d2a1SIgor Romanov * Helper structure to pass parameters to MCDI function to add a VNIC
29d874d2a1SIgor Romanov * encapsulation rule.
30d874d2a1SIgor Romanov */
31d874d2a1SIgor Romanov typedef struct efx_vnic_encap_rule_spec_s {
32d874d2a1SIgor Romanov uint32_t evers_mport_selector; /* Host-endian */
33d874d2a1SIgor Romanov uint32_t evers_match_flags; /* Host-endian */
34d874d2a1SIgor Romanov uint16_t evers_ether_type; /* Host-endian */
35d874d2a1SIgor Romanov uint16_t evers_outer_vid; /* Host-endian */
36d874d2a1SIgor Romanov efx_oword_t evers_loc_host; /* Big-endian */
37d874d2a1SIgor Romanov uint8_t evers_ip_proto;
38d874d2a1SIgor Romanov uint16_t evers_loc_port; /* Host-endian */
39d874d2a1SIgor Romanov efx_tunnel_protocol_t evers_encap_type;
40d874d2a1SIgor Romanov } efx_vnic_encap_rule_spec_t;
41d874d2a1SIgor Romanov
42d874d2a1SIgor Romanov static uint32_t
efx_tunnel_protocol2mae_encap_type(__in efx_tunnel_protocol_t proto,__out uint32_t * typep)43d874d2a1SIgor Romanov efx_tunnel_protocol2mae_encap_type(
44d874d2a1SIgor Romanov __in efx_tunnel_protocol_t proto,
45d874d2a1SIgor Romanov __out uint32_t *typep)
46d874d2a1SIgor Romanov {
47d874d2a1SIgor Romanov efx_rc_t rc;
48d874d2a1SIgor Romanov
49d874d2a1SIgor Romanov switch (proto) {
50d874d2a1SIgor Romanov case EFX_TUNNEL_PROTOCOL_NONE:
51d874d2a1SIgor Romanov *typep = MAE_MCDI_ENCAP_TYPE_NONE;
52d874d2a1SIgor Romanov break;
53d874d2a1SIgor Romanov case EFX_TUNNEL_PROTOCOL_VXLAN:
54d874d2a1SIgor Romanov *typep = MAE_MCDI_ENCAP_TYPE_VXLAN;
55d874d2a1SIgor Romanov break;
56d874d2a1SIgor Romanov case EFX_TUNNEL_PROTOCOL_GENEVE:
57d874d2a1SIgor Romanov *typep = MAE_MCDI_ENCAP_TYPE_GENEVE;
58d874d2a1SIgor Romanov break;
59d874d2a1SIgor Romanov case EFX_TUNNEL_PROTOCOL_NVGRE:
60d874d2a1SIgor Romanov *typep = MAE_MCDI_ENCAP_TYPE_NVGRE;
61d874d2a1SIgor Romanov break;
62d874d2a1SIgor Romanov default:
63d874d2a1SIgor Romanov rc = EINVAL;
64d874d2a1SIgor Romanov goto fail1;
65d874d2a1SIgor Romanov }
66d874d2a1SIgor Romanov
67d874d2a1SIgor Romanov return (0);
68d874d2a1SIgor Romanov
69d874d2a1SIgor Romanov fail1:
70d874d2a1SIgor Romanov EFSYS_PROBE1(fail1, efx_rc_t, rc);
71d874d2a1SIgor Romanov
72d874d2a1SIgor Romanov return (rc);
73d874d2a1SIgor Romanov }
74d874d2a1SIgor Romanov
75d874d2a1SIgor Romanov static __checkReturn efx_rc_t
efx_mcdi_vnic_encap_rule_add(__in efx_nic_t * enp,__in const efx_vnic_encap_rule_spec_t * spec,__out efx_vnic_encap_rule_handle_t * handle)76d874d2a1SIgor Romanov efx_mcdi_vnic_encap_rule_add(
77d874d2a1SIgor Romanov __in efx_nic_t *enp,
78d874d2a1SIgor Romanov __in const efx_vnic_encap_rule_spec_t *spec,
79d874d2a1SIgor Romanov __out efx_vnic_encap_rule_handle_t *handle)
80d874d2a1SIgor Romanov
81d874d2a1SIgor Romanov {
82d874d2a1SIgor Romanov efx_mcdi_req_t req;
83d874d2a1SIgor Romanov EFX_MCDI_DECLARE_BUF(payload,
84d874d2a1SIgor Romanov MC_CMD_VNIC_ENCAP_RULE_ADD_IN_LEN,
85d874d2a1SIgor Romanov MC_CMD_VNIC_ENCAP_RULE_ADD_OUT_LEN);
86d874d2a1SIgor Romanov uint32_t encap_type;
87d874d2a1SIgor Romanov efx_rc_t rc;
88d874d2a1SIgor Romanov
89d874d2a1SIgor Romanov req.emr_cmd = MC_CMD_VNIC_ENCAP_RULE_ADD;
90d874d2a1SIgor Romanov req.emr_in_buf = payload;
91d874d2a1SIgor Romanov req.emr_in_length = MC_CMD_VNIC_ENCAP_RULE_ADD_IN_LEN;
92d874d2a1SIgor Romanov req.emr_out_buf = payload;
93d874d2a1SIgor Romanov req.emr_out_length = MC_CMD_VNIC_ENCAP_RULE_ADD_OUT_LEN;
94d874d2a1SIgor Romanov
95d874d2a1SIgor Romanov MCDI_IN_SET_DWORD(req, VNIC_ENCAP_RULE_ADD_IN_MPORT_SELECTOR,
96d874d2a1SIgor Romanov spec->evers_mport_selector);
97d874d2a1SIgor Romanov MCDI_IN_SET_DWORD(req, VNIC_ENCAP_RULE_ADD_IN_MATCH_FLAGS,
98d874d2a1SIgor Romanov spec->evers_match_flags);
99d874d2a1SIgor Romanov
100d874d2a1SIgor Romanov MCDI_IN_SET_WORD_NATIVE(req, VNIC_ENCAP_RULE_ADD_IN_ETHER_TYPE,
101d874d2a1SIgor Romanov __CPU_TO_BE_16(spec->evers_ether_type));
102d874d2a1SIgor Romanov MCDI_IN_SET_WORD_NATIVE(req, VNIC_ENCAP_RULE_ADD_IN_OUTER_VLAN_WORD,
103d874d2a1SIgor Romanov __CPU_TO_BE_16(spec->evers_outer_vid));
104d874d2a1SIgor Romanov
105d874d2a1SIgor Romanov /*
106d874d2a1SIgor Romanov * Address is already in network order as well as the MCDI field,
107d874d2a1SIgor Romanov * so plain copy is used.
108d874d2a1SIgor Romanov */
109d874d2a1SIgor Romanov EFX_STATIC_ASSERT(sizeof (spec->evers_loc_host) ==
110d874d2a1SIgor Romanov MC_CMD_VNIC_ENCAP_RULE_ADD_IN_DST_IP_LEN);
111d874d2a1SIgor Romanov memcpy(MCDI_IN2(req, uint8_t, VNIC_ENCAP_RULE_ADD_IN_DST_IP),
112d874d2a1SIgor Romanov &spec->evers_loc_host.eo_byte[0],
113d874d2a1SIgor Romanov MC_CMD_VNIC_ENCAP_RULE_ADD_IN_DST_IP_LEN);
114d874d2a1SIgor Romanov
115d874d2a1SIgor Romanov MCDI_IN_SET_BYTE(req, VNIC_ENCAP_RULE_ADD_IN_IP_PROTO,
116d874d2a1SIgor Romanov spec->evers_ip_proto);
117d874d2a1SIgor Romanov MCDI_IN_SET_WORD_NATIVE(req, VNIC_ENCAP_RULE_ADD_IN_DST_PORT,
118d874d2a1SIgor Romanov __CPU_TO_BE_16(spec->evers_loc_port));
119d874d2a1SIgor Romanov
120d874d2a1SIgor Romanov rc = efx_tunnel_protocol2mae_encap_type(spec->evers_encap_type,
121d874d2a1SIgor Romanov &encap_type);
122d874d2a1SIgor Romanov if (rc != 0)
123d874d2a1SIgor Romanov goto fail1;
124d874d2a1SIgor Romanov
125d874d2a1SIgor Romanov MCDI_IN_SET_DWORD(req, VNIC_ENCAP_RULE_ADD_IN_ENCAP_TYPE, encap_type);
126d874d2a1SIgor Romanov
127d874d2a1SIgor Romanov efx_mcdi_execute(enp, &req);
128d874d2a1SIgor Romanov
129d874d2a1SIgor Romanov if (req.emr_rc != 0) {
130d874d2a1SIgor Romanov rc = req.emr_rc;
131d874d2a1SIgor Romanov goto fail2;
132d874d2a1SIgor Romanov }
133d874d2a1SIgor Romanov
134d874d2a1SIgor Romanov if (req.emr_out_length_used != MC_CMD_VNIC_ENCAP_RULE_ADD_OUT_LEN) {
135d874d2a1SIgor Romanov rc = EMSGSIZE;
136d874d2a1SIgor Romanov goto fail3;
137d874d2a1SIgor Romanov }
138d874d2a1SIgor Romanov
139d874d2a1SIgor Romanov if (handle != NULL)
140d874d2a1SIgor Romanov *handle = MCDI_OUT_DWORD(req, VNIC_ENCAP_RULE_ADD_OUT_HANDLE);
141d874d2a1SIgor Romanov
142d874d2a1SIgor Romanov return (0);
143d874d2a1SIgor Romanov
144d874d2a1SIgor Romanov fail3:
145d874d2a1SIgor Romanov EFSYS_PROBE(fail3);
146d874d2a1SIgor Romanov
147d874d2a1SIgor Romanov fail2:
148d874d2a1SIgor Romanov EFSYS_PROBE(fail2);
149d874d2a1SIgor Romanov
150d874d2a1SIgor Romanov fail1:
151d874d2a1SIgor Romanov EFSYS_PROBE1(fail1, efx_rc_t, rc);
152d874d2a1SIgor Romanov
153d874d2a1SIgor Romanov return (rc);
154d874d2a1SIgor Romanov }
155d874d2a1SIgor Romanov
156d874d2a1SIgor Romanov static __checkReturn efx_rc_t
efx_mcdi_vnic_encap_rule_remove(__in efx_nic_t * enp,__in efx_vnic_encap_rule_handle_t handle)157d874d2a1SIgor Romanov efx_mcdi_vnic_encap_rule_remove(
158d874d2a1SIgor Romanov __in efx_nic_t *enp,
159d874d2a1SIgor Romanov __in efx_vnic_encap_rule_handle_t handle)
160d874d2a1SIgor Romanov
161d874d2a1SIgor Romanov {
162d874d2a1SIgor Romanov efx_mcdi_req_t req;
163d874d2a1SIgor Romanov EFX_MCDI_DECLARE_BUF(payload,
164d874d2a1SIgor Romanov MC_CMD_VNIC_ENCAP_RULE_REMOVE_IN_LEN,
165d874d2a1SIgor Romanov MC_CMD_VNIC_ENCAP_RULE_REMOVE_OUT_LEN);
166d874d2a1SIgor Romanov efx_rc_t rc;
167d874d2a1SIgor Romanov
168d874d2a1SIgor Romanov req.emr_cmd = MC_CMD_VNIC_ENCAP_RULE_REMOVE;
169d874d2a1SIgor Romanov req.emr_in_buf = payload;
170d874d2a1SIgor Romanov req.emr_in_length = MC_CMD_VNIC_ENCAP_RULE_REMOVE_IN_LEN;
171d874d2a1SIgor Romanov req.emr_out_buf = payload;
172d874d2a1SIgor Romanov req.emr_out_length = MC_CMD_VNIC_ENCAP_RULE_REMOVE_OUT_LEN;
173d874d2a1SIgor Romanov
174d874d2a1SIgor Romanov MCDI_IN_SET_DWORD(req, VNIC_ENCAP_RULE_REMOVE_IN_HANDLE, handle);
175d874d2a1SIgor Romanov
176d874d2a1SIgor Romanov efx_mcdi_execute(enp, &req);
177d874d2a1SIgor Romanov
178d874d2a1SIgor Romanov if (req.emr_rc != 0) {
179d874d2a1SIgor Romanov rc = req.emr_rc;
180d874d2a1SIgor Romanov goto fail1;
181d874d2a1SIgor Romanov }
182d874d2a1SIgor Romanov
183d874d2a1SIgor Romanov if (req.emr_out_length_used != MC_CMD_VNIC_ENCAP_RULE_REMOVE_OUT_LEN) {
184d874d2a1SIgor Romanov rc = EMSGSIZE;
185d874d2a1SIgor Romanov goto fail2;
186d874d2a1SIgor Romanov }
187d874d2a1SIgor Romanov
188d874d2a1SIgor Romanov return (0);
189d874d2a1SIgor Romanov
190d874d2a1SIgor Romanov fail2:
191d874d2a1SIgor Romanov EFSYS_PROBE(fail2);
192d874d2a1SIgor Romanov
193d874d2a1SIgor Romanov fail1:
194d874d2a1SIgor Romanov EFSYS_PROBE1(fail1, efx_rc_t, rc);
195d874d2a1SIgor Romanov
196d874d2a1SIgor Romanov return (rc);
197d874d2a1SIgor Romanov }
198d874d2a1SIgor Romanov
199d874d2a1SIgor Romanov static void
rhead_vnic_encap_rule_spec_init(__in const efx_tunnel_udp_entry_t * etuep,__out efx_vnic_encap_rule_spec_t * spec)200d874d2a1SIgor Romanov rhead_vnic_encap_rule_spec_init(
201d874d2a1SIgor Romanov __in const efx_tunnel_udp_entry_t *etuep,
202d874d2a1SIgor Romanov __out efx_vnic_encap_rule_spec_t *spec)
203d874d2a1SIgor Romanov {
204d874d2a1SIgor Romanov memset(spec, 0, sizeof (*spec));
205d874d2a1SIgor Romanov
206d874d2a1SIgor Romanov spec->evers_mport_selector = MAE_MPORT_SELECTOR_ASSIGNED;
207d874d2a1SIgor Romanov spec->evers_match_flags = EFX_VNIC_ENCAP_RULE_MATCH_IP_PROTO |
208d874d2a1SIgor Romanov EFX_VNIC_ENCAP_RULE_MATCH_LOC_PORT;
209d874d2a1SIgor Romanov spec->evers_ip_proto = EFX_IPPROTO_UDP;
210d874d2a1SIgor Romanov spec->evers_loc_port = etuep->etue_port;
211d874d2a1SIgor Romanov spec->evers_encap_type = etuep->etue_protocol;
212d874d2a1SIgor Romanov }
213d874d2a1SIgor Romanov
214d874d2a1SIgor Romanov static __checkReturn efx_rc_t
rhead_udp_port_tunnel_add(__in efx_nic_t * enp,__inout efx_tunnel_udp_entry_t * etuep)215d874d2a1SIgor Romanov rhead_udp_port_tunnel_add(
216d874d2a1SIgor Romanov __in efx_nic_t *enp,
217d874d2a1SIgor Romanov __inout efx_tunnel_udp_entry_t *etuep)
218d874d2a1SIgor Romanov {
219d874d2a1SIgor Romanov efx_vnic_encap_rule_spec_t spec;
220d874d2a1SIgor Romanov
221d874d2a1SIgor Romanov rhead_vnic_encap_rule_spec_init(etuep, &spec);
222d874d2a1SIgor Romanov return (efx_mcdi_vnic_encap_rule_add(enp, &spec, &etuep->etue_handle));
223d874d2a1SIgor Romanov }
224d874d2a1SIgor Romanov
225d874d2a1SIgor Romanov static __checkReturn efx_rc_t
rhead_udp_port_tunnel_remove(__in efx_nic_t * enp,__in efx_tunnel_udp_entry_t * etuep)226d874d2a1SIgor Romanov rhead_udp_port_tunnel_remove(
227d874d2a1SIgor Romanov __in efx_nic_t *enp,
228d874d2a1SIgor Romanov __in efx_tunnel_udp_entry_t *etuep)
229d874d2a1SIgor Romanov {
230d874d2a1SIgor Romanov return (efx_mcdi_vnic_encap_rule_remove(enp, etuep->etue_handle));
231d874d2a1SIgor Romanov }
232d874d2a1SIgor Romanov
233d874d2a1SIgor Romanov __checkReturn efx_rc_t
rhead_tunnel_reconfigure(__in efx_nic_t * enp)234d874d2a1SIgor Romanov rhead_tunnel_reconfigure(
235d874d2a1SIgor Romanov __in efx_nic_t *enp)
236d874d2a1SIgor Romanov {
237d874d2a1SIgor Romanov efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
238d874d2a1SIgor Romanov efx_rc_t rc;
239d874d2a1SIgor Romanov efsys_lock_state_t state;
240d874d2a1SIgor Romanov efx_tunnel_cfg_t etc;
241d874d2a1SIgor Romanov efx_tunnel_cfg_t added;
242d874d2a1SIgor Romanov unsigned int i;
243d874d2a1SIgor Romanov unsigned int j;
244d874d2a1SIgor Romanov
245d874d2a1SIgor Romanov memset(&added, 0, sizeof(added));
246d874d2a1SIgor Romanov
247d874d2a1SIgor Romanov /*
248d874d2a1SIgor Romanov * Make a local copy of UDP tunnel table to release the lock
249d874d2a1SIgor Romanov * when executing MCDIs.
250d874d2a1SIgor Romanov */
251d874d2a1SIgor Romanov EFSYS_LOCK(enp->en_eslp, state);
252d874d2a1SIgor Romanov memcpy(&etc, etcp, sizeof (etc));
253d874d2a1SIgor Romanov EFSYS_UNLOCK(enp->en_eslp, state);
254d874d2a1SIgor Romanov
255d874d2a1SIgor Romanov for (i = 0; i < etc.etc_udp_entries_num; i++) {
256d874d2a1SIgor Romanov efx_tunnel_udp_entry_t *etc_entry = &etc.etc_udp_entries[i];
257d874d2a1SIgor Romanov
258d874d2a1SIgor Romanov if (etc_entry->etue_busy == B_FALSE)
259d874d2a1SIgor Romanov continue;
260d874d2a1SIgor Romanov
261d874d2a1SIgor Romanov switch (etc_entry->etue_state) {
262d874d2a1SIgor Romanov case EFX_TUNNEL_UDP_ENTRY_APPLIED:
263d874d2a1SIgor Romanov break;
264d874d2a1SIgor Romanov case EFX_TUNNEL_UDP_ENTRY_ADDED:
265d874d2a1SIgor Romanov rc = rhead_udp_port_tunnel_add(enp, etc_entry);
266d874d2a1SIgor Romanov if (rc != 0)
267d874d2a1SIgor Romanov goto fail1;
268d874d2a1SIgor Romanov added.etc_udp_entries[added.etc_udp_entries_num] =
269d874d2a1SIgor Romanov *etc_entry;
270d874d2a1SIgor Romanov added.etc_udp_entries_num++;
271d874d2a1SIgor Romanov break;
272d874d2a1SIgor Romanov case EFX_TUNNEL_UDP_ENTRY_REMOVED:
273d874d2a1SIgor Romanov rc = rhead_udp_port_tunnel_remove(enp, etc_entry);
274d874d2a1SIgor Romanov if (rc != 0)
275d874d2a1SIgor Romanov goto fail2;
276d874d2a1SIgor Romanov break;
277d874d2a1SIgor Romanov default:
278d874d2a1SIgor Romanov EFSYS_ASSERT(0);
279d874d2a1SIgor Romanov break;
280d874d2a1SIgor Romanov }
281d874d2a1SIgor Romanov }
282d874d2a1SIgor Romanov
283d874d2a1SIgor Romanov EFSYS_LOCK(enp->en_eslp, state);
284d874d2a1SIgor Romanov
285d874d2a1SIgor Romanov /*
286d874d2a1SIgor Romanov * Adding or removing non-busy entries does not change the
287d874d2a1SIgor Romanov * order of busy entries. Therefore one linear search iteration
288d874d2a1SIgor Romanov * suffices.
289d874d2a1SIgor Romanov */
290d874d2a1SIgor Romanov for (i = 0, j = 0; i < etcp->etc_udp_entries_num; i++) {
291d874d2a1SIgor Romanov efx_tunnel_udp_entry_t *cur_entry = &etcp->etc_udp_entries[i];
292d874d2a1SIgor Romanov efx_tunnel_udp_entry_t *added_entry = &added.etc_udp_entries[j];
293d874d2a1SIgor Romanov
294d874d2a1SIgor Romanov if (cur_entry->etue_state == EFX_TUNNEL_UDP_ENTRY_ADDED &&
295d874d2a1SIgor Romanov cur_entry->etue_port == added_entry->etue_port) {
296d874d2a1SIgor Romanov cur_entry->etue_handle = added_entry->etue_handle;
297d874d2a1SIgor Romanov j++;
298d874d2a1SIgor Romanov }
299d874d2a1SIgor Romanov }
300d874d2a1SIgor Romanov
301d874d2a1SIgor Romanov EFSYS_UNLOCK(enp->en_eslp, state);
302d874d2a1SIgor Romanov
303d874d2a1SIgor Romanov return (0);
304d874d2a1SIgor Romanov
305d874d2a1SIgor Romanov fail2:
306d874d2a1SIgor Romanov EFSYS_PROBE(fail2);
307d874d2a1SIgor Romanov
308d874d2a1SIgor Romanov fail1:
309d874d2a1SIgor Romanov EFSYS_PROBE1(fail1, efx_rc_t, rc);
310d874d2a1SIgor Romanov
311d874d2a1SIgor Romanov while (i-- > 0) {
312d874d2a1SIgor Romanov if (etc.etc_udp_entries[i].etue_busy == B_FALSE)
313d874d2a1SIgor Romanov continue;
314d874d2a1SIgor Romanov
315d874d2a1SIgor Romanov switch (etc.etc_udp_entries[i].etue_state) {
316d874d2a1SIgor Romanov case EFX_TUNNEL_UDP_ENTRY_APPLIED:
317d874d2a1SIgor Romanov break;
318d874d2a1SIgor Romanov case EFX_TUNNEL_UDP_ENTRY_ADDED:
319d874d2a1SIgor Romanov (void) rhead_udp_port_tunnel_remove(enp,
320d874d2a1SIgor Romanov &etc.etc_udp_entries[i]);
321d874d2a1SIgor Romanov break;
322d874d2a1SIgor Romanov case EFX_TUNNEL_UDP_ENTRY_REMOVED:
323d874d2a1SIgor Romanov (void) rhead_udp_port_tunnel_add(enp,
324d874d2a1SIgor Romanov &etc.etc_udp_entries[i]);
325d874d2a1SIgor Romanov break;
326d874d2a1SIgor Romanov default:
327d874d2a1SIgor Romanov EFSYS_ASSERT(0);
328d874d2a1SIgor Romanov break;
329d874d2a1SIgor Romanov }
330d874d2a1SIgor Romanov }
331d874d2a1SIgor Romanov
332d874d2a1SIgor Romanov return (rc);
333d874d2a1SIgor Romanov }
334d874d2a1SIgor Romanov
335d874d2a1SIgor Romanov void
rhead_tunnel_fini(__in efx_nic_t * enp)336d874d2a1SIgor Romanov rhead_tunnel_fini(
337d874d2a1SIgor Romanov __in efx_nic_t *enp)
338d874d2a1SIgor Romanov {
339d874d2a1SIgor Romanov (void) efx_tunnel_config_clear(enp);
340d874d2a1SIgor Romanov (void) efx_tunnel_reconfigure(enp);
341d874d2a1SIgor Romanov }
342d874d2a1SIgor Romanov
343d874d2a1SIgor Romanov #endif /* EFSYS_OPT_RIVERHEAD && EFSYS_OPT_TUNNEL */
344