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 */
27 NULL, /* eeo_vport_stats */
29 #endif /* EFSYS_OPT_SIENA */
31 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
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 /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
49 __checkReturn efx_rc_t
53 const efx_evb_ops_t *eeop;
55 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
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));
61 switch (enp->en_family) {
63 case EFX_FAMILY_SIENA:
64 eeop = &__efx_evb_dummy_ops;
66 #endif /* EFSYS_OPT_SIENA */
68 #if EFSYS_OPT_HUNTINGTON
69 case EFX_FAMILY_HUNTINGTON:
70 eeop = &__efx_evb_ef10_ops;
72 #endif /* EFSYS_OPT_HUNTINGTON */
75 case EFX_FAMILY_MEDFORD:
76 eeop = &__efx_evb_ef10_ops;
78 #endif /* EFSYS_OPT_MEDFORD */
80 #if EFSYS_OPT_MEDFORD2
81 case EFX_FAMILY_MEDFORD2:
82 eeop = &__efx_evb_ef10_ops;
84 #endif /* EFSYS_OPT_MEDFORD2 */
92 if (!encp->enc_datapath_cap_evb || !eeop->eeo_init) {
97 if ((rc = eeop->eeo_init(enp)) != 0)
101 enp->en_mod_flags |= EFX_MOD_EVB;
109 EFSYS_PROBE1(fail1, efx_rc_t, rc);
118 const efx_evb_ops_t *eeop = enp->en_eeop;
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));
125 if (eeop && eeop->eeo_fini)
129 enp->en_mod_flags &= ~EFX_MOD_EVB;
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.
140 __checkReturn boolean_t
141 efx_is_zero_eth_addr(
142 __in_bcount(EFX_MAC_ADDR_LEN) const uint8_t *addrp)
144 return (!(addrp[0] | addrp[1] | addrp[2] |
145 addrp[3] | addrp[4] | addrp[5]));
151 __in efx_vswitch_id_t vswitch_id,
152 __inout efx_vport_config_t *configp)
154 const efx_evb_ops_t *eeop = enp->en_eeop;
156 /* If any callback fails, continue clean-up with others functions */
157 if (EFX_VPORT_PCI_FUNCTION_IS_PF(configp)) {
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);
167 if (configp->evc_vport_assigned == B_TRUE) {
168 if (eeop->eeo_vport_assign(enp, vswitch_id,
170 configp->evc_function) != 0) {
171 EFSYS_PROBE1(eeo_vport_assign,
172 uint16_t, configp->evc_function);
174 configp->evc_vport_assigned = B_FALSE;
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
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);
189 memset(configp->evc_mac_addr, 0x00, EFX_MAC_ADDR_LEN);
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);
198 configp->evc_vport_id = EFX_VPORT_ID_INVALID;
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)
209 efx_vport_config_t *configp;
212 if (vport_configp == NULL) {
213 EFSYS_PROBE(null_vport_config);
217 for (i = 0; i < num_vports; i++) {
218 configp = vport_configp + i;
219 efx_evb_free_vport(enp, vswitch_id, configp);
223 static __checkReturn efx_rc_t
224 efx_evb_configure_vport(
226 __in efx_vswitch_id_t vswitch_id,
227 __in const efx_evb_ops_t *eeop,
228 __inout efx_vport_config_t *configp)
231 efx_vport_id_t vport_id;
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)
238 configp->evc_vport_id = vport_id;
240 if ((rc = eeop->eeo_vport_mac_addr_add(enp, vswitch_id,
241 configp->evc_vport_id,
242 configp->evc_mac_addr)) != 0)
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)
250 if ((rc = eeop->eeo_vport_assign(enp, vswitch_id,
251 configp->evc_vport_id,
252 configp->evc_function)) != 0)
254 configp->evc_vport_assigned = B_TRUE;
266 EFSYS_PROBE1(fail1, efx_rc_t, rc);
271 __checkReturn efx_rc_t
272 efx_evb_vswitch_create(
274 __in uint32_t num_vports,
275 __inout_ecount(num_vports) efx_vport_config_t *vport_configp,
276 __deref_out efx_vswitch_t **evpp)
280 efx_vswitch_id_t vswitch_id;
281 efx_vport_config_t *configp;
282 const efx_evb_ops_t *eeop = enp->en_eeop;
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.
289 EFSYS_ASSERT((num_vports != 0) && (vport_configp != NULL) &&
291 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
292 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
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)) {
307 /* Allocate a vSwitch object */
308 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_vswitch_t), evp);
315 if ((rc = eeop->eeo_vswitch_alloc(enp, &vswitch_id)) != 0)
319 evp->ev_num_vports = num_vports;
320 evp->ev_evcp = vport_configp;
321 evp->ev_vswitch_id = vswitch_id;
323 for (i = 0; i < num_vports; i++) {
324 configp = vport_configp + i;
326 if ((rc = efx_evb_configure_vport(enp, vswitch_id, eeop,
331 enp->en_vswitchp = evp;
337 efx_evb_free_vports(enp, vswitch_id, i + 1, vport_configp);
338 /* Free the vSwitch */
339 eeop->eeo_vswitch_free(enp, vswitch_id);
343 /* Free the vSwitch object */
344 EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp);
350 EFSYS_PROBE1(fail1, efx_rc_t, rc);
355 __checkReturn efx_rc_t
356 efx_evb_vport_mac_set(
358 __in efx_vswitch_t *evp,
359 __in efx_vport_id_t vport_id,
360 __in_bcount(EFX_MAC_ADDR_LEN) uint8_t *addrp)
362 const efx_evb_ops_t *eeop = enp->en_eeop;
365 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
367 if (eeop->eeo_vport_reconfigure == NULL) {
377 rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
389 EFSYS_PROBE1(fail1, efx_rc_t, rc);
393 __checkReturn efx_rc_t
394 efx_evb_vport_vlan_set(
396 __in efx_vswitch_t *evp,
397 __in efx_vport_id_t vport_id,
400 const efx_evb_ops_t *eeop = enp->en_eeop;
403 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
405 if (eeop->eeo_vport_reconfigure == NULL) {
410 rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
420 EFSYS_PROBE1(fail1, efx_rc_t, rc);
424 __checkReturn efx_rc_t
427 __in efx_vswitch_t *evp,
428 __in efx_vport_id_t vport_id,
429 __in_bcount(EFX_MAC_ADDR_LEN) uint8_t *addrp,
431 __out boolean_t *is_fn_resetp)
433 const efx_evb_ops_t *eeop = enp->en_eeop;
436 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
438 if (eeop->eeo_vport_reconfigure == NULL) {
443 if (is_fn_resetp == NULL) {
448 rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
449 &vid, addrp, is_fn_resetp);
460 EFSYS_PROBE1(fail1, efx_rc_t, rc);
463 __checkReturn efx_rc_t
464 efx_evb_vswitch_destroy(
466 __in efx_vswitch_t *evp)
468 const efx_evb_ops_t *eeop = enp->en_eeop;
469 efx_vswitch_id_t vswitch_id;
472 EFSYS_ASSERT(evp != NULL);
473 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
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)) {
484 vswitch_id = evp->ev_vswitch_id;
485 efx_evb_free_vports(enp, vswitch_id,
486 evp->ev_num_vports, evp->ev_evcp);
488 /* Free the vSwitch object */
489 EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp);
490 enp->en_vswitchp = NULL;
492 /* Free the vSwitch */
493 if ((rc = eeop->eeo_vswitch_free(enp, vswitch_id)) != 0)
502 EFSYS_PROBE1(fail1, efx_rc_t, rc);
506 __checkReturn efx_rc_t
509 __in efx_vswitch_t *evp,
510 __in efx_vport_id_t vport_id,
511 __out efsys_mem_t *stats_bufferp)
514 const efx_evb_ops_t *eeop = enp->en_eeop;
516 EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
518 if (eeop->eeo_vport_stats == NULL) {
523 if (stats_bufferp == NULL) {
528 rc = eeop->eeo_vport_stats(enp, evp->ev_vswitch_id,
529 vport_id, stats_bufferp);
540 EFSYS_PROBE1(fail1, efx_rc_t, rc);