6ae9ed
From 9798935b4b81d153f59116707e7708e7a8988b05 Mon Sep 17 00:00:00 2001
6ae9ed
Message-Id: <9798935b4b81d153f59116707e7708e7a8988b05@dist-git>
6ae9ed
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
6ae9ed
Date: Thu, 21 Jul 2016 15:57:52 +0200
6ae9ed
Subject: [PATCH] Add functions for adding USB hubs to addrs
6ae9ed
MIME-Version: 1.0
6ae9ed
Content-Type: text/plain; charset=UTF-8
6ae9ed
Content-Transfer-Encoding: 8bit
6ae9ed
6ae9ed
Walk through all the usb hubs in the domain definition
6ae9ed
that have a USB address specified, create the
6ae9ed
corresponding structures in the virDomainUSBAddressSet
6ae9ed
and mark the port it occupies as used.
6ae9ed
6ae9ed
(cherry picked from commit 2f0813515e8a573a74c37850c4a90924cecebb90)
6ae9ed
Signed-off-by: Ján Tomko <jtomko@redhat.com>
6ae9ed
6ae9ed
https://bugzilla.redhat.com/show_bug.cgi?id=1215968
6ae9ed
---
6ae9ed
 src/conf/domain_addr.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++
6ae9ed
 1 file changed, 115 insertions(+)
6ae9ed
6ae9ed
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
6ae9ed
index ea37a42..ad20fef 100644
6ae9ed
--- a/src/conf/domain_addr.c
6ae9ed
+++ b/src/conf/domain_addr.c
6ae9ed
@@ -1432,6 +1432,109 @@ virDomainUSBAddressSetAddController(virDomainUSBAddressSetPtr addrs,
6ae9ed
 }
6ae9ed
 
6ae9ed
 
6ae9ed
+static ssize_t
6ae9ed
+virDomainUSBAddressGetLastIdx(virDomainDeviceInfoPtr info)
6ae9ed
+{
6ae9ed
+    ssize_t i;
6ae9ed
+    for (i = VIR_DOMAIN_DEVICE_USB_MAX_PORT_DEPTH - 1; i > 0; i--) {
6ae9ed
+        if (info->addr.usb.port[i] != 0)
6ae9ed
+            break;
6ae9ed
+    }
6ae9ed
+    return i;
6ae9ed
+}
6ae9ed
+
6ae9ed
+
6ae9ed
+/* Find the USBAddressHub structure representing the hub/controller
6ae9ed
+ * that corresponds to the bus/port path specified by info.
6ae9ed
+ * Returns the index of the requested port in targetIdx.
6ae9ed
+ */
6ae9ed
+static virDomainUSBAddressHubPtr
6ae9ed
+virDomainUSBAddressFindPort(virDomainUSBAddressSetPtr addrs,
6ae9ed
+                            virDomainDeviceInfoPtr info,
6ae9ed
+                            int *targetIdx,
6ae9ed
+                            const char *portStr)
6ae9ed
+{
6ae9ed
+    virDomainUSBAddressHubPtr hub = NULL;
6ae9ed
+    ssize_t i, lastIdx;
6ae9ed
+
6ae9ed
+    if (info->addr.usb.bus >= addrs->nbuses ||
6ae9ed
+        !addrs->buses[info->addr.usb.bus]) {
6ae9ed
+        virReportError(VIR_ERR_XML_ERROR, _("Missing USB bus %u"),
6ae9ed
+                       info->addr.usb.bus);
6ae9ed
+        return NULL;
6ae9ed
+    }
6ae9ed
+    hub = addrs->buses[info->addr.usb.bus];
6ae9ed
+
6ae9ed
+    lastIdx = virDomainUSBAddressGetLastIdx(info);
6ae9ed
+
6ae9ed
+    for (i = 0; i < lastIdx; i++) {
6ae9ed
+        /* ports are numbered from 1 */
6ae9ed
+        int portIdx = info->addr.usb.port[i] - 1;
6ae9ed
+
6ae9ed
+        if (hub->nports <= portIdx) {
6ae9ed
+            virReportError(VIR_ERR_XML_ERROR,
6ae9ed
+                           _("port %u out of range in USB address bus: %u port: %s"),
6ae9ed
+                           info->addr.usb.port[i],
6ae9ed
+                           info->addr.usb.bus,
6ae9ed
+                           portStr);
6ae9ed
+            return NULL;
6ae9ed
+        }
6ae9ed
+        hub = hub->ports[portIdx];
6ae9ed
+    }
6ae9ed
+
6ae9ed
+    *targetIdx = info->addr.usb.port[lastIdx] - 1;
6ae9ed
+    return hub;
6ae9ed
+}
6ae9ed
+
6ae9ed
+
6ae9ed
+#define VIR_DOMAIN_USB_HUB_PORTS 8
6ae9ed
+
6ae9ed
+static int
6ae9ed
+virDomainUSBAddressSetAddHub(virDomainUSBAddressSetPtr addrs,
6ae9ed
+                             virDomainHubDefPtr hub)
6ae9ed
+{
6ae9ed
+    virDomainUSBAddressHubPtr targetHub = NULL, newHub = NULL;
6ae9ed
+    int ret = -1;
6ae9ed
+    int targetPort;
6ae9ed
+    char *portStr = NULL;
6ae9ed
+
6ae9ed
+    if (hub->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
6ae9ed
+        virReportError(VIR_ERR_XML_ERROR, "%s",
6ae9ed
+                       _("Wrong address type for USB hub"));
6ae9ed
+        goto cleanup;
6ae9ed
+    }
6ae9ed
+
6ae9ed
+    if (!(portStr = virDomainUSBAddressPortFormat(hub->info.addr.usb.port)))
6ae9ed
+        goto cleanup;
6ae9ed
+
6ae9ed
+    VIR_DEBUG("Adding a USB hub with 8 ports on bus=%u port=%s",
6ae9ed
+              hub->info.addr.usb.bus, portStr);
6ae9ed
+
6ae9ed
+    if (!(newHub = virDomainUSBAddressHubNew(VIR_DOMAIN_USB_HUB_PORTS)))
6ae9ed
+        goto cleanup;
6ae9ed
+
6ae9ed
+    if (!(targetHub = virDomainUSBAddressFindPort(addrs, &(hub->info), &targetPort,
6ae9ed
+                                                  portStr)))
6ae9ed
+        goto cleanup;
6ae9ed
+
6ae9ed
+    if (targetHub->ports[targetPort]) {
6ae9ed
+        virReportError(VIR_ERR_XML_ERROR,
6ae9ed
+                       _("Duplicate USB hub on bus %u port %s"),
6ae9ed
+                       hub->info.addr.usb.bus, portStr);
6ae9ed
+        goto cleanup;
6ae9ed
+    }
6ae9ed
+    ignore_value(virBitmapSetBit(targetHub->portmap, targetPort));
6ae9ed
+    targetHub->ports[targetPort] = newHub;
6ae9ed
+    newHub = NULL;
6ae9ed
+
6ae9ed
+    ret = 0;
6ae9ed
+ cleanup:
6ae9ed
+    virDomainUSBAddressHubFree(newHub);
6ae9ed
+    VIR_FREE(portStr);
6ae9ed
+    return ret;
6ae9ed
+}
6ae9ed
+
6ae9ed
+
6ae9ed
 int
6ae9ed
 virDomainUSBAddressSetAddControllers(virDomainUSBAddressSetPtr addrs,
6ae9ed
                                      virDomainDefPtr def)
6ae9ed
@@ -1445,5 +1548,17 @@ virDomainUSBAddressSetAddControllers(virDomainUSBAddressSetPtr addrs,
6ae9ed
                 return -1;
6ae9ed
         }
6ae9ed
     }
6ae9ed
+
6ae9ed
+    for (i = 0; i < def->nhubs; i++) {
6ae9ed
+        virDomainHubDefPtr hub = def->hubs[i];
6ae9ed
+        if (hub->type == VIR_DOMAIN_HUB_TYPE_USB &&
6ae9ed
+            hub->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB &&
6ae9ed
+            virDomainUSBAddressPortIsValid(hub->info.addr.usb.port)) {
6ae9ed
+            /* USB hubs that do not yet have an USB address have to be
6ae9ed
+             * dealt with later */
6ae9ed
+            if (virDomainUSBAddressSetAddHub(addrs, hub) < 0)
6ae9ed
+                return -1;
6ae9ed
+        }
6ae9ed
+    }
6ae9ed
     return 0;
6ae9ed
 }
6ae9ed
-- 
6ae9ed
2.9.2
6ae9ed