X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fbase%2Fefx_evb.c;h=27b466f8b5ad20db81d4fdafbf5cc1e4720efcc2;hb=05fa170a2b0760295cb0af687cb1c56c1e6d06ea;hp=f235252493d37a87032b458853929421ab9ea0fa;hpb=4f12e20c85dce289668ef0ff61295fdebeb14b7d;p=dpdk.git diff --git a/drivers/net/sfc/base/efx_evb.c b/drivers/net/sfc/base/efx_evb.c index f235252493..27b466f8b5 100644 --- a/drivers/net/sfc/base/efx_evb.c +++ b/drivers/net/sfc/base/efx_evb.c @@ -14,13 +14,31 @@ static const efx_evb_ops_t __efx_evb_dummy_ops = { NULL, /* eeo_init */ NULL, /* eeo_fini */ + NULL, /* eeo_vswitch_alloc */ + NULL, /* eeo_vswitch_free */ + NULL, /* eeo_vport_alloc */ + NULL, /* eeo_vport_free */ + NULL, /* eeo_vport_mac_addr_add */ + NULL, /* eeo_vport_mac_addr_del */ + NULL, /* eeo_vadaptor_alloc */ + NULL, /* eeo_vadaptor_free */ + NULL, /* eeo_vport_assign */ }; #endif /* EFSYS_OPT_SIENA */ #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 static const efx_evb_ops_t __efx_evb_ef10_ops = { - ef10_evb_init, /* eeo_init */ - ef10_evb_fini, /* eeo_fini */ + ef10_evb_init, /* eeo_init */ + ef10_evb_fini, /* eeo_fini */ + ef10_evb_vswitch_alloc, /* eeo_vswitch_alloc */ + ef10_evb_vswitch_free, /* eeo_vswitch_free */ + ef10_evb_vport_alloc, /* eeo_vport_alloc */ + ef10_evb_vport_free, /* eeo_vport_free */ + ef10_evb_vport_mac_addr_add, /* eeo_vport_mac_addr_add */ + ef10_evb_vport_mac_addr_del, /* eeo_vport_mac_addr_del */ + ef10_evb_vadaptor_alloc, /* eeo_vadaptor_alloc */ + ef10_evb_vadaptor_free, /* eeo_vadaptor_free */ + ef10_evb_vport_assign, /* eeo_vport_assign */ }; #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */ @@ -107,4 +125,271 @@ efx_evb_fini( enp->en_mod_flags &= ~EFX_MOD_EVB; } +/* + * efx_is_zero_eth_addr returns TRUE if the passed MAC address has all bytes + * equal to zero. A vport is assigned a MAC address after creation and this + * function checks if that has happened. It is called in the clean-up function + * before calling eeo_vport_mac_addr_del to ensure that the vport actually had + * an allocated MAC address. + */ + +__checkReturn boolean_t +efx_is_zero_eth_addr( + __in_bcount(EFX_MAC_ADDR_LEN) const uint8_t *addrp) +{ + return (!(addrp[0] | addrp[1] | addrp[2] | + addrp[3] | addrp[4] | addrp[5])); +} + +static void +efx_evb_free_vport( + __in efx_nic_t *enp, + __in efx_vswitch_id_t vswitch_id, + __inout efx_vport_config_t *configp) +{ + const efx_evb_ops_t *eeop = enp->en_eeop; + + /* If any callback fails, continue clean-up with others functions */ + if (EFX_VPORT_PCI_FUNCTION_IS_PF(configp)) { + /* free vadaptor */ + if ((configp->evc_vport_id != EFX_VPORT_ID_INVALID) && + (eeop->eeo_vadaptor_free(enp, vswitch_id, + configp->evc_vport_id) != 0)) { + EFSYS_PROBE2(eeo_vadaptor_free, + uint16_t, configp->evc_function, + uint32_t, configp->evc_vport_id); + } + } else { + if (configp->evc_vport_assigned == B_TRUE) { + if (eeop->eeo_vport_assign(enp, vswitch_id, + EVB_PORT_ID_NULL, + configp->evc_function) != 0) { + EFSYS_PROBE1(eeo_vport_assign, + uint16_t, configp->evc_function); + } + configp->evc_vport_assigned = B_FALSE; + } + } + + /* + * Call eeo_vport_mac_addr_del after checking that this vport is + * actually allocated a MAC address in call to efx_evb_configure_vport + */ + if (!efx_is_zero_eth_addr(configp->evc_mac_addr)) { + if (eeop->eeo_vport_mac_addr_del(enp, vswitch_id, + configp->evc_vport_id, + configp->evc_mac_addr) != 0) { + EFSYS_PROBE1(eeo_vport_mac_addr_del, + uint16_t, configp->evc_function); + } + memset(configp->evc_mac_addr, 0x00, EFX_MAC_ADDR_LEN); + } + + if (configp->evc_vport_id != EFX_VPORT_ID_INVALID) { + if (eeop->eeo_vport_free(enp, vswitch_id, + configp->evc_vport_id) != 0) { + EFSYS_PROBE1(eeo_vport_free, + uint16_t, configp->evc_function); + } + configp->evc_vport_id = EFX_VPORT_ID_INVALID; + } +} + +static void +efx_evb_free_vports( + __in efx_nic_t *enp, + __in efx_vswitch_id_t vswitch_id, + __in uint32_t num_vports, + __inout_ecount(num_vports) efx_vport_config_t *vport_configp) +{ + efx_vport_config_t *configp; + uint32_t i; + + if (vport_configp == NULL) { + EFSYS_PROBE(null_vport_config); + return; + } + + for (i = 0; i < num_vports; i++) { + configp = vport_configp + i; + efx_evb_free_vport(enp, vswitch_id, configp); + } +} + +static __checkReturn efx_rc_t +efx_evb_configure_vport( + __in efx_nic_t *enp, + __in efx_vswitch_id_t vswitch_id, + __in const efx_evb_ops_t *eeop, + __inout efx_vport_config_t *configp) +{ + efx_rc_t rc; + efx_vport_id_t vport_id; + + if ((rc = eeop->eeo_vport_alloc(enp, vswitch_id, + EFX_VPORT_TYPE_NORMAL, configp->evc_vid, + configp->evc_vlan_restrict, &vport_id)) != 0) + goto fail1; + + configp->evc_vport_id = vport_id; + + if ((rc = eeop->eeo_vport_mac_addr_add(enp, vswitch_id, + configp->evc_vport_id, + configp->evc_mac_addr)) != 0) + goto fail2; + + if (EFX_VPORT_PCI_FUNCTION_IS_PF(configp)) { + if ((rc = eeop->eeo_vadaptor_alloc(enp, vswitch_id, + configp->evc_vport_id)) != 0) + goto fail3; + } else { + if ((rc = eeop->eeo_vport_assign(enp, vswitch_id, + configp->evc_vport_id, + configp->evc_function)) != 0) + goto fail4; + configp->evc_vport_assigned = B_TRUE; + } + + return (0); + +fail4: + EFSYS_PROBE(fail4); +fail3: + EFSYS_PROBE(fail3); +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + __checkReturn efx_rc_t +efx_evb_vswitch_create( + __in efx_nic_t *enp, + __in uint32_t num_vports, + __inout_ecount(num_vports) efx_vport_config_t *vport_configp, + __deref_out efx_vswitch_t **evpp) +{ + efx_vswitch_t *evp; + efx_rc_t rc; + efx_vswitch_id_t vswitch_id; + efx_vport_config_t *configp; + const efx_evb_ops_t *eeop = enp->en_eeop; + uint32_t i; + + /* vport_configp is a caller allocated array filled in with vports + * configuration. Index 0 carries the PF vport configuration and next + * num_vports - 1 indices carry VFs configuration. + */ + EFSYS_ASSERT((num_vports != 0) && (vport_configp != NULL) && + (evpp != NULL)); + EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB); + EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC)); + + if ((eeop->eeo_vswitch_alloc == NULL) || + (eeop->eeo_vport_alloc == NULL) || + (eeop->eeo_vport_free == NULL) || + (eeop->eeo_vport_mac_addr_add == NULL) || + (eeop->eeo_vport_mac_addr_del == NULL) || + (eeop->eeo_vadaptor_alloc == NULL) || + (eeop->eeo_vadaptor_free == NULL) || + (eeop->eeo_vport_assign == NULL) || + (eeop->eeo_vswitch_free == NULL)) { + rc = ENOTSUP; + goto fail1; + } + + /* Allocate a vSwitch object */ + EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_vswitch_t), evp); + + if (evp == NULL) { + rc = ENOMEM; + goto fail2; + } + + if ((rc = eeop->eeo_vswitch_alloc(enp, &vswitch_id)) != 0) + goto fail3; + + evp->ev_enp = enp; + evp->ev_num_vports = num_vports; + evp->ev_evcp = vport_configp; + evp->ev_vswitch_id = vswitch_id; + + for (i = 0; i < num_vports; i++) { + configp = vport_configp + i; + + if ((rc = efx_evb_configure_vport(enp, vswitch_id, eeop, + configp)) != 0) + goto fail4; + } + + enp->en_vswitchp = evp; + *evpp = evp; + return (0); + +fail4: + EFSYS_PROBE(fail4); + efx_evb_free_vports(enp, vswitch_id, i + 1, vport_configp); + /* Free the vSwitch */ + eeop->eeo_vswitch_free(enp, vswitch_id); + +fail3: + EFSYS_PROBE(fail3); + /* Free the vSwitch object */ + EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp); + +fail2: + EFSYS_PROBE(fail2); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + + __checkReturn efx_rc_t +efx_evb_vswitch_destroy( + __in efx_nic_t *enp, + __in efx_vswitch_t *evp) +{ + const efx_evb_ops_t *eeop = enp->en_eeop; + efx_vswitch_id_t vswitch_id; + efx_rc_t rc; + + EFSYS_ASSERT(evp != NULL); + EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB); + + if ((eeop->eeo_vport_mac_addr_del == NULL) || + (eeop->eeo_vadaptor_free == NULL) || + (eeop->eeo_vport_assign == NULL) || + (eeop->eeo_vport_free == NULL) || + (eeop->eeo_vswitch_free == NULL)) { + rc = ENOTSUP; + goto fail1; + } + + vswitch_id = evp->ev_vswitch_id; + efx_evb_free_vports(enp, vswitch_id, + evp->ev_num_vports, evp->ev_evcp); + + /* Free the vSwitch object */ + EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp); + enp->en_vswitchp = NULL; + + /* Free the vSwitch */ + if ((rc = eeop->eeo_vswitch_free(enp, vswitch_id)) != 0) + goto fail2; + + return (0); + +fail2: + EFSYS_PROBE(fail2); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + return (rc); +} + #endif