1 /* SPDX-License-Identifier: BSD-3-Clause
3 * 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 */
28 #endif /* EFSYS_OPT_SIENA */
30 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
31 static const efx_evb_ops_t __efx_evb_ef10_ops = {
32 ef10_evb_init, /* eeo_init */
33 ef10_evb_fini, /* eeo_fini */
34 ef10_evb_vswitch_alloc, /* eeo_vswitch_alloc */
35 ef10_evb_vswitch_free, /* eeo_vswitch_free */
36 ef10_evb_vport_alloc, /* eeo_vport_alloc */
37 ef10_evb_vport_free, /* eeo_vport_free */
38 ef10_evb_vport_mac_addr_add, /* eeo_vport_mac_addr_add */
39 ef10_evb_vport_mac_addr_del, /* eeo_vport_mac_addr_del */
40 ef10_evb_vadaptor_alloc, /* eeo_vadaptor_alloc */
41 ef10_evb_vadaptor_free, /* eeo_vadaptor_free */
42 ef10_evb_vport_assign, /* eeo_vport_assign */
43 ef10_evb_vport_reconfigure, /* eeo_vport_reconfigure */
45 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
47 __checkReturn efx_rc_t
51 const efx_evb_ops_t *eeop;
53 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
55 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
56 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
57 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EVB));
59 switch (enp->en_family) {
61 case EFX_FAMILY_SIENA:
62 eeop = &__efx_evb_dummy_ops;
64 #endif /* EFSYS_OPT_SIENA */
66 #if EFSYS_OPT_HUNTINGTON
67 case EFX_FAMILY_HUNTINGTON:
68 eeop = &__efx_evb_ef10_ops;
70 #endif /* EFSYS_OPT_HUNTINGTON */
73 case EFX_FAMILY_MEDFORD:
74 eeop = &__efx_evb_ef10_ops;
76 #endif /* EFSYS_OPT_MEDFORD */
78 #if EFSYS_OPT_MEDFORD2
79 case EFX_FAMILY_MEDFORD2:
80 eeop = &__efx_evb_ef10_ops;
82 #endif /* EFSYS_OPT_MEDFORD2 */
90 if (!encp->enc_datapath_cap_evb || !eeop->eeo_init) {
95 if ((rc = eeop->eeo_init(enp)) != 0)
99 enp->en_mod_flags |= EFX_MOD_EVB;
107 EFSYS_PROBE1(fail1, efx_rc_t, rc);
116 const efx_evb_ops_t *eeop = enp->en_eeop;
118 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
119 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
120 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
121 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
123 if (eeop && eeop->eeo_fini)
127 enp->en_mod_flags &= ~EFX_MOD_EVB;
131 * efx_is_zero_eth_addr returns TRUE if the passed MAC address has all bytes
132 * equal to zero. A vport is assigned a MAC address after creation and this
133 * function checks if that has happened. It is called in the clean-up function
134 * before calling eeo_vport_mac_addr_del to ensure that the vport actually had
135 * an allocated MAC address.
138 __checkReturn boolean_t
139 efx_is_zero_eth_addr(
140 __in_bcount(EFX_MAC_ADDR_LEN) const uint8_t *addrp)
142 return (!(addrp[0] | addrp[1] | addrp[2] |
143 addrp[3] | addrp[4] | addrp[5]));
149 __in efx_vswitch_id_t vswitch_id,
150 __inout efx_vport_config_t *configp)
152 const efx_evb_ops_t *eeop = enp->en_eeop;
154 /* If any callback fails, continue clean-up with others functions */
155 if (EFX_VPORT_PCI_FUNCTION_IS_PF(configp)) {
157 if ((configp->evc_vport_id != EFX_VPORT_ID_INVALID) &&
158 (eeop->eeo_vadaptor_free(enp, vswitch_id,
159 configp->evc_vport_id) != 0)) {
160 EFSYS_PROBE2(eeo_vadaptor_free,
161 uint16_t, configp->evc_function,
162 uint32_t, configp->evc_vport_id);
165 if (configp->evc_vport_assigned == B_TRUE) {
166 if (eeop->eeo_vport_assign(enp, vswitch_id,
168 configp->evc_function) != 0) {
169 EFSYS_PROBE1(eeo_vport_assign,
170 uint16_t, configp->evc_function);
172 configp->evc_vport_assigned = B_FALSE;
177 * Call eeo_vport_mac_addr_del after checking that this vport is
178 * actually allocated a MAC address in call to efx_evb_configure_vport
180 if (!efx_is_zero_eth_addr(configp->evc_mac_addr)) {
181 if (eeop->eeo_vport_mac_addr_del(enp, vswitch_id,
182 configp->evc_vport_id,
183 configp->evc_mac_addr) != 0) {
184 EFSYS_PROBE1(eeo_vport_mac_addr_del,
185 uint16_t, configp->evc_function);
187 memset(configp->evc_mac_addr, 0x00, EFX_MAC_ADDR_LEN);
190 if (configp->evc_vport_id != EFX_VPORT_ID_INVALID) {
191 if (eeop->eeo_vport_free(enp, vswitch_id,
192 configp->evc_vport_id) != 0) {
193 EFSYS_PROBE1(eeo_vport_free,
194 uint16_t, configp->evc_function);
196 configp->evc_vport_id = EFX_VPORT_ID_INVALID;
203 __in efx_vswitch_id_t vswitch_id,
204 __in uint32_t num_vports,
205 __inout_ecount(num_vports) efx_vport_config_t *vport_configp)
207 efx_vport_config_t *configp;
210 if (vport_configp == NULL) {
211 EFSYS_PROBE(null_vport_config);
215 for (i = 0; i < num_vports; i++) {
216 configp = vport_configp + i;
217 efx_evb_free_vport(enp, vswitch_id, configp);
221 static __checkReturn efx_rc_t
222 efx_evb_configure_vport(
224 __in efx_vswitch_id_t vswitch_id,
225 __in const efx_evb_ops_t *eeop,
226 __inout efx_vport_config_t *configp)
229 efx_vport_id_t vport_id;
231 if ((rc = eeop->eeo_vport_alloc(enp, vswitch_id,
232 EFX_VPORT_TYPE_NORMAL, configp->evc_vid,
233 configp->evc_vlan_restrict, &vport_id)) != 0)
236 configp->evc_vport_id = vport_id;
238 if ((rc = eeop->eeo_vport_mac_addr_add(enp, vswitch_id,
239 configp->evc_vport_id,
240 configp->evc_mac_addr)) != 0)
243 if (EFX_VPORT_PCI_FUNCTION_IS_PF(configp)) {
244 if ((rc = eeop->eeo_vadaptor_alloc(enp, vswitch_id,
245 configp->evc_vport_id)) != 0)
248 if ((rc = eeop->eeo_vport_assign(enp, vswitch_id,
249 configp->evc_vport_id,
250 configp->evc_function)) != 0)
252 configp->evc_vport_assigned = B_TRUE;
264 EFSYS_PROBE1(fail1, efx_rc_t, rc);
269 __checkReturn efx_rc_t
270 efx_evb_vswitch_create(
272 __in uint32_t num_vports,
273 __inout_ecount(num_vports) efx_vport_config_t *vport_configp,
274 __deref_out efx_vswitch_t **evpp)
278 efx_vswitch_id_t vswitch_id;
279 efx_vport_config_t *configp;
280 const efx_evb_ops_t *eeop = enp->en_eeop;
283 /* vport_configp is a caller allocated array filled in with vports
284 * configuration. Index 0 carries the PF vport configuration and next
285 * num_vports - 1 indices carry VFs configuration.
287 EFSYS_ASSERT((num_vports != 0) && (vport_configp != NULL) &&
289 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
290 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
292 if ((eeop->eeo_vswitch_alloc == NULL) ||
293 (eeop->eeo_vport_alloc == NULL) ||
294 (eeop->eeo_vport_free == NULL) ||
295 (eeop->eeo_vport_mac_addr_add == NULL) ||
296 (eeop->eeo_vport_mac_addr_del == NULL) ||
297 (eeop->eeo_vadaptor_alloc == NULL) ||
298 (eeop->eeo_vadaptor_free == NULL) ||
299 (eeop->eeo_vport_assign == NULL) ||
300 (eeop->eeo_vswitch_free == NULL)) {
305 /* Allocate a vSwitch object */
306 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_vswitch_t), evp);
313 if ((rc = eeop->eeo_vswitch_alloc(enp, &vswitch_id)) != 0)
317 evp->ev_num_vports = num_vports;
318 evp->ev_evcp = vport_configp;
319 evp->ev_vswitch_id = vswitch_id;
321 for (i = 0; i < num_vports; i++) {
322 configp = vport_configp + i;
324 if ((rc = efx_evb_configure_vport(enp, vswitch_id, eeop,
329 enp->en_vswitchp = evp;
335 efx_evb_free_vports(enp, vswitch_id, i + 1, vport_configp);
336 /* Free the vSwitch */
337 eeop->eeo_vswitch_free(enp, vswitch_id);
341 /* Free the vSwitch object */
342 EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp);
348 EFSYS_PROBE1(fail1, efx_rc_t, rc);
353 __checkReturn efx_rc_t
354 efx_evb_vport_mac_set(
356 __in efx_vswitch_t *evp,
357 __in efx_vport_id_t vport_id,
358 __in_bcount(EFX_MAC_ADDR_LEN) uint8_t *addrp)
360 const efx_evb_ops_t *eeop = enp->en_eeop;
363 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
365 if (eeop->eeo_vport_reconfigure == NULL) {
375 rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
387 EFSYS_PROBE1(fail1, efx_rc_t, rc);
391 __checkReturn efx_rc_t
392 efx_evb_vport_vlan_set(
394 __in efx_vswitch_t *evp,
395 __in efx_vport_id_t vport_id,
398 const efx_evb_ops_t *eeop = enp->en_eeop;
401 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
403 if (eeop->eeo_vport_reconfigure == NULL) {
408 rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
418 EFSYS_PROBE1(fail1, efx_rc_t, rc);
422 __checkReturn efx_rc_t
425 __in efx_vswitch_t *evp,
426 __in efx_vport_id_t vport_id,
427 __in_bcount(EFX_MAC_ADDR_LEN) uint8_t *addrp,
429 __out boolean_t *is_fn_resetp)
431 const efx_evb_ops_t *eeop = enp->en_eeop;
434 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
436 if (eeop->eeo_vport_reconfigure == NULL) {
441 if (is_fn_resetp == NULL) {
446 rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
447 &vid, addrp, is_fn_resetp);
458 EFSYS_PROBE1(fail1, efx_rc_t, rc);
461 __checkReturn efx_rc_t
462 efx_evb_vswitch_destroy(
464 __in efx_vswitch_t *evp)
466 const efx_evb_ops_t *eeop = enp->en_eeop;
467 efx_vswitch_id_t vswitch_id;
470 EFSYS_ASSERT(evp != NULL);
471 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
473 if ((eeop->eeo_vport_mac_addr_del == NULL) ||
474 (eeop->eeo_vadaptor_free == NULL) ||
475 (eeop->eeo_vport_assign == NULL) ||
476 (eeop->eeo_vport_free == NULL) ||
477 (eeop->eeo_vswitch_free == NULL)) {
482 vswitch_id = evp->ev_vswitch_id;
483 efx_evb_free_vports(enp, vswitch_id,
484 evp->ev_num_vports, evp->ev_evcp);
486 /* Free the vSwitch object */
487 EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp);
488 enp->en_vswitchp = NULL;
490 /* Free the vSwitch */
491 if ((rc = eeop->eeo_vswitch_free(enp, vswitch_id)) != 0)
500 EFSYS_PROBE1(fail1, efx_rc_t, rc);