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 */
27 #endif /* EFSYS_OPT_SIENA */
29 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
30 static const efx_evb_ops_t __efx_evb_ef10_ops = {
31 ef10_evb_init, /* eeo_init */
32 ef10_evb_fini, /* eeo_fini */
33 ef10_evb_vswitch_alloc, /* eeo_vswitch_alloc */
34 ef10_evb_vswitch_free, /* eeo_vswitch_free */
35 ef10_evb_vport_alloc, /* eeo_vport_alloc */
36 ef10_evb_vport_free, /* eeo_vport_free */
37 ef10_evb_vport_mac_addr_add, /* eeo_vport_mac_addr_add */
38 ef10_evb_vport_mac_addr_del, /* eeo_vport_mac_addr_del */
39 ef10_evb_vadaptor_alloc, /* eeo_vadaptor_alloc */
40 ef10_evb_vadaptor_free, /* eeo_vadaptor_free */
41 ef10_evb_vport_assign, /* eeo_vport_assign */
43 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
45 __checkReturn efx_rc_t
49 const efx_evb_ops_t *eeop;
51 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
53 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
54 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
55 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EVB));
57 switch (enp->en_family) {
59 case EFX_FAMILY_SIENA:
60 eeop = &__efx_evb_dummy_ops;
62 #endif /* EFSYS_OPT_SIENA */
64 #if EFSYS_OPT_HUNTINGTON
65 case EFX_FAMILY_HUNTINGTON:
66 eeop = &__efx_evb_ef10_ops;
68 #endif /* EFSYS_OPT_HUNTINGTON */
71 case EFX_FAMILY_MEDFORD:
72 eeop = &__efx_evb_ef10_ops;
74 #endif /* EFSYS_OPT_MEDFORD */
76 #if EFSYS_OPT_MEDFORD2
77 case EFX_FAMILY_MEDFORD2:
78 eeop = &__efx_evb_ef10_ops;
80 #endif /* EFSYS_OPT_MEDFORD2 */
88 if (!encp->enc_datapath_cap_evb || !eeop->eeo_init) {
93 if ((rc = eeop->eeo_init(enp)) != 0)
97 enp->en_mod_flags |= EFX_MOD_EVB;
105 EFSYS_PROBE1(fail1, efx_rc_t, rc);
114 const efx_evb_ops_t *eeop = enp->en_eeop;
116 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
117 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
118 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
119 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
121 if (eeop && eeop->eeo_fini)
125 enp->en_mod_flags &= ~EFX_MOD_EVB;
129 * efx_is_zero_eth_addr returns TRUE if the passed MAC address has all bytes
130 * equal to zero. A vport is assigned a MAC address after creation and this
131 * function checks if that has happened. It is called in the clean-up function
132 * before calling eeo_vport_mac_addr_del to ensure that the vport actually had
133 * an allocated MAC address.
136 __checkReturn boolean_t
137 efx_is_zero_eth_addr(
138 __in_bcount(EFX_MAC_ADDR_LEN) const uint8_t *addrp)
140 return (!(addrp[0] | addrp[1] | addrp[2] |
141 addrp[3] | addrp[4] | addrp[5]));
147 __in efx_vswitch_id_t vswitch_id,
148 __inout efx_vport_config_t *configp)
150 const efx_evb_ops_t *eeop = enp->en_eeop;
152 /* If any callback fails, continue clean-up with others functions */
153 if (EFX_VPORT_PCI_FUNCTION_IS_PF(configp)) {
155 if ((configp->evc_vport_id != EFX_VPORT_ID_INVALID) &&
156 (eeop->eeo_vadaptor_free(enp, vswitch_id,
157 configp->evc_vport_id) != 0)) {
158 EFSYS_PROBE2(eeo_vadaptor_free,
159 uint16_t, configp->evc_function,
160 uint32_t, configp->evc_vport_id);
163 if (configp->evc_vport_assigned == B_TRUE) {
164 if (eeop->eeo_vport_assign(enp, vswitch_id,
166 configp->evc_function) != 0) {
167 EFSYS_PROBE1(eeo_vport_assign,
168 uint16_t, configp->evc_function);
170 configp->evc_vport_assigned = B_FALSE;
175 * Call eeo_vport_mac_addr_del after checking that this vport is
176 * actually allocated a MAC address in call to efx_evb_configure_vport
178 if (!efx_is_zero_eth_addr(configp->evc_mac_addr)) {
179 if (eeop->eeo_vport_mac_addr_del(enp, vswitch_id,
180 configp->evc_vport_id,
181 configp->evc_mac_addr) != 0) {
182 EFSYS_PROBE1(eeo_vport_mac_addr_del,
183 uint16_t, configp->evc_function);
185 memset(configp->evc_mac_addr, 0x00, EFX_MAC_ADDR_LEN);
188 if (configp->evc_vport_id != EFX_VPORT_ID_INVALID) {
189 if (eeop->eeo_vport_free(enp, vswitch_id,
190 configp->evc_vport_id) != 0) {
191 EFSYS_PROBE1(eeo_vport_free,
192 uint16_t, configp->evc_function);
194 configp->evc_vport_id = EFX_VPORT_ID_INVALID;
201 __in efx_vswitch_id_t vswitch_id,
202 __in uint32_t num_vports,
203 __inout_ecount(num_vports) efx_vport_config_t *vport_configp)
205 efx_vport_config_t *configp;
208 if (vport_configp == NULL) {
209 EFSYS_PROBE(null_vport_config);
213 for (i = 0; i < num_vports; i++) {
214 configp = vport_configp + i;
215 efx_evb_free_vport(enp, vswitch_id, configp);
219 static __checkReturn efx_rc_t
220 efx_evb_configure_vport(
222 __in efx_vswitch_id_t vswitch_id,
223 __in const efx_evb_ops_t *eeop,
224 __inout efx_vport_config_t *configp)
227 efx_vport_id_t vport_id;
229 if ((rc = eeop->eeo_vport_alloc(enp, vswitch_id,
230 EFX_VPORT_TYPE_NORMAL, configp->evc_vid,
231 configp->evc_vlan_restrict, &vport_id)) != 0)
234 configp->evc_vport_id = vport_id;
236 if ((rc = eeop->eeo_vport_mac_addr_add(enp, vswitch_id,
237 configp->evc_vport_id,
238 configp->evc_mac_addr)) != 0)
241 if (EFX_VPORT_PCI_FUNCTION_IS_PF(configp)) {
242 if ((rc = eeop->eeo_vadaptor_alloc(enp, vswitch_id,
243 configp->evc_vport_id)) != 0)
246 if ((rc = eeop->eeo_vport_assign(enp, vswitch_id,
247 configp->evc_vport_id,
248 configp->evc_function)) != 0)
250 configp->evc_vport_assigned = B_TRUE;
262 EFSYS_PROBE1(fail1, efx_rc_t, rc);
267 __checkReturn efx_rc_t
268 efx_evb_vswitch_create(
270 __in uint32_t num_vports,
271 __inout_ecount(num_vports) efx_vport_config_t *vport_configp,
272 __deref_out efx_vswitch_t **evpp)
276 efx_vswitch_id_t vswitch_id;
277 efx_vport_config_t *configp;
278 const efx_evb_ops_t *eeop = enp->en_eeop;
281 /* vport_configp is a caller allocated array filled in with vports
282 * configuration. Index 0 carries the PF vport configuration and next
283 * num_vports - 1 indices carry VFs configuration.
285 EFSYS_ASSERT((num_vports != 0) && (vport_configp != NULL) &&
287 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
288 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
290 if ((eeop->eeo_vswitch_alloc == NULL) ||
291 (eeop->eeo_vport_alloc == NULL) ||
292 (eeop->eeo_vport_free == NULL) ||
293 (eeop->eeo_vport_mac_addr_add == NULL) ||
294 (eeop->eeo_vport_mac_addr_del == NULL) ||
295 (eeop->eeo_vadaptor_alloc == NULL) ||
296 (eeop->eeo_vadaptor_free == NULL) ||
297 (eeop->eeo_vport_assign == NULL) ||
298 (eeop->eeo_vswitch_free == NULL)) {
303 /* Allocate a vSwitch object */
304 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_vswitch_t), evp);
311 if ((rc = eeop->eeo_vswitch_alloc(enp, &vswitch_id)) != 0)
315 evp->ev_num_vports = num_vports;
316 evp->ev_evcp = vport_configp;
317 evp->ev_vswitch_id = vswitch_id;
319 for (i = 0; i < num_vports; i++) {
320 configp = vport_configp + i;
322 if ((rc = efx_evb_configure_vport(enp, vswitch_id, eeop,
327 enp->en_vswitchp = evp;
333 efx_evb_free_vports(enp, vswitch_id, i + 1, vport_configp);
334 /* Free the vSwitch */
335 eeop->eeo_vswitch_free(enp, vswitch_id);
339 /* Free the vSwitch object */
340 EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp);
346 EFSYS_PROBE1(fail1, efx_rc_t, rc);
352 __checkReturn efx_rc_t
353 efx_evb_vswitch_destroy(
355 __in efx_vswitch_t *evp)
357 const efx_evb_ops_t *eeop = enp->en_eeop;
358 efx_vswitch_id_t vswitch_id;
361 EFSYS_ASSERT(evp != NULL);
362 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
364 if ((eeop->eeo_vport_mac_addr_del == NULL) ||
365 (eeop->eeo_vadaptor_free == NULL) ||
366 (eeop->eeo_vport_assign == NULL) ||
367 (eeop->eeo_vport_free == NULL) ||
368 (eeop->eeo_vswitch_free == NULL)) {
373 vswitch_id = evp->ev_vswitch_id;
374 efx_evb_free_vports(enp, vswitch_id,
375 evp->ev_num_vports, evp->ev_evcp);
377 /* Free the vSwitch object */
378 EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp);
379 enp->en_vswitchp = NULL;
381 /* Free the vSwitch */
382 if ((rc = eeop->eeo_vswitch_free(enp, vswitch_id)) != 0)
391 EFSYS_PROBE1(fail1, efx_rc_t, rc);