diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index f838671ad4..a0f64947f7 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -2334,6 +2334,7 @@ static int networkCreateInterfacePool(virNetworkDefPtr netdef) { size_t numVirtFns = 0; + unsigned int maxVirtFns = 0; char **vfNames = NULL; virPCIDeviceAddressPtr *virtFns; @@ -2343,8 +2344,8 @@ networkCreateInterfacePool(virNetworkDefPtr netdef) if (netdef->forward.npfs == 0 || netdef->forward.nifs > 0) return 0; - if ((virNetDevGetVirtualFunctions(netdef->forward.pfs->dev, - &vfNames, &virtFns, &numVirtFns)) < 0) { + if ((virNetDevGetVirtualFunctions(netdef->forward.pfs->dev, &vfNames, + &virtFns, &numVirtFns, &maxVirtFns)) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not get Virtual functions on %s"), netdef->forward.pfs->dev); diff --git a/src/node_device/node_device_linux_sysfs.c b/src/node_device/node_device_linux_sysfs.c index 6d5a406ec9..431f471f7a 100644 --- a/src/node_device/node_device_linux_sysfs.c +++ b/src/node_device/node_device_linux_sysfs.c @@ -150,6 +150,7 @@ nodeDeviceSysfsGetPCISRIOVCaps(const char *sysfsPath, VIR_FREE(data->pci_dev.virtual_functions[i]); VIR_FREE(data->pci_dev.virtual_functions); data->pci_dev.num_virtual_functions = 0; + data->pci_dev.max_virtual_functions = 0; data->pci_dev.flags &= ~VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION; data->pci_dev.flags &= ~VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION; @@ -157,11 +158,13 @@ nodeDeviceSysfsGetPCISRIOVCaps(const char *sysfsPath, data->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION; ret = virPCIGetVirtualFunctions(sysfsPath, &data->pci_dev.virtual_functions, - &data->pci_dev.num_virtual_functions); + &data->pci_dev.num_virtual_functions, + &data->pci_dev.max_virtual_functions); if (ret < 0) return ret; - if (data->pci_dev.num_virtual_functions > 0) + if (data->pci_dev.num_virtual_functions > 0 || + data->pci_dev.max_virtual_functions > 0) data->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION; return ret; diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index ade9afad13..e7f44cdd24 100644 --- a/src/util/virnetdev.c +++ b/src/util/virnetdev.c @@ -1802,7 +1802,8 @@ int virNetDevGetVirtualFunctions(const char *pfname, char ***vfname, virPCIDeviceAddressPtr **virt_fns, - size_t *n_vfname) + size_t *n_vfname, + unsigned int *max_vfs) { int ret = -1; size_t i; @@ -1812,12 +1813,13 @@ virNetDevGetVirtualFunctions(const char *pfname, *virt_fns = NULL; *n_vfname = 0; + *max_vfs = 0; if (virNetDevSysfsFile(&pf_sysfs_device_link, pfname, "device") < 0) return ret; if (virPCIGetVirtualFunctions(pf_sysfs_device_link, virt_fns, - n_vfname) < 0) + n_vfname, max_vfs) < 0) goto cleanup; if (VIR_ALLOC_N(*vfname, *n_vfname) < 0) @@ -1987,7 +1989,8 @@ int virNetDevGetVirtualFunctions(const char *pfname ATTRIBUTE_UNUSED, char ***vfname ATTRIBUTE_UNUSED, virPCIDeviceAddressPtr **virt_fns ATTRIBUTE_UNUSED, - size_t *n_vfname ATTRIBUTE_UNUSED) + size_t *n_vfname ATTRIBUTE_UNUSED, + unsigned int *max_vfs ATTRIBUTE_UNUSED) { virReportSystemError(ENOSYS, "%s", _("Unable to get virtual functions on this platform")); diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h index 772ae75682..e7719d58a4 100644 --- a/src/util/virnetdev.h +++ b/src/util/virnetdev.h @@ -163,9 +163,10 @@ int virNetDevGetPhysicalFunction(const char *ifname, char **pfname) int virNetDevGetVirtualFunctions(const char *pfname, char ***vfname, virPCIDeviceAddressPtr **virt_fns, - size_t *n_vfname) + size_t *n_vfname, + unsigned int *max_vfs) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) - ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; + ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_RETURN_CHECK; int virNetDevLinkDump(const char *ifname, int ifindex, void **nlData, struct nlattr **tb, diff --git a/src/util/virpci.c b/src/util/virpci.c index 35b145931a..bececb5796 100644 --- a/src/util/virpci.c +++ b/src/util/virpci.c @@ -1,7 +1,7 @@ /* * virpci.c: helper APIs for managing host PCI devices * - * Copyright (C) 2009-2014 Red Hat, Inc. + * Copyright (C) 2009-2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -2514,18 +2514,36 @@ virPCIGetPhysicalFunction(const char *vf_sysfs_path, int virPCIGetVirtualFunctions(const char *sysfs_path, virPCIDeviceAddressPtr **virtual_functions, - size_t *num_virtual_functions) + size_t *num_virtual_functions, + unsigned int *max_virtual_functions) { int ret = -1; size_t i; char *device_link = NULL; virPCIDeviceAddress *config_addr = NULL; + char *totalvfs_file = NULL, *totalvfs_str = NULL; VIR_DEBUG("Attempting to get SR IOV virtual functions for device" "with sysfs path '%s'", sysfs_path); *virtual_functions = NULL; *num_virtual_functions = 0; + *max_virtual_functions = 0; + + if (virAsprintf(&totalvfs_file, "%s/sriov_totalvfs", sysfs_path) < 0) + goto error; + if (virFileExists(totalvfs_file)) { + char *end = NULL; /* so that terminating \n doesn't create error */ + + if (virFileReadAll(totalvfs_file, 16, &totalvfs_str) < 0) + goto error; + if (virStrToLong_ui(totalvfs_str, &end, 10, max_virtual_functions) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unrecognized value in %s: %s"), + totalvfs_file, totalvfs_str); + goto error; + } + } do { /* look for virtfn%d links until one isn't found */ @@ -2553,6 +2571,8 @@ virPCIGetVirtualFunctions(const char *sysfs_path, cleanup: VIR_FREE(device_link); VIR_FREE(config_addr); + VIR_FREE(totalvfs_file); + VIR_FREE(totalvfs_str); return ret; error: @@ -2594,6 +2614,7 @@ virPCIGetVirtualFunctionIndex(const char *pf_sysfs_device_link, int ret = -1; size_t i; size_t num_virt_fns = 0; + unsigned int max_virt_fns = 0; virPCIDeviceAddressPtr vf_bdf = NULL; virPCIDeviceAddressPtr *virt_fns = NULL; @@ -2602,7 +2623,7 @@ virPCIGetVirtualFunctionIndex(const char *pf_sysfs_device_link, return ret; if (virPCIGetVirtualFunctions(pf_sysfs_device_link, &virt_fns, - &num_virt_fns) < 0) { + &num_virt_fns, &max_virt_fns) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Error getting physical function's '%s' " "virtual_functions"), pf_sysfs_device_link); @@ -2738,7 +2759,8 @@ virPCIGetPhysicalFunction(const char *vf_sysfs_path ATTRIBUTE_UNUSED, int virPCIGetVirtualFunctions(const char *sysfs_path ATTRIBUTE_UNUSED, virPCIDeviceAddressPtr **virtual_functions ATTRIBUTE_UNUSED, - size_t *num_virtual_functions ATTRIBUTE_UNUSED) + size_t *num_virtual_functions ATTRIBUTE_UNUSED, + unsigned int *max_virtual_functions ATTRIBUTE_UNUSED) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(unsupported)); return -1; diff --git a/src/util/virpci.h b/src/util/virpci.h index 64b9e96040..6516f058c7 100644 --- a/src/util/virpci.h +++ b/src/util/virpci.h @@ -1,7 +1,7 @@ /* * virpci.h: helper APIs for managing host PCI devices * - * Copyright (C) 2009, 2011-2014 Red Hat, Inc. + * Copyright (C) 2009, 2011-2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -171,7 +171,8 @@ int virPCIGetPhysicalFunction(const char *sysfs_path, int virPCIGetVirtualFunctions(const char *sysfs_path, virPCIDeviceAddressPtr **virtual_functions, - size_t *num_virtual_functions); + size_t *num_virtual_functions, + unsigned int *max_virtual_functions); int virPCIIsVirtualFunction(const char *vf_sysfs_device_link);