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