[PATCH v2 15/21] domain: addr: Introduce virDomainPCIAddressEnsureMultifunctionAddress

Daniel Henrique Barboza danielhb413 at gmail.com
Thu Jan 30 16:44:27 UTC 2020


From: Shivaprasad G Bhat <sbhat at linux.vnet.ibm.com>

Signed-off-by: Shivaprasad G Bhat <sbhat at linux.vnet.ibm.com>
Signed-off-by: Daniel Henrique Barboza <danielhb413 at gmail.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, 96 insertions(+), 2 deletions(-)

diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
index d8649daa6d..8c5811a4f6 100644
--- a/src/conf/device_conf.h
+++ b/src/conf/device_conf.h
@@ -183,6 +183,12 @@ struct _virDomainDeviceInfo {
     bool isolationGroupLocked;
 };
 
+typedef struct _virDomainPCIMultifunctionAddressInfo virDomainPCIMultifunctionAddressInfo;
+typedef virDomainPCIMultifunctionAddressInfo *virDomainPCIMultifunctionAddressInfoPtr;
+struct _virDomainPCIMultifunctionAddressInfo {
+   virDomainDeviceInfoPtr infos[VIR_PCI_MAX_FUNCTIONS];
+};
+
 void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info);
 void virDomainDeviceInfoFree(virDomainDeviceInfoPtr info);
 
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
index 8e4817689e..9abbdc9d54 100644
--- a/src/conf/domain_addr.c
+++ b/src/conf/domain_addr.c
@@ -21,11 +21,12 @@
 
 #include <config.h>
 
+#include "device_conf.h"
+#include "domain_addr.h"
 #include "viralloc.h"
+#include "virhashcode.h"
 #include "virlog.h"
 #include "virstring.h"
-#include "domain_addr.h"
-#include "virhashcode.h"
 
 #define VIR_FROM_THIS VIR_FROM_DOMAIN
 
@@ -977,6 +978,85 @@ virDomainPCIAddressExtensionReleaseAddr(virDomainPCIAddressSetPtr addrs,
 }
 
 
+int
+virDomainPCIAddressEnsureMultifunctionAddress(virDomainPCIAddressSetPtr addrs,
+                                              virDomainPCIMultifunctionAddressInfoPtr pcicard)
+{
+    size_t i;
+    int ret = 0;
+    virPCIDeviceAddressPtr addr1 = NULL, addr2 = NULL;
+    virDomainDeviceInfoPtr dev = 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++) {
+        g_autofree char *addrStr = NULL;
+        dev = pcicard->infos[i];
+
+        if (dev && !dev->pciConnectFlags) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Not a PCI Multifunction device."));
+            return -1;
+        }
+        if (dev && virDeviceInfoPCIAddressIsPresent(dev)) {
+            /* Pick one and compare against rest of the user given */
+            addr1 = addr1 ? addr1 : &dev->addr.pci;
+            addr2 = &dev->addr.pci;
+
+            if (!(addrStr = virPCIDeviceAddressAsString(addr2)))
+                return -1;
+
+            if (!virDomainPCIAddressValidate(addrs, addr2, addrStr,
+                                             dev->pciConnectFlags, true))
+                return -1;
+
+            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"));
+                return -1;
+            }
+        }
+    }
+
+    /* Reserve all the user given addresses. */
+    for (i = 0; i < VIR_PCI_MAX_FUNCTIONS; i++) {
+        dev = pcicard->infos[i];
+        if (dev && virDeviceInfoPCIAddressIsPresent(dev)) {
+            ret = virDomainPCIAddressReserveAddrInternal(addrs, &dev->addr.pci,
+                                                         dev->pciConnectFlags,
+                                                         dev->isolationGroup,
+                                                         dev->aggregateSlotIdx,
+                                                         true);
+            if (ret < 0)
+                return ret;
+        }
+    }
+
+    /* 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 && !virDeviceInfoPCIAddressIsPresent(dev)) {
+            ret = virDomainPCIAddressReserveNextAddr(addrs, dev,
+                                                     dev->pciConnectFlags, i);
+            if (ret < 0)
+                return ret;
+        }
+    }
+
+    /* Set multi on overriding what user has set. */
+    pcicard->infos[0]->addr.pci.multi = VIR_TRISTATE_SWITCH_ON;
+
+    return 0;
+}
+
+
 void
 virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
                                virPCIDeviceAddressPtr addr)
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
index 65dbdb3286..50006a8e9b 100644
--- a/src/conf/domain_addr.h
+++ b/src/conf/domain_addr.h
@@ -178,6 +178,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 eda759c219..0b5a34e450 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -148,6 +148,7 @@ virDomainCCWAddressSetFree;
 virDomainPCIAddressBusIsFullyReserved;
 virDomainPCIAddressBusSetModel;
 virDomainPCIAddressEnsureAddr;
+virDomainPCIAddressEnsureMultifunctionAddress;
 virDomainPCIAddressExtensionReleaseAddr;
 virDomainPCIAddressExtensionReserveAddr;
 virDomainPCIAddressExtensionReserveNextAddr;
diff --git a/src/util/virpci.h b/src/util/virpci.h
index 9d8dcfec05..4d0994b195 100644
--- a/src/util/virpci.h
+++ b/src/util/virpci.h
@@ -26,6 +26,8 @@
 #include "virutil.h"
 #include "virenum.h"
 
+#define VIR_PCI_MAX_FUNCTIONS 8
+
 typedef struct _virPCIDevice virPCIDevice;
 typedef virPCIDevice *virPCIDevicePtr;
 typedef struct _virPCIDeviceAddress virPCIDeviceAddress;
-- 
2.24.1





More information about the libvir-list mailing list