1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright(c) 2019-2021 Xilinx, Inc.
4 * Copyright(c) 2018-2019 Solarflare Communications Inc.
14 static const efx_evb_ops_t __efx_evb_dummy_ops = {
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 */
29 #endif /* EFSYS_OPT_SIENA */
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 */
47 #endif /* EFX_OPTS_EF10() */
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 */
65 #endif /* EFSYS_OPT_RIVERHEAD */
67 __checkReturn efx_rc_t
71 const efx_evb_ops_t *eeop;
73 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
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));
79 switch (enp->en_family) {
81 case EFX_FAMILY_SIENA:
82 eeop = &__efx_evb_dummy_ops;
84 #endif /* EFSYS_OPT_SIENA */
86 #if EFSYS_OPT_HUNTINGTON
87 case EFX_FAMILY_HUNTINGTON:
88 eeop = &__efx_evb_ef10_ops;
90 #endif /* EFSYS_OPT_HUNTINGTON */
93 case EFX_FAMILY_MEDFORD:
94 eeop = &__efx_evb_ef10_ops;
96 #endif /* EFSYS_OPT_MEDFORD */
98 #if EFSYS_OPT_MEDFORD2
99 case EFX_FAMILY_MEDFORD2:
100 eeop = &__efx_evb_ef10_ops;
102 #endif /* EFSYS_OPT_MEDFORD2 */
104 #if EFSYS_OPT_RIVERHEAD
105 case EFX_FAMILY_RIVERHEAD:
106 eeop = &__efx_evb_rhead_ops;
108 #endif /* EFSYS_OPT_RIVERHEAD */
116 if (!encp->enc_datapath_cap_evb || !eeop->eeo_init) {
121 if ((rc = eeop->eeo_init(enp)) != 0)
125 enp->en_mod_flags |= EFX_MOD_EVB;
133 EFSYS_PROBE1(fail1, efx_rc_t, rc);
142 const efx_evb_ops_t *eeop = enp->en_eeop;
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));
149 if (eeop && eeop->eeo_fini)
153 enp->en_mod_flags &= ~EFX_MOD_EVB;
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.
164 __checkReturn boolean_t
165 efx_is_zero_eth_addr(
166 __in_bcount(EFX_MAC_ADDR_LEN) const uint8_t *addrp)
168 return (!(addrp[0] | addrp[1] | addrp[2] |
169 addrp[3] | addrp[4] | addrp[5]));
175 __in efx_vswitch_id_t vswitch_id,
176 __inout efx_vport_config_t *configp)
178 const efx_evb_ops_t *eeop = enp->en_eeop;
180 /* If any callback fails, continue clean-up with others functions */
181 if (EFX_VPORT_PCI_FUNCTION_IS_PF(configp)) {
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);
191 if (configp->evc_vport_assigned == B_TRUE) {
192 if (eeop->eeo_vport_assign(enp, vswitch_id,
194 configp->evc_function) != 0) {
195 EFSYS_PROBE1(eeo_vport_assign,
196 uint16_t, configp->evc_function);
198 configp->evc_vport_assigned = B_FALSE;
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
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);
213 memset(configp->evc_mac_addr, 0x00, EFX_MAC_ADDR_LEN);
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);
222 configp->evc_vport_id = EFX_VPORT_ID_INVALID;
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)
233 efx_vport_config_t *configp;
236 if (vport_configp == NULL) {
237 EFSYS_PROBE(null_vport_config);
241 for (i = 0; i < num_vports; i++) {
242 configp = vport_configp + i;
243 efx_evb_free_vport(enp, vswitch_id, configp);
247 static __checkReturn efx_rc_t
248 efx_evb_configure_vport(
250 __in efx_vswitch_id_t vswitch_id,
251 __in const efx_evb_ops_t *eeop,
252 __inout efx_vport_config_t *configp)
255 efx_vport_id_t vport_id;
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)
262 configp->evc_vport_id = vport_id;
264 if ((rc = eeop->eeo_vport_mac_addr_add(enp, vswitch_id,
265 configp->evc_vport_id,
266 configp->evc_mac_addr)) != 0)
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)
274 if ((rc = eeop->eeo_vport_assign(enp, vswitch_id,
275 configp->evc_vport_id,
276 configp->evc_function)) != 0)
278 configp->evc_vport_assigned = B_TRUE;
290 EFSYS_PROBE1(fail1, efx_rc_t, rc);
295 __checkReturn efx_rc_t
296 efx_evb_vswitch_create(
298 __in uint32_t num_vports,
299 __inout_ecount(num_vports) efx_vport_config_t *vport_configp,
300 __deref_out efx_vswitch_t **evpp)
304 efx_vswitch_id_t vswitch_id;
305 efx_vport_config_t *configp;
306 const efx_evb_ops_t *eeop = enp->en_eeop;
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.
313 EFSYS_ASSERT((num_vports != 0) && (vport_configp != NULL) &&
315 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
316 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
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)) {
331 /* Allocate a vSwitch object */
332 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_vswitch_t), evp);
339 if ((rc = eeop->eeo_vswitch_alloc(enp, &vswitch_id)) != 0)
343 evp->ev_num_vports = num_vports;
344 evp->ev_evcp = vport_configp;
345 evp->ev_vswitch_id = vswitch_id;
347 for (i = 0; i < num_vports; i++) {
348 configp = vport_configp + i;
350 if ((rc = efx_evb_configure_vport(enp, vswitch_id, eeop,
355 enp->en_vswitchp = evp;
361 efx_evb_free_vports(enp, vswitch_id, i + 1, vport_configp);
362 /* Free the vSwitch */
363 eeop->eeo_vswitch_free(enp, vswitch_id);
367 /* Free the vSwitch object */
368 EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp);
374 EFSYS_PROBE1(fail1, efx_rc_t, rc);
379 __checkReturn efx_rc_t
380 efx_evb_vport_mac_set(
382 __in efx_vswitch_t *evp,
383 __in efx_vport_id_t vport_id,
384 __in_bcount(EFX_MAC_ADDR_LEN) uint8_t *addrp)
386 const efx_evb_ops_t *eeop = enp->en_eeop;
389 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
391 if (eeop->eeo_vport_reconfigure == NULL) {
401 rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
413 EFSYS_PROBE1(fail1, efx_rc_t, rc);
417 __checkReturn efx_rc_t
418 efx_evb_vport_vlan_set(
420 __in efx_vswitch_t *evp,
421 __in efx_vport_id_t vport_id,
424 const efx_evb_ops_t *eeop = enp->en_eeop;
427 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
429 if (eeop->eeo_vport_reconfigure == NULL) {
434 rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
444 EFSYS_PROBE1(fail1, efx_rc_t, rc);
448 __checkReturn efx_rc_t
451 __in efx_vswitch_t *evp,
452 __in efx_vport_id_t vport_id,
453 __in_bcount(EFX_MAC_ADDR_LEN) uint8_t *addrp,
455 __out boolean_t *is_fn_resetp)
457 const efx_evb_ops_t *eeop = enp->en_eeop;
460 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
462 if (eeop->eeo_vport_reconfigure == NULL) {
467 if (is_fn_resetp == NULL) {
472 rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
473 &vid, addrp, is_fn_resetp);
484 EFSYS_PROBE1(fail1, efx_rc_t, rc);
487 __checkReturn efx_rc_t
488 efx_evb_vswitch_destroy(
490 __in efx_vswitch_t *evp)
492 const efx_evb_ops_t *eeop = enp->en_eeop;
493 efx_vswitch_id_t vswitch_id;
496 EFSYS_ASSERT(evp != NULL);
497 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
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)) {
508 vswitch_id = evp->ev_vswitch_id;
509 efx_evb_free_vports(enp, vswitch_id,
510 evp->ev_num_vports, evp->ev_evcp);
512 /* Free the vSwitch object */
513 EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp);
514 enp->en_vswitchp = NULL;
516 /* Free the vSwitch */
517 if ((rc = eeop->eeo_vswitch_free(enp, vswitch_id)) != 0)
526 EFSYS_PROBE1(fail1, efx_rc_t, rc);
530 __checkReturn efx_rc_t
533 __in efx_vswitch_t *evp,
534 __in efx_vport_id_t vport_id,
535 __out efsys_mem_t *stats_bufferp)
538 const efx_evb_ops_t *eeop = enp->en_eeop;
540 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
542 if (eeop->eeo_vport_stats == NULL) {
547 if (stats_bufferp == NULL) {
552 rc = eeop->eeo_vport_stats(enp, evp->ev_vswitch_id,
553 vport_id, stats_bufferp);
564 EFSYS_PROBE1(fail1, efx_rc_t, rc);