/* On top of the default firmware vswitch setup, create a VEB vswitch and * expansion vport for use by this function.
*/ int efx_ef10_vswitching_probe_pf(struct efx_nic *efx)
{ struct efx_ef10_nic_data *nic_data = efx->nic_data; struct net_device *net_dev = efx->net_dev; int rc;
if (pci_sriov_get_totalvfs(efx->pci_dev) <= 0) { /* vswitch not needed as we have no VFs */
efx_ef10_vadaptor_alloc_set_features(efx); return 0;
}
rc = efx_ef10_vswitch_alloc(efx, EVB_PORT_ID_ASSIGNED,
MC_CMD_VSWITCH_ALLOC_IN_VSWITCH_TYPE_VEB); if (rc) goto fail1;
/* Disable SRIOV and remove VFs * If some VFs are attached to a guest (using Xen, only) nothing is * done if force=false, and vports are freed if force=true (for the non * attachedc ones, only) but SRIOV is not disabled and VFs are not * removed in either case.
*/ staticint efx_ef10_pci_sriov_disable(struct efx_nic *efx, bool force)
{ struct pci_dev *dev = efx->pci_dev; struct efx_ef10_nic_data *nic_data = efx->nic_data; unsignedint vfs_assigned = pci_vfs_assigned(dev); int i, rc = 0;
if (vfs_assigned && !force) {
netif_info(efx, drv, efx->net_dev, "VFs are assigned to guests; " "please detach them before disabling SR-IOV\n"); return -EBUSY;
}
if (!vfs_assigned) { for (i = 0; i < efx->vf_count; i++)
nic_data->vf[i].pci_dev = NULL;
pci_disable_sriov(dev);
} else {
rc = -EBUSY;
}
if (!nic_data->vf) { /* Remove any un-assigned orphaned VFs. This can happen if the PF driver * was unloaded while any VF was assigned to a guest (using Xen, only).
*/ if (pci_num_vf(efx->pci_dev) && !pci_vfs_assigned(efx->pci_dev))
pci_disable_sriov(efx->pci_dev); return;
}
/* Disable SRIOV and remove any VFs in the host */
rc = efx_ef10_pci_sriov_disable(efx, true); if (rc)
netif_dbg(efx, drv, efx->net_dev, "Disabling SRIOV was not successful rc=%d\n", rc); else
netif_dbg(efx, drv, efx->net_dev, "SRIOV disabled\n");
}
if (vf->efx) {
efx_device_detach_sync(vf->efx);
efx_net_stop(vf->efx->net_dev);
vf->efx->type->filter_table_remove(vf->efx);
rc = efx_ef10_vadaptor_free(vf->efx, EVB_PORT_ID_ASSIGNED); if (rc) return rc;
}
rc = efx_ef10_evb_port_assign(efx, EVB_PORT_ID_NULL, vf_i); if (rc) return rc;
if (!is_zero_ether_addr(vf->mac)) {
rc = efx_ef10_vport_del_vf_mac(efx, vf->vport_id, vf->mac); if (rc) return rc;
}
if (!is_zero_ether_addr(mac)) {
rc = efx_ef10_vport_add_mac(efx, vf->vport_id, mac); if (rc) goto fail;
if (vf->efx)
eth_hw_addr_set(vf->efx->net_dev, mac);
}
ether_addr_copy(vf->mac, mac);
rc = efx_ef10_evb_port_assign(efx, vf->vport_id, vf_i); if (rc) goto fail;
if (vf->efx) { /* VF cannot use the vport_id that the PF created */
rc = efx_ef10_vadaptor_alloc(vf->efx, EVB_PORT_ID_ASSIGNED); if (rc) return rc;
vf->efx->type->filter_table_probe(vf->efx);
efx_net_open(vf->efx->net_dev);
efx_device_attach_if_not_resetting(vf->efx);
}
return 0;
fail:
eth_zero_addr(vf->mac); return rc;
}
int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan,
u8 qos)
{ struct efx_ef10_nic_data *nic_data = efx->nic_data; struct ef10_vf *vf;
u16 new_vlan; int rc = 0, rc2 = 0;
if (vf_i >= efx->vf_count) return -EINVAL; if (qos != 0) return -EINVAL;
rc = efx_ef10_vadaptor_free(vf->efx, EVB_PORT_ID_ASSIGNED); if (rc) goto restore_filters;
}
if (vf->vport_assigned) {
rc = efx_ef10_evb_port_assign(efx, EVB_PORT_ID_NULL, vf_i); if (rc) {
netif_warn(efx, drv, efx->net_dev, "Failed to change vlan on VF %d.\n", vf_i);
netif_warn(efx, drv, efx->net_dev, "This is likely because the VF is bound to a driver in a VM.\n");
netif_warn(efx, drv, efx->net_dev, "Please unload the driver in the VM.\n"); goto restore_vadaptor;
}
vf->vport_assigned = 0;
}
if (!is_zero_ether_addr(vf->mac)) {
rc = efx_ef10_vport_del_mac(efx, vf->vport_id, vf->mac); if (rc) goto restore_evb_port;
}
if (vf->vport_id) {
rc = efx_ef10_vport_free(efx, vf->vport_id); if (rc) goto restore_mac;
vf->vport_id = 0;
}
/* Do the actual vlan change */
vf->vlan = new_vlan;
/* Restore everything in reverse order */
rc = efx_ef10_vport_alloc(efx, EVB_PORT_ID_ASSIGNED,
MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL,
vf->vlan, &vf->vport_id); if (rc) goto reset_nic_up_write;
restore_mac: if (!is_zero_ether_addr(vf->mac)) {
rc2 = efx_ef10_vport_add_mac(efx, vf->vport_id, vf->mac); if (rc2) {
eth_zero_addr(vf->mac); goto reset_nic_up_write;
}
}
reset_nic_up_write: if (vf->efx)
mutex_unlock(&vf->efx->mac_lock);
reset_nic: if (vf->efx) {
netif_err(efx, drv, efx->net_dev, "Failed to restore VF - scheduling reset.\n");
efx_schedule_reset(vf->efx, RESET_TYPE_DATAPATH);
} else {
netif_err(efx, drv, efx->net_dev, "Failed to restore the VF and cannot reset the VF " "- VF is not functional.\n");
netif_err(efx, drv, efx->net_dev, "Please reload the driver attached to the VF.\n");
}
if (rc != 0) return rc; if (outlen != MC_CMD_PRIVILEGE_MASK_OUT_LEN) return -EIO;
return 0;
}
int efx_ef10_sriov_set_vf_spoofchk(struct efx_nic *efx, int vf_i, bool spoofchk)
{ struct efx_ef10_nic_data *nic_data = efx->nic_data;
/* Can't enable spoofchk if firmware doesn't support it. */ if (!(nic_data->datapath_caps &
BIT(MC_CMD_GET_CAPABILITIES_OUT_TX_MAC_SECURITY_FILTERING_LBN)) &&
spoofchk) return -EOPNOTSUPP;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.