The udev and hal drivers both already call the same functions as these new functions added to node_device_linux_sysfs.c, but 1) we need to call them from node_device_driver.c, and 2) it would be nice to eliminate the duplicated code from the hal and udev backends. --- src/node_device/node_device_linux_sysfs.c | 90 +++++++++++++++++++++++++++++++ src/node_device/node_device_linux_sysfs.h | 2 + 2 files changed, 92 insertions(+) diff --git a/src/node_device/node_device_linux_sysfs.c b/src/node_device/node_device_linux_sysfs.c index fc82b32..6d5a406 100644 --- a/src/node_device/node_device_linux_sysfs.c +++ b/src/node_device/node_device_linux_sysfs.c @@ -137,6 +137,96 @@ nodeDeviceSysfsGetSCSIHostCaps(virNodeDevCapDataPtr d) return ret; } + +static int +nodeDeviceSysfsGetPCISRIOVCaps(const char *sysfsPath, + virNodeDevCapDataPtr data) +{ + size_t i; + int ret; + + /* this could be a refresh, so clear out the old data */ + for (i = 0; i < data->pci_dev.num_virtual_functions; i++) + 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.flags &= ~VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION; + data->pci_dev.flags &= ~VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION; + + if (!virPCIGetPhysicalFunction(sysfsPath, &data->pci_dev.physical_function)) + 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); + if (ret < 0) + return ret; + + if (data->pci_dev.num_virtual_functions > 0) + data->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION; + + return ret; +} + + +static int +nodeDeviceSysfsGetPCIIOMMUGroupCaps(virNodeDevCapDataPtr data) +{ + size_t i; + int tmpGroup, ret = -1; + virPCIDeviceAddress addr; + + /* this could be a refresh, so clear out the old data */ + for (i = 0; i < data->pci_dev.nIommuGroupDevices; i++) + VIR_FREE(data->pci_dev.iommuGroupDevices[i]); + VIR_FREE(data->pci_dev.iommuGroupDevices); + data->pci_dev.nIommuGroupDevices = 0; + data->pci_dev.iommuGroupNumber = 0; + + addr.domain = data->pci_dev.domain; + addr.bus = data->pci_dev.bus; + addr.slot = data->pci_dev.slot; + addr.function = data->pci_dev.function; + tmpGroup = virPCIDeviceAddressGetIOMMUGroupNum(&addr); + if (tmpGroup == -1) { + /* error was already reported */ + goto cleanup; + } + if (tmpGroup == -2) { + /* -2 return means there is no iommu_group data */ + ret = 0; + goto cleanup; + } + if (tmpGroup >= 0) { + if (virPCIDeviceAddressGetIOMMUGroupAddresses(&addr, &data->pci_dev.iommuGroupDevices, + &data->pci_dev.nIommuGroupDevices) < 0) + goto cleanup; + data->pci_dev.iommuGroupNumber = tmpGroup; + } + + ret = 0; + cleanup: + return ret; +} + + +/* nodeDeviceSysfsGetPCIRelatedCaps() get info that is stored in sysfs + * about devices related to this device, i.e. things that can change + * without this device itself changing. These must be refreshed + * anytime full XML of the device is requested, because they can + * change with no corresponding notification from the kernel/udev. + */ +int +nodeDeviceSysfsGetPCIRelatedDevCaps(const char *sysfsPath, + virNodeDevCapDataPtr data) +{ + if (nodeDeviceSysfsGetPCISRIOVCaps(sysfsPath, data) < 0) + return -1; + if (nodeDeviceSysfsGetPCIIOMMUGroupCaps(data) < 0) + return -1; + return 0; +} + + #else int diff --git a/src/node_device/node_device_linux_sysfs.h b/src/node_device/node_device_linux_sysfs.h index 307a8aa..e4afdd7 100644 --- a/src/node_device/node_device_linux_sysfs.h +++ b/src/node_device/node_device_linux_sysfs.h @@ -26,5 +26,7 @@ # include "node_device_conf.h" int nodeDeviceSysfsGetSCSIHostCaps(virNodeDevCapDataPtr d); +int nodeDeviceSysfsGetPCIRelatedDevCaps(const char *sysfsPath, + virNodeDevCapDataPtr data); #endif /* __VIR_NODE_DEVICE_LINUX_SYSFS_H__ */ -- 2.1.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list