}
+static int
+virNodeDevPCICapabilityParseXML(xmlXPathContextPtr ctxt,
+ xmlNodePtr node,
+ virNodeDevCapDataPtr data)
+{
+ char *maxFuncsStr = virXMLPropString(node, "maxCount");
+ char *type = virXMLPropString(node, "type");
+ xmlNodePtr *addresses = NULL;
+ xmlNodePtr orignode = ctxt->node;
+ int ret = -1;
+ size_t i = 0;
+
+ ctxt->node = node;
+
+ if (!type) {
+ virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing capability type"));
+ goto out;
+ }
+
+ if (STREQ(type, "phys_function")) {
+ xmlNodePtr address = virXPathNode("./address[1]", ctxt);
+
+ if (VIR_ALLOC(data->pci_dev.physical_function) < 0)
+ goto out;
+
+ data->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION;
+
+ if (!address) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Missing address in 'phys_function' capability"));
+ goto out;
+ }
+
+ if (virPCIDeviceAddressParseXML(address,
+ data->pci_dev.physical_function) < 0)
+ goto out;
+ } else if (STREQ(type, "virt_functions")) {
+ int naddresses = virXPathNodeSet("./address", ctxt, &addresses);
+
+ if (maxFuncsStr &&
+ virStrToLong_uip(maxFuncsStr, NULL, 10,
+ &data->pci_dev.max_virtual_functions) < 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Malformed 'maxCount' parameter"));
+ goto out;
+ }
+
+ if (VIR_ALLOC_N(data->pci_dev.virtual_functions, naddresses) < 0)
+ goto out;
+
+ for (i = 0; i < naddresses; i++) {
+ virPCIDeviceAddressPtr addr = NULL;
+
+ if (VIR_ALLOC(addr) < 0)
+ goto out;
+
+ if (virPCIDeviceAddressParseXML(addresses[i], addr) < 0) {
+ VIR_FREE(addr);
+ goto out;
+ }
+
+ if (VIR_APPEND_ELEMENT(data->pci_dev.virtual_functions,
+ data->pci_dev.num_virtual_functions,
+ addr) < 0)
+ goto out;
+ }
+
+ data->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION;
+ } else {
+ int hdrType = virPCIHeaderTypeFromString(type);
+
+ if (hdrType > 0 && !data->pci_dev.hdrType)
+ data->pci_dev.hdrType = hdrType;
+ }
+
+ ret = 0;
+ out:
+ VIR_FREE(addresses);
+ VIR_FREE(maxFuncsStr);
+ VIR_FREE(type);
+ ctxt->node = orignode;
+ return ret;
+}
+
+
static int
virNodeDevCapPCIDevParseXML(xmlXPathContextPtr ctxt,
virNodeDeviceDefPtr def,
virNodeDevCapDataPtr data)
{
xmlNodePtr orignode, iommuGroupNode, pciExpress;
+ xmlNodePtr *nodes = NULL;
+ int n = 0;
int ret = -1;
virPCIEDeviceInfoPtr pci_express = NULL;
char *tmp = NULL;
+ size_t i = 0;
orignode = ctxt->node;
ctxt->node = node;
data->pci_dev.vendor_name = virXPathString("string(./vendor[1])", ctxt);
data->pci_dev.product_name = virXPathString("string(./product[1])", ctxt);
+ if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) < 0)
+ goto out;
+
+ for (i = 0; i < n; i++) {
+ if (virNodeDevPCICapabilityParseXML(ctxt, nodes[i], data) < 0)
+ goto out;
+ }
+ VIR_FREE(nodes);
+
if ((iommuGroupNode = virXPathNode("./iommuGroup[1]", ctxt))) {
if (virNodeDevCapPCIDevIommuGroupParseXML(ctxt, iommuGroupNode,
data) < 0) {
ret = 0;
out:
+ VIR_FREE(nodes);
VIR_FREE(tmp);
virPCIEDeviceInfoFree(pci_express);
ctxt->node = orignode;
DO_TEST("usb_device_1d6b_1_0000_00_1d_0");
DO_TEST("pci_8086_4238_pcie_wireless");
DO_TEST("pci_8086_0c0c_snd_hda_intel");
+ DO_TEST("pci_0000_00_02_0_header_type");
+ DO_TEST("pci_0000_00_1c_0_header_type");
DO_TEST("scsi_target0_0_0");
+ DO_TEST("pci_0000_02_10_7_sriov");
+ DO_TEST("pci_0000_02_10_7_sriov_vfs");
+ DO_TEST("pci_0000_02_10_7_sriov_zero_vfs_max_count");
+ DO_TEST("pci_0000_02_10_7_sriov_pf_vfs_all");
+ DO_TEST("pci_0000_02_10_7_sriov_pf_vfs_all_header_type");
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}