[libvirt] [RFC PATCH 24/28] domain: addr: Introduce virDomainPCIAddressEnsureMultifunctionAddress

Shivaprasad G Bhat posted 28 patches 6 years, 8 months ago
[libvirt] [RFC PATCH 24/28] domain: addr: Introduce virDomainPCIAddressEnsureMultifunctionAddress
Posted by Shivaprasad G Bhat 6 years, 8 months ago
Signed-off-by: Shivaprasad G Bhat <sbhat@linux.vnet.ibm.com>
---
 src/conf/device_conf.h   |    6 +++
 src/conf/domain_addr.c   |   84 ++++++++++++++++++++++++++++++++++++++++++++++
 src/conf/domain_addr.h   |    5 +++
 src/libvirt_private.syms |    1 +
 src/util/virpci.h        |    2 +
 5 files changed, 98 insertions(+)

diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
index cdb2040fb8..ae7a651ee0 100644
--- a/src/conf/device_conf.h
+++ b/src/conf/device_conf.h
@@ -177,6 +177,12 @@ struct _virDomainDeviceInfo {
     bool isolationGroupLocked;
 };
 
+typedef struct _virDomainPCIMultifunctionAddressInfo virDomainPCIMultifunctionAddressInfo;
+typedef virDomainPCIMultifunctionAddressInfo *virDomainPCIMultifunctionAddressInfoPtr;
+struct _virDomainPCIMultifunctionAddressInfo {
+   virDomainDeviceInfoPtr infos[VIR_PCI_MAX_FUNCTIONS];
+};
+
 int virDomainDeviceInfoCopy(virDomainDeviceInfoPtr dst,
                             virDomainDeviceInfoPtr src);
 void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info);
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
index c4a0b99628..43227a4b25 100644
--- a/src/conf/domain_addr.c
+++ b/src/conf/domain_addr.c
@@ -27,6 +27,7 @@
 #include "virlog.h"
 #include "virstring.h"
 #include "domain_addr.h"
+#include "device_conf.h"
 
 #define VIR_FROM_THIS VIR_FROM_DOMAIN
 
@@ -697,6 +698,89 @@ virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
 }
 
 
+/*
+ *virDomainPCIAddressEnsureMultifunctionAddress:
+ *
+ *
+ *
+ */
+
+int
+virDomainPCIAddressEnsureMultifunctionAddress(virDomainPCIAddressSetPtr addrs,
+                                              virDomainPCIMultifunctionAddressInfoPtr pcicard)
+{
+    size_t i;
+    int ret = 0;
+    virPCIDeviceAddressPtr addr1 = NULL, addr2 = NULL;
+    virDomainDeviceInfoPtr dev = NULL;
+    char *addrStr = NULL;
+
+    if (!pcicard->infos[0]) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Function-Zero missing on the slot"));
+        return -1;
+    }
+
+    /* If the address is given by the user, make sure they belong
+     * to same slot */
+    for (i = 0; i < VIR_PCI_MAX_FUNCTIONS; i++) {
+        dev = pcicard->infos[i];
+        if (dev && !dev->pciConnectFlags) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Not a PCI Multifunction device."));
+            goto cleanup;
+        }
+        if (dev && virDeviceInfoPCIAddressPresent(dev)) {
+            /* Pick one and compare against rest of the user given */
+            addr1 = addr1 ? addr1 : &dev->addr.pci;
+            addr2 = &dev->addr.pci;
+            if (!(addrStr = virDomainPCIAddressAsString(addr2)))
+                goto cleanup;
+            if (!virDomainPCIAddressValidate(addrs, addr2,
+                                             addrStr, dev->pciConnectFlags, true))
+                goto cleanup;
+            if (!(addr1->domain == addr2->domain && addr1->bus == addr2->bus &&
+                  addr1->slot == addr2->slot)) {
+                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                _("Addresses belong to different PCI slots"));
+                goto cleanup;
+            }
+            VIR_FREE(addrStr);
+        }
+    }
+
+    /* Reserve all the user given addresses. */
+    for (i = 0; i < VIR_PCI_MAX_FUNCTIONS; i++) {
+        dev = pcicard->infos[i];
+        if (dev && virDeviceInfoPCIAddressPresent(dev)) {
+            ret = virDomainPCIAddressReserveAddrInternal(addrs, &dev->addr.pci,
+                                                         dev->pciConnectFlags, dev->isolationGroup,
+                                                         dev->aggregateSlotIdx,
+                                                         true);
+            if (ret < 0)
+                goto cleanup;
+        }
+    }
+
+    /* If the user has not given addresses, start with function zero */
+    for (i = 0; i < VIR_PCI_MAX_FUNCTIONS; i++) {
+        dev = pcicard->infos[i];
+        if (dev && !virDeviceInfoPCIAddressPresent(dev)) {
+            ret = virDomainPCIAddressReserveNextAddr(addrs, dev, dev->pciConnectFlags, i);
+            if (ret < 0)
+                goto cleanup;
+        }
+    }
+
+    /* Set multi on overriding what user has set. */
+    pcicard->infos[0]->addr.pci.multi = VIR_TRISTATE_SWITCH_ON;
+
+ cleanup:
+    VIR_FREE(addrStr);
+    return ret;
+}
+
+
 void
 virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
                                virPCIDeviceAddressPtr addr)
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
index fa98b67e5c..e80e1e9089 100644
--- a/src/conf/domain_addr.h
+++ b/src/conf/domain_addr.h
@@ -162,6 +162,11 @@ int virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
                                   virDomainPCIConnectFlags flags)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
 
+int
+virDomainPCIAddressEnsureMultifunctionAddress(virDomainPCIAddressSetPtr addrs,
+                                              virDomainPCIMultifunctionAddressInfoPtr pcicard)
+   ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
 void virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
                                     virPCIDeviceAddressPtr addr)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d1ff2f5f99..3e4d627004 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -114,6 +114,7 @@ virDomainPCIAddressAsString;
 virDomainPCIAddressBusIsFullyReserved;
 virDomainPCIAddressBusSetModel;
 virDomainPCIAddressEnsureAddr;
+virDomainPCIAddressEnsureMultifunctionAddress;
 virDomainPCIAddressReleaseAddr;
 virDomainPCIAddressReserveAddr;
 virDomainPCIAddressReserveNextAddr;
diff --git a/src/util/virpci.h b/src/util/virpci.h
index 5830fb4c12..65e586ed15 100644
--- a/src/util/virpci.h
+++ b/src/util/virpci.h
@@ -29,6 +29,8 @@
 # include "virobject.h"
 # include "virutil.h"
 
+# define VIR_PCI_MAX_FUNCTIONS 8
+
 typedef struct _virPCIDevice virPCIDevice;
 typedef virPCIDevice *virPCIDevicePtr;
 typedef struct _virPCIDeviceAddress virPCIDeviceAddress;

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list