There are two places in qemu_domain_address.c where we have a switch
statement to convert PCI controller models
(VIR_DOMAIN_CONTROLLER_MODEL_PCI*) into the connection type flag that
is matched when looking for an upstream connection for that model of
controller (VIR_PCI_CONNECT_TYPE_*). This patch makes a utility
function in conf/domain_addr.c to do that, so that when a new PCI
controller is added, we only need to add the new model-->connect-type
in a single place.
---
src/conf/domain_addr.c | 47 +++++++++++++++++++++++++
src/conf/domain_addr.h | 4 +++
src/libvirt_private.syms | 1 +
src/qemu/qemu_domain_address.c | 80 +++++-------------------------------------
4 files changed, 61 insertions(+), 71 deletions(-)
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
index 4408c4a..1bf2c9a 100644
--- a/src/conf/domain_addr.c
+++ b/src/conf/domain_addr.c
@@ -32,6 +32,53 @@
VIR_LOG_INIT("conf.domain_addr");
+int
+virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model,
+ virDomainPCIConnectFlags *connectType)
+{
+ /* given a VIR_DOMAIN_CONTROLLER_MODEL_PCI*, set connectType to
+ * the equivalent VIR_PCI_CONNECT_TYPE_*. return 0 on success, -1
+ * if the model wasn't recognized.
+ */
+ switch (model) {
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
+ /* pci-root and pcie-root are implicit in the machine,
+ * and have no upstream connection
+ */
+ *connectType = 0;
+ break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
+ /* pci-bridge is treated like a standard PCI endpoint device, */
+ *connectType = VIR_PCI_CONNECT_TYPE_PCI_DEVICE;
+ break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
+ /* dmi-to-pci-bridge is treated like a PCIe device
+ * (e.g. it can be plugged directly into pcie-root)
+ */
+ *connectType = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE;
+ break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT:
+ *connectType = VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT;
+ break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT:
+ *connectType = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT;
+ break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT:
+ *connectType = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_DOWNSTREAM_PORT;
+ break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST:
+ /* if this happens, there is an error in the code. A
+ * PCI controller should always have a proper model
+ * set
+ */
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("PCI controller model incorrectly set to
'last'"));
+ return -1;
+ }
+ return 0;
+}
+
bool
virDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr,
const char *addrStr,
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
index b5cb0ee..eadfaf1 100644
--- a/src/conf/domain_addr.h
+++ b/src/conf/domain_addr.h
@@ -59,6 +59,10 @@ typedef enum {
# define VIR_PCI_CONNECT_TYPES_ENDPOINT \
(VIR_PCI_CONNECT_TYPE_PCI_DEVICE | VIR_PCI_CONNECT_TYPE_PCIE_DEVICE)
+int
+virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model,
+ virDomainPCIConnectFlags *connectType);
+
typedef struct {
virDomainControllerModelPCI model;
/* flags and min/max can be computed from model, but
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index af133c5..6642f3a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -107,6 +107,7 @@ virDomainPCIAddressSetFree;
virDomainPCIAddressSetGrow;
virDomainPCIAddressSlotInUse;
virDomainPCIAddressValidate;
+virDomainPCIControllerModelToConnectType;
virDomainVirtioSerialAddrAssign;
virDomainVirtioSerialAddrAutoAssign;
virDomainVirtioSerialAddrIsComplete;
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index c6e694e..7d3e441 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -446,39 +446,9 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
case VIR_DOMAIN_DEVICE_CONTROLLER:
switch (device->data.controller->type) {
case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
- switch (device->data.controller->model) {
- case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
- /* pci-bridge needs a PCI slot, but it isn't
- * hot-pluggable, so it doesn't need a hot-pluggable slot.
- */
- flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE;
- break;
- case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
- /* pci-bridge needs a PCIe slot, but it isn't
- * hot-pluggable, so it doesn't need a hot-pluggable slot.
- */
- flags = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE;
- break;
- case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT:
- /* pcie-root-port isn't hot-pluggable, and
- * is unique in what it can connect to, so
- * it has its own flag.
- */
- flags = VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT;
- break;
- case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT:
- /* pcie-switch-upstream-port is also unique, and
- * not hot-pluggable...
- */
- flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT;
- break;
- case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT:
- /* ... same for pcie-switch-downstream-port */
- flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_DOWNSTREAM_PORT;
- break;
- default:
- break;
- }
+ if
(virDomainPCIControllerModelToConnectType(device->data.controller->model,
+ &flags) < 0)
+ return -1;
break;
case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
@@ -1058,51 +1028,19 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def,
/* PCI controllers */
for (i = 0; i < def->ncontrollers; i++) {
if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
- if (def->controllers[i]->info.type !=
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+ virDomainControllerModelPCI model = def->controllers[i]->model;
+
+ if (def->controllers[i]->info.type !=
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
+ model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT ||
+ model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT)
continue;
/* convert the type of controller into a "CONNECT_TYPE"
* flag to use when searching for the proper
* controller/bus to connect it to on the upstream side.
*/
- switch ((virDomainControllerModelPCI)def->controllers[i]->model) {
- case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
- case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
- /* pci-root and pcie-root are implicit in the machine,
- * and need no address */
- continue;
- case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
- /* pci-bridge doesn't require hot-plug
- * (although it does provide hot-plug in its slots)
- */
- flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE;
- break;
- case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
- /* dmi-to-pci-bridge is treated like a
- * non-hotplug-capable PCIe device (e.g. it can be
- * plugged directly into pcie-root)
- */
- flags = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE;
- break;
- case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT:
- flags = VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT;
- break;
- case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT:
- flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT;
- break;
- case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT:
- flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_DOWNSTREAM_PORT;
- break;
-
- case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST:
- /* if this happens, there is an error in the code. A
- * PCI controller should always have a proper model
- * set
- */
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("PCI controller model icorrectly set to
'last'"));
+ if (virDomainPCIControllerModelToConnectType(model, &flags) < 0)
goto error;
- }
if (virDomainPCIAddressReserveNextSlot(addrs,
&def->controllers[i]->info,
flags) < 0)
--
2.5.5