common/sfc_efx/base: use EF10 filter methods for Riverhead
[dpdk.git] / drivers / common / sfc_efx / base / efx_tunnel.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019-2020 Xilinx, Inc.
4  * Copyright(c) 2007-2019 Solarflare Communications Inc.
5  */
6
7 #include "efx.h"
8 #include "efx_impl.h"
9
10
11 #if EFSYS_OPT_TUNNEL
12
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_udp_encap_supported */
16         NULL,   /* eto_reconfigure */
17 };
18 #endif /* EFSYS_OPT_SIENA || EFSYS_OPT_HUNTINGTON || EFSYS_OPT_RIVERHEAD */
19
20 #if EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
21 static  __checkReturn   boolean_t
22 ef10_udp_encap_supported(
23         __in            efx_nic_t *enp);
24
25 static  __checkReturn   efx_rc_t
26 ef10_tunnel_reconfigure(
27         __in            efx_nic_t *enp);
28
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 */
32 };
33 #endif /* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
34
35 static  __checkReturn           efx_rc_t
36 efx_mcdi_set_tunnel_encap_udp_ports(
37         __in                    efx_nic_t *enp,
38         __in                    efx_tunnel_cfg_t *etcp,
39         __in                    boolean_t unloading,
40         __out                   boolean_t *resetting)
41 {
42         efx_mcdi_req_t req;
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);
46         efx_word_t flags;
47         efx_rc_t rc;
48         unsigned int i;
49         unsigned int entries_num;
50
51         if (etcp == NULL)
52                 entries_num = 0;
53         else
54                 entries_num = etcp->etc_udp_entries_num;
55
56         req.emr_cmd = MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS;
57         req.emr_in_buf = payload;
58         req.emr_in_length =
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;
62
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));
68
69         MCDI_IN_SET_WORD(req, SET_TUNNEL_ENCAP_UDP_PORTS_IN_NUM_ENTRIES,
70             entries_num);
71
72         for (i = 0; i < entries_num; ++i) {
73                 uint16_t mcdi_udp_protocol;
74
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;
78                         break;
79                 case EFX_TUNNEL_PROTOCOL_GENEVE:
80                         mcdi_udp_protocol = TUNNEL_ENCAP_UDP_PORT_ENTRY_GENEVE;
81                         break;
82                 default:
83                         rc = EINVAL;
84                         goto fail1;
85                 }
86
87                 /*
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.
91                  */
92                 EFX_STATIC_ASSERT(sizeof (efx_dword_t) ==
93                     TUNNEL_ENCAP_UDP_PORT_ENTRY_LEN);
94                 EFX_POPULATE_DWORD_2(
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,
100                     mcdi_udp_protocol);
101         }
102
103         efx_mcdi_execute(enp, &req);
104
105         if (req.emr_rc != 0) {
106                 rc = req.emr_rc;
107                 goto fail2;
108         }
109
110         if (req.emr_out_length_used !=
111             MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_LEN) {
112                 rc = EMSGSIZE;
113                 goto fail3;
114         }
115
116         *resetting = MCDI_OUT_WORD_FIELD(req,
117             SET_TUNNEL_ENCAP_UDP_PORTS_OUT_FLAGS,
118             SET_TUNNEL_ENCAP_UDP_PORTS_OUT_RESETTING);
119
120         return (0);
121
122 fail3:
123         EFSYS_PROBE(fail3);
124
125 fail2:
126         EFSYS_PROBE(fail2);
127
128 fail1:
129         EFSYS_PROBE1(fail1, efx_rc_t, rc);
130
131         return (rc);
132 }
133
134         __checkReturn   efx_rc_t
135 efx_tunnel_init(
136         __in            efx_nic_t *enp)
137 {
138         efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
139         const efx_tunnel_ops_t *etop;
140         efx_rc_t rc;
141
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));
145
146         EFX_STATIC_ASSERT(EFX_TUNNEL_MAXNENTRIES ==
147             MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_ENTRIES_MAXNUM);
148
149         switch (enp->en_family) {
150 #if EFSYS_OPT_SIENA
151         case EFX_FAMILY_SIENA:
152                 etop = &__efx_tunnel_dummy_ops;
153                 break;
154 #endif /* EFSYS_OPT_SIENA */
155
156 #if EFSYS_OPT_HUNTINGTON
157         case EFX_FAMILY_HUNTINGTON:
158                 etop = &__efx_tunnel_dummy_ops;
159                 break;
160 #endif /* EFSYS_OPT_HUNTINGTON */
161
162 #if EFSYS_OPT_MEDFORD
163         case EFX_FAMILY_MEDFORD:
164                 etop = &__efx_tunnel_ef10_ops;
165                 break;
166 #endif /* EFSYS_OPT_MEDFORD */
167
168 #if EFSYS_OPT_MEDFORD2
169         case EFX_FAMILY_MEDFORD2:
170                 etop = &__efx_tunnel_ef10_ops;
171                 break;
172 #endif /* EFSYS_OPT_MEDFORD2 */
173
174 #if EFSYS_OPT_RIVERHEAD
175         case EFX_FAMILY_RIVERHEAD:
176                 etop = &__efx_tunnel_dummy_ops;
177                 break;
178 #endif /* EFSYS_OPT_RIVERHEAD */
179
180         default:
181                 EFSYS_ASSERT(0);
182                 rc = ENOTSUP;
183                 goto fail1;
184         }
185
186         memset(etcp->etc_udp_entries, 0, sizeof (etcp->etc_udp_entries));
187         etcp->etc_udp_entries_num = 0;
188
189         enp->en_etop = etop;
190         enp->en_mod_flags |= EFX_MOD_TUNNEL;
191
192         return (0);
193
194 fail1:
195         EFSYS_PROBE1(fail1, efx_rc_t, rc);
196
197         enp->en_etop = NULL;
198         enp->en_mod_flags &= ~EFX_MOD_TUNNEL;
199
200         return (rc);
201 }
202
203                         void
204 efx_tunnel_fini(
205         __in            efx_nic_t *enp)
206 {
207         boolean_t resetting;
208
209         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
210         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
211         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TUNNEL);
212
213         if ((enp->en_etop->eto_udp_encap_supported != NULL) &&
214             enp->en_etop->eto_udp_encap_supported(enp)) {
215                 /*
216                  * The UNLOADING flag allows the MC to suppress the datapath
217                  * reset if it was set on the last call to
218                  * MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS by all functions
219                  */
220                 (void) efx_mcdi_set_tunnel_encap_udp_ports(enp, NULL, B_TRUE,
221                     &resetting);
222         }
223
224         enp->en_etop = NULL;
225         enp->en_mod_flags &= ~EFX_MOD_TUNNEL;
226 }
227
228 static  __checkReturn   efx_rc_t
229 efx_tunnel_config_find_udp_tunnel_entry(
230         __in            efx_tunnel_cfg_t *etcp,
231         __in            uint16_t port,
232         __out           unsigned int *entryp)
233 {
234         unsigned int i;
235
236         for (i = 0; i < etcp->etc_udp_entries_num; ++i) {
237                 efx_tunnel_udp_entry_t *p = &etcp->etc_udp_entries[i];
238
239                 if (p->etue_port == port) {
240                         *entryp = i;
241                         return (0);
242                 }
243         }
244
245         return (ENOENT);
246 }
247
248         __checkReturn   efx_rc_t
249 efx_tunnel_config_udp_add(
250         __in            efx_nic_t *enp,
251         __in            uint16_t port /* host/cpu-endian */,
252         __in            efx_tunnel_protocol_t protocol)
253 {
254         const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
255         efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
256         efsys_lock_state_t state;
257         efx_rc_t rc;
258         unsigned int entry;
259
260         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TUNNEL);
261
262         if (protocol >= EFX_TUNNEL_NPROTOS) {
263                 rc = EINVAL;
264                 goto fail1;
265         }
266
267         if ((encp->enc_tunnel_encapsulations_supported &
268             (1u << protocol)) == 0) {
269                 rc = ENOTSUP;
270                 goto fail2;
271         }
272
273         EFSYS_LOCK(enp->en_eslp, state);
274
275         rc = efx_tunnel_config_find_udp_tunnel_entry(etcp, port, &entry);
276         if (rc == 0) {
277                 rc = EEXIST;
278                 goto fail3;
279         }
280
281         if (etcp->etc_udp_entries_num ==
282             encp->enc_tunnel_config_udp_entries_max) {
283                 rc = ENOSPC;
284                 goto fail4;
285         }
286
287         etcp->etc_udp_entries[etcp->etc_udp_entries_num].etue_port = port;
288         etcp->etc_udp_entries[etcp->etc_udp_entries_num].etue_protocol =
289             protocol;
290
291         etcp->etc_udp_entries_num++;
292
293         EFSYS_UNLOCK(enp->en_eslp, state);
294
295         return (0);
296
297 fail4:
298         EFSYS_PROBE(fail4);
299
300 fail3:
301         EFSYS_PROBE(fail3);
302         EFSYS_UNLOCK(enp->en_eslp, state);
303
304 fail2:
305         EFSYS_PROBE(fail2);
306
307 fail1:
308         EFSYS_PROBE1(fail1, efx_rc_t, rc);
309
310         return (rc);
311 }
312
313         __checkReturn   efx_rc_t
314 efx_tunnel_config_udp_remove(
315         __in            efx_nic_t *enp,
316         __in            uint16_t port /* host/cpu-endian */,
317         __in            efx_tunnel_protocol_t protocol)
318 {
319         efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
320         efsys_lock_state_t state;
321         unsigned int entry;
322         efx_rc_t rc;
323
324         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TUNNEL);
325
326         EFSYS_LOCK(enp->en_eslp, state);
327
328         rc = efx_tunnel_config_find_udp_tunnel_entry(etcp, port, &entry);
329         if (rc != 0)
330                 goto fail1;
331
332         if (etcp->etc_udp_entries[entry].etue_protocol != protocol) {
333                 rc = EINVAL;
334                 goto fail2;
335         }
336
337         EFSYS_ASSERT3U(etcp->etc_udp_entries_num, >, 0);
338         etcp->etc_udp_entries_num--;
339
340         if (entry < etcp->etc_udp_entries_num) {
341                 memmove(&etcp->etc_udp_entries[entry],
342                     &etcp->etc_udp_entries[entry + 1],
343                     (etcp->etc_udp_entries_num - entry) *
344                     sizeof (etcp->etc_udp_entries[0]));
345         }
346
347         memset(&etcp->etc_udp_entries[etcp->etc_udp_entries_num], 0,
348             sizeof (etcp->etc_udp_entries[0]));
349
350         EFSYS_UNLOCK(enp->en_eslp, state);
351
352         return (0);
353
354 fail2:
355         EFSYS_PROBE(fail2);
356
357 fail1:
358         EFSYS_PROBE1(fail1, efx_rc_t, rc);
359         EFSYS_UNLOCK(enp->en_eslp, state);
360
361         return (rc);
362 }
363
364                         void
365 efx_tunnel_config_clear(
366         __in                    efx_nic_t *enp)
367 {
368         efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
369         efsys_lock_state_t state;
370
371         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TUNNEL);
372
373         EFSYS_LOCK(enp->en_eslp, state);
374
375         etcp->etc_udp_entries_num = 0;
376         memset(etcp->etc_udp_entries, 0, sizeof (etcp->etc_udp_entries));
377
378         EFSYS_UNLOCK(enp->en_eslp, state);
379 }
380
381         __checkReturn   efx_rc_t
382 efx_tunnel_reconfigure(
383         __in            efx_nic_t *enp)
384 {
385         const efx_tunnel_ops_t *etop = enp->en_etop;
386         efx_rc_t rc;
387
388         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TUNNEL);
389
390         if (etop->eto_reconfigure == NULL) {
391                 rc = ENOTSUP;
392                 goto fail1;
393         }
394
395         if ((rc = enp->en_etop->eto_reconfigure(enp)) != 0)
396                 goto fail2;
397
398         return (0);
399
400 fail2:
401         EFSYS_PROBE(fail2);
402
403 fail1:
404         EFSYS_PROBE1(fail1, efx_rc_t, rc);
405
406         return (rc);
407 }
408
409 #if EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
410 static  __checkReturn           boolean_t
411 ef10_udp_encap_supported(
412         __in            efx_nic_t *enp)
413 {
414         const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
415         uint32_t udp_tunnels_mask = 0;
416
417         udp_tunnels_mask |= (1u << EFX_TUNNEL_PROTOCOL_VXLAN);
418         udp_tunnels_mask |= (1u << EFX_TUNNEL_PROTOCOL_GENEVE);
419
420         return ((encp->enc_tunnel_encapsulations_supported &
421             udp_tunnels_mask) == 0 ? B_FALSE : B_TRUE);
422 }
423
424 static  __checkReturn   efx_rc_t
425 ef10_tunnel_reconfigure(
426         __in            efx_nic_t *enp)
427 {
428         efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
429         efx_rc_t rc;
430         boolean_t resetting = B_FALSE;
431         efsys_lock_state_t state;
432         efx_tunnel_cfg_t etc;
433
434         EFSYS_LOCK(enp->en_eslp, state);
435         memcpy(&etc, etcp, sizeof (etc));
436         EFSYS_UNLOCK(enp->en_eslp, state);
437
438         if (ef10_udp_encap_supported(enp) == B_FALSE) {
439                 /*
440                  * It is OK to apply empty UDP tunnel ports when UDP
441                  * tunnel encapsulations are not supported - just nothing
442                  * should be done.
443                  */
444                 if (etc.etc_udp_entries_num == 0)
445                         return (0);
446                 rc = ENOTSUP;
447                 goto fail1;
448         } else {
449                 /*
450                  * All PCI functions can see a reset upon the
451                  * MCDI request completion
452                  */
453                 rc = efx_mcdi_set_tunnel_encap_udp_ports(enp, &etc, B_FALSE,
454                     &resetting);
455                 if (rc != 0) {
456                         /*
457                          * Do not fail if the access is denied when no
458                          * tunnel encap UDP ports are configured.
459                          */
460                         if (rc != EACCES || etc.etc_udp_entries_num != 0)
461                                 goto fail2;
462                 }
463
464                 /*
465                  * Although the caller should be able to handle MC reboot,
466                  * it might come in handy to report the impending reboot
467                  * by returning EAGAIN
468                  */
469                 return ((resetting) ? EAGAIN : 0);
470         }
471 fail2:
472         EFSYS_PROBE(fail2);
473
474 fail1:
475         EFSYS_PROBE1(fail1, efx_rc_t, rc);
476
477         return (rc);
478 }
479 #endif /* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
480
481 #endif /* EFSYS_OPT_TUNNEL */