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