common/sfc_efx: update copyright year
[dpdk.git] / drivers / common / sfc_efx / base / efx_evb.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019-2021 Xilinx, Inc.
4  * Copyright(c) 2018-2019 Solarflare Communications Inc.
5  */
6
7 #include "efx.h"
8 #include "efx_impl.h"
9
10
11 #if EFSYS_OPT_EVB
12
13 #if EFSYS_OPT_SIENA
14 static const efx_evb_ops_t      __efx_evb_dummy_ops = {
15         NULL,           /* eeo_init */
16         NULL,           /* eeo_fini */
17         NULL,           /* eeo_vswitch_alloc */
18         NULL,           /* eeo_vswitch_free */
19         NULL,           /* eeo_vport_alloc */
20         NULL,           /* eeo_vport_free */
21         NULL,           /* eeo_vport_mac_addr_add */
22         NULL,           /* eeo_vport_mac_addr_del */
23         NULL,           /* eeo_vadaptor_alloc */
24         NULL,           /* eeo_vadaptor_free */
25         NULL,           /* eeo_vport_assign */
26         NULL,           /* eeo_vport_reconfigure */
27         NULL,           /* eeo_vport_stats */
28 };
29 #endif /* EFSYS_OPT_SIENA */
30
31 #if EFX_OPTS_EF10()
32 static const efx_evb_ops_t      __efx_evb_ef10_ops = {
33         ef10_evb_init,                  /* eeo_init */
34         ef10_evb_fini,                  /* eeo_fini */
35         ef10_evb_vswitch_alloc,         /* eeo_vswitch_alloc */
36         ef10_evb_vswitch_free,          /* eeo_vswitch_free */
37         ef10_evb_vport_alloc,           /* eeo_vport_alloc */
38         ef10_evb_vport_free,            /* eeo_vport_free */
39         ef10_evb_vport_mac_addr_add,    /* eeo_vport_mac_addr_add */
40         ef10_evb_vport_mac_addr_del,    /* eeo_vport_mac_addr_del */
41         ef10_evb_vadaptor_alloc,        /* eeo_vadaptor_alloc */
42         ef10_evb_vadaptor_free,         /* eeo_vadaptor_free */
43         ef10_evb_vport_assign,          /* eeo_vport_assign */
44         ef10_evb_vport_reconfigure,     /* eeo_vport_reconfigure */
45         ef10_evb_vport_stats,           /* eeo_vport_stats */
46 };
47 #endif /* EFX_OPTS_EF10() */
48
49 #if EFSYS_OPT_RIVERHEAD
50 static const efx_evb_ops_t      __efx_evb_rhead_ops = {
51         ef10_evb_init,                  /* eeo_init */
52         ef10_evb_fini,                  /* eeo_fini */
53         ef10_evb_vswitch_alloc,         /* eeo_vswitch_alloc */
54         ef10_evb_vswitch_free,          /* eeo_vswitch_free */
55         ef10_evb_vport_alloc,           /* eeo_vport_alloc */
56         ef10_evb_vport_free,            /* eeo_vport_free */
57         ef10_evb_vport_mac_addr_add,    /* eeo_vport_mac_addr_add */
58         ef10_evb_vport_mac_addr_del,    /* eeo_vport_mac_addr_del */
59         ef10_evb_vadaptor_alloc,        /* eeo_vadaptor_alloc */
60         ef10_evb_vadaptor_free,         /* eeo_vadaptor_free */
61         ef10_evb_vport_assign,          /* eeo_vport_assign */
62         ef10_evb_vport_reconfigure,     /* eeo_vport_reconfigure */
63         ef10_evb_vport_stats,           /* eeo_vport_stats */
64 };
65 #endif /* EFSYS_OPT_RIVERHEAD */
66
67         __checkReturn   efx_rc_t
68 efx_evb_init(
69         __in            efx_nic_t *enp)
70 {
71         const efx_evb_ops_t *eeop;
72         efx_rc_t rc;
73         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
74
75         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
76         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
77         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EVB));
78
79         switch (enp->en_family) {
80 #if EFSYS_OPT_SIENA
81         case EFX_FAMILY_SIENA:
82                 eeop = &__efx_evb_dummy_ops;
83                 break;
84 #endif /* EFSYS_OPT_SIENA */
85
86 #if EFSYS_OPT_HUNTINGTON
87         case EFX_FAMILY_HUNTINGTON:
88                 eeop = &__efx_evb_ef10_ops;
89                 break;
90 #endif /* EFSYS_OPT_HUNTINGTON */
91
92 #if EFSYS_OPT_MEDFORD
93         case EFX_FAMILY_MEDFORD:
94                 eeop = &__efx_evb_ef10_ops;
95                 break;
96 #endif /* EFSYS_OPT_MEDFORD */
97
98 #if EFSYS_OPT_MEDFORD2
99         case EFX_FAMILY_MEDFORD2:
100                 eeop = &__efx_evb_ef10_ops;
101                 break;
102 #endif /* EFSYS_OPT_MEDFORD2 */
103
104 #if EFSYS_OPT_RIVERHEAD
105         case EFX_FAMILY_RIVERHEAD:
106                 eeop = &__efx_evb_rhead_ops;
107                 break;
108 #endif /* EFSYS_OPT_RIVERHEAD */
109
110         default:
111                 EFSYS_ASSERT(0);
112                 rc = ENOTSUP;
113                 goto fail1;
114         }
115
116         if (!encp->enc_datapath_cap_evb || !eeop->eeo_init) {
117                 rc = ENOTSUP;
118                 goto fail2;
119         }
120
121         if ((rc = eeop->eeo_init(enp)) != 0)
122                 goto fail3;
123
124         enp->en_eeop = eeop;
125         enp->en_mod_flags |= EFX_MOD_EVB;
126         return (0);
127
128 fail3:
129         EFSYS_PROBE(fail3);
130 fail2:
131         EFSYS_PROBE(fail2);
132 fail1:
133         EFSYS_PROBE1(fail1, efx_rc_t, rc);
134
135         return (rc);
136 }
137
138                         void
139 efx_evb_fini(
140         __in            efx_nic_t *enp)
141 {
142         const efx_evb_ops_t *eeop = enp->en_eeop;
143
144         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
145         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
146         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
147         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
148
149         if (eeop && eeop->eeo_fini)
150                 eeop->eeo_fini(enp);
151
152         enp->en_eeop = NULL;
153         enp->en_mod_flags &= ~EFX_MOD_EVB;
154 }
155
156 /*
157  * efx_is_zero_eth_addr returns TRUE if the passed MAC address has all bytes
158  * equal to zero. A vport is assigned a MAC address after creation and this
159  * function checks if that has happened. It is called in the clean-up function
160  * before calling eeo_vport_mac_addr_del to ensure that the vport actually had
161  * an allocated MAC address.
162  */
163
164 __checkReturn                           boolean_t
165 efx_is_zero_eth_addr(
166         __in_bcount(EFX_MAC_ADDR_LEN)   const uint8_t *addrp)
167 {
168         return (!(addrp[0] | addrp[1] | addrp[2] |
169                 addrp[3] | addrp[4] | addrp[5]));
170 }
171
172 static                  void
173 efx_evb_free_vport(
174         __in            efx_nic_t *enp,
175         __in            efx_vswitch_id_t vswitch_id,
176         __inout         efx_vport_config_t *configp)
177 {
178         const efx_evb_ops_t *eeop = enp->en_eeop;
179
180         /* If any callback fails, continue clean-up with others functions */
181         if (EFX_VPORT_PCI_FUNCTION_IS_PF(configp)) {
182                 /* free vadaptor */
183                 if ((configp->evc_vport_id != EFX_VPORT_ID_INVALID) &&
184                     (eeop->eeo_vadaptor_free(enp, vswitch_id,
185                     configp->evc_vport_id) != 0)) {
186                         EFSYS_PROBE2(eeo_vadaptor_free,
187                             uint16_t, configp->evc_function,
188                             uint32_t, configp->evc_vport_id);
189                 }
190         } else {
191                 if (configp->evc_vport_assigned == B_TRUE) {
192                         if (eeop->eeo_vport_assign(enp, vswitch_id,
193                             EVB_PORT_ID_NULL,
194                             configp->evc_function) != 0) {
195                                 EFSYS_PROBE1(eeo_vport_assign,
196                                     uint16_t, configp->evc_function);
197                         }
198                         configp->evc_vport_assigned = B_FALSE;
199                 }
200         }
201
202         /*
203          * Call eeo_vport_mac_addr_del after checking that this vport is
204          * actually allocated a MAC address in call to efx_evb_configure_vport
205          */
206         if (!efx_is_zero_eth_addr(configp->evc_mac_addr)) {
207                 if (eeop->eeo_vport_mac_addr_del(enp, vswitch_id,
208                     configp->evc_vport_id,
209                     configp->evc_mac_addr) != 0) {
210                         EFSYS_PROBE1(eeo_vport_mac_addr_del,
211                             uint16_t, configp->evc_function);
212                 }
213                 memset(configp->evc_mac_addr, 0x00, EFX_MAC_ADDR_LEN);
214         }
215
216         if (configp->evc_vport_id != EFX_VPORT_ID_INVALID) {
217                 if (eeop->eeo_vport_free(enp, vswitch_id,
218                     configp->evc_vport_id) != 0) {
219                         EFSYS_PROBE1(eeo_vport_free,
220                             uint16_t, configp->evc_function);
221                 }
222                 configp->evc_vport_id = EFX_VPORT_ID_INVALID;
223         }
224 }
225
226 static                                  void
227 efx_evb_free_vports(
228         __in                            efx_nic_t *enp,
229         __in                            efx_vswitch_id_t vswitch_id,
230         __in                            uint32_t num_vports,
231         __inout_ecount(num_vports)      efx_vport_config_t *vport_configp)
232 {
233         efx_vport_config_t *configp;
234         uint32_t i;
235
236         if (vport_configp == NULL) {
237                 EFSYS_PROBE(null_vport_config);
238                 return;
239         }
240
241         for (i = 0; i < num_vports; i++) {
242                 configp = vport_configp + i;
243                 efx_evb_free_vport(enp, vswitch_id, configp);
244         }
245 }
246
247 static  __checkReturn   efx_rc_t
248 efx_evb_configure_vport(
249         __in            efx_nic_t *enp,
250         __in            efx_vswitch_id_t vswitch_id,
251         __in            const efx_evb_ops_t *eeop,
252         __inout         efx_vport_config_t *configp)
253 {
254         efx_rc_t rc;
255         efx_vport_id_t vport_id;
256
257         if ((rc = eeop->eeo_vport_alloc(enp, vswitch_id,
258                         EFX_VPORT_TYPE_NORMAL, configp->evc_vid,
259                         configp->evc_vlan_restrict, &vport_id)) != 0)
260                 goto fail1;
261
262         configp->evc_vport_id = vport_id;
263
264         if ((rc = eeop->eeo_vport_mac_addr_add(enp, vswitch_id,
265                         configp->evc_vport_id,
266                         configp->evc_mac_addr)) != 0)
267                 goto fail2;
268
269         if (EFX_VPORT_PCI_FUNCTION_IS_PF(configp)) {
270                 if ((rc = eeop->eeo_vadaptor_alloc(enp, vswitch_id,
271                                 configp->evc_vport_id)) != 0)
272                         goto fail3;
273         } else {
274                 if ((rc = eeop->eeo_vport_assign(enp, vswitch_id,
275                                 configp->evc_vport_id,
276                                 configp->evc_function)) != 0)
277                         goto fail4;
278                 configp->evc_vport_assigned = B_TRUE;
279         }
280
281         return (0);
282
283 fail4:
284         EFSYS_PROBE(fail4);
285 fail3:
286         EFSYS_PROBE(fail3);
287 fail2:
288         EFSYS_PROBE(fail2);
289 fail1:
290         EFSYS_PROBE1(fail1, efx_rc_t, rc);
291
292         return (rc);
293 }
294
295         __checkReturn                   efx_rc_t
296 efx_evb_vswitch_create(
297         __in                            efx_nic_t *enp,
298         __in                            uint32_t num_vports,
299         __inout_ecount(num_vports)      efx_vport_config_t *vport_configp,
300         __deref_out                     efx_vswitch_t **evpp)
301 {
302         efx_vswitch_t *evp;
303         efx_rc_t rc;
304         efx_vswitch_id_t vswitch_id;
305         efx_vport_config_t *configp;
306         const efx_evb_ops_t *eeop = enp->en_eeop;
307         uint32_t i;
308
309         /* vport_configp is a caller allocated array filled in with vports
310          * configuration. Index 0 carries the PF vport configuration and next
311          * num_vports - 1 indices carry VFs configuration.
312          */
313         EFSYS_ASSERT((num_vports != 0) && (vport_configp != NULL) &&
314                 (evpp != NULL));
315         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
316         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
317
318         if ((eeop->eeo_vswitch_alloc == NULL) ||
319             (eeop->eeo_vport_alloc == NULL) ||
320             (eeop->eeo_vport_free == NULL) ||
321             (eeop->eeo_vport_mac_addr_add == NULL) ||
322             (eeop->eeo_vport_mac_addr_del == NULL) ||
323             (eeop->eeo_vadaptor_alloc == NULL) ||
324             (eeop->eeo_vadaptor_free == NULL) ||
325             (eeop->eeo_vport_assign == NULL) ||
326             (eeop->eeo_vswitch_free == NULL)) {
327                 rc = ENOTSUP;
328                 goto fail1;
329         }
330
331         /* Allocate a vSwitch object */
332         EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_vswitch_t), evp);
333
334         if (evp == NULL) {
335                 rc = ENOMEM;
336                 goto fail2;
337         }
338
339         if ((rc = eeop->eeo_vswitch_alloc(enp, &vswitch_id)) != 0)
340                 goto fail3;
341
342         evp->ev_enp = enp;
343         evp->ev_num_vports = num_vports;
344         evp->ev_evcp = vport_configp;
345         evp->ev_vswitch_id = vswitch_id;
346
347         for (i = 0; i < num_vports; i++) {
348                 configp = vport_configp + i;
349
350                 if ((rc = efx_evb_configure_vport(enp, vswitch_id, eeop,
351                                 configp)) != 0)
352                         goto fail4;
353         }
354
355         enp->en_vswitchp = evp;
356         *evpp = evp;
357         return (0);
358
359 fail4:
360         EFSYS_PROBE(fail4);
361         efx_evb_free_vports(enp, vswitch_id, i + 1, vport_configp);
362         /* Free the vSwitch */
363         eeop->eeo_vswitch_free(enp, vswitch_id);
364
365 fail3:
366         EFSYS_PROBE(fail3);
367         /* Free the vSwitch object */
368         EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp);
369
370 fail2:
371         EFSYS_PROBE(fail2);
372
373 fail1:
374         EFSYS_PROBE1(fail1, efx_rc_t, rc);
375
376         return (rc);
377 }
378
379         __checkReturn                   efx_rc_t
380 efx_evb_vport_mac_set(
381         __in                            efx_nic_t *enp,
382         __in                            efx_vswitch_t *evp,
383         __in                            efx_vport_id_t vport_id,
384         __in_bcount(EFX_MAC_ADDR_LEN)   uint8_t *addrp)
385 {
386         const efx_evb_ops_t *eeop = enp->en_eeop;
387         efx_rc_t rc;
388
389         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
390
391         if (eeop->eeo_vport_reconfigure == NULL) {
392                 rc = ENOTSUP;
393                 goto fail1;
394         }
395
396         if (addrp == NULL) {
397                 rc = EINVAL;
398                 goto fail2;
399         }
400
401         rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
402                 NULL, addrp, NULL);
403         if (rc != 0)
404                 goto fail3;
405
406         return (0);
407
408 fail3:
409         EFSYS_PROBE(fail3);
410 fail2:
411         EFSYS_PROBE(fail2);
412 fail1:
413         EFSYS_PROBE1(fail1, efx_rc_t, rc);
414         return (rc);
415 }
416
417         __checkReturn   efx_rc_t
418 efx_evb_vport_vlan_set(
419         __in            efx_nic_t *enp,
420         __in            efx_vswitch_t *evp,
421         __in            efx_vport_id_t vport_id,
422         __in            uint16_t vid)
423 {
424         const efx_evb_ops_t *eeop = enp->en_eeop;
425         efx_rc_t rc;
426
427         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
428
429         if (eeop->eeo_vport_reconfigure == NULL) {
430                 rc = ENOTSUP;
431                 goto fail1;
432         }
433
434         rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
435                 &vid, NULL, NULL);
436         if (rc != 0)
437                 goto fail2;
438
439         return (0);
440
441 fail2:
442         EFSYS_PROBE(fail2);
443 fail1:
444         EFSYS_PROBE1(fail1, efx_rc_t, rc);
445         return (rc);
446 }
447
448         __checkReturn                   efx_rc_t
449 efx_evb_vport_reset(
450         __in                            efx_nic_t *enp,
451         __in                            efx_vswitch_t *evp,
452         __in                            efx_vport_id_t vport_id,
453         __in_bcount(EFX_MAC_ADDR_LEN)   uint8_t *addrp,
454         __in                            uint16_t vid,
455         __out                           boolean_t *is_fn_resetp)
456 {
457         const efx_evb_ops_t *eeop = enp->en_eeop;
458         efx_rc_t rc;
459
460         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
461
462         if (eeop->eeo_vport_reconfigure == NULL) {
463                 rc = ENOTSUP;
464                 goto fail1;
465         }
466
467         if (is_fn_resetp == NULL) {
468                 rc = EINVAL;
469                 goto fail2;
470         }
471
472         rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
473                 &vid, addrp, is_fn_resetp);
474         if (rc != 0)
475                 goto fail3;
476
477         return (0);
478
479 fail3:
480         EFSYS_PROBE(fail3);
481 fail2:
482         EFSYS_PROBE(fail2);
483 fail1:
484         EFSYS_PROBE1(fail1, efx_rc_t, rc);
485         return (rc);
486 }
487         __checkReturn   efx_rc_t
488 efx_evb_vswitch_destroy(
489         __in            efx_nic_t *enp,
490         __in            efx_vswitch_t *evp)
491 {
492         const efx_evb_ops_t *eeop = enp->en_eeop;
493         efx_vswitch_id_t vswitch_id;
494         efx_rc_t rc;
495
496         EFSYS_ASSERT(evp != NULL);
497         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
498
499         if ((eeop->eeo_vport_mac_addr_del == NULL) ||
500             (eeop->eeo_vadaptor_free == NULL) ||
501             (eeop->eeo_vport_assign == NULL) ||
502             (eeop->eeo_vport_free == NULL) ||
503             (eeop->eeo_vswitch_free == NULL)) {
504                 rc = ENOTSUP;
505                 goto fail1;
506         }
507
508         vswitch_id  = evp->ev_vswitch_id;
509         efx_evb_free_vports(enp, vswitch_id,
510                 evp->ev_num_vports, evp->ev_evcp);
511
512         /* Free the vSwitch object */
513         EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp);
514         enp->en_vswitchp = NULL;
515
516         /* Free the vSwitch */
517         if ((rc = eeop->eeo_vswitch_free(enp, vswitch_id)) != 0)
518                 goto fail2;
519
520         return (0);
521
522 fail2:
523         EFSYS_PROBE(fail2);
524
525 fail1:
526         EFSYS_PROBE1(fail1, efx_rc_t, rc);
527         return (rc);
528 }
529
530         __checkReturn   efx_rc_t
531 efx_evb_vport_stats(
532         __in            efx_nic_t *enp,
533         __in            efx_vswitch_t *evp,
534         __in            efx_vport_id_t vport_id,
535         __out           efsys_mem_t *stats_bufferp)
536 {
537         efx_rc_t rc;
538         const efx_evb_ops_t *eeop = enp->en_eeop;
539
540         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
541
542         if (eeop->eeo_vport_stats == NULL) {
543                 rc = ENOTSUP;
544                 goto fail1;
545         }
546
547         if (stats_bufferp == NULL) {
548                 rc = EINVAL;
549                 goto fail2;
550         }
551
552         rc = eeop->eeo_vport_stats(enp, evp->ev_vswitch_id,
553                 vport_id, stats_bufferp);
554         if (rc != 0)
555                 goto fail3;
556
557         return (0);
558
559 fail3:
560         EFSYS_PROBE(fail3);
561 fail2:
562         EFSYS_PROBE(fail2);
563 fail1:
564         EFSYS_PROBE1(fail1, efx_rc_t, rc);
565         return (rc);
566 }
567
568 #endif