A pci-bridge has *almost* the same rules as a legacy PCI endpoint
device for where it can be automatically connected, and until now both
had been considered identical. There is one pairing that is okay when
specifically requested by the user (i.e. manual assignment), but we
want to avoid it when auto-assigning addresses - plugging a pci-bridge
directly into pcie-root (it is cleaner to plug in a dmi-to-pci-bridge,
then plug the pci-bridge into that).

In order to allow that difference, this patch makes a separate
CONNECT_TYPE for pci-bridge, and uses it to restrict auto-assigned
addresses for pci-bridges to be only on pci-root, pci-expander-bus,
dmi-to-pci-bridge, or on another pci-bridge.

NB: As with other discouraged-but-seem-to-work configurations
(e.g. plugging a legacy PCI device into a pcie-root-port) if someone
*really* wants to, they can still force a pci-bridge to be plugged
into pcie-root (by manually specifying its PCI address.)
---
 src/conf/domain_addr.c | 24 ++++++++++++++++--------
 src/conf/domain_addr.h |  4 +++-
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
index 93026c2..cff2c3b 100644
--- a/src/conf/domain_addr.c
+++ b/src/conf/domain_addr.c
@@ -51,11 +51,7 @@ 
virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model)
         return 0;
 
     case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
-        /* pci-bridge is treated like a standard
-         * PCI endpoint device, because it can plug into any
-         * standard PCI slot (it just can't be hotplugged).
-         */
-        return VIR_PCI_CONNECT_TYPE_PCI_DEVICE;
+        return VIR_PCI_CONNECT_TYPE_PCI_BRIDGE;
 
     case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS:
         return VIR_PCI_CONNECT_TYPE_PCI_EXPANDER_BUS;
@@ -110,6 +106,12 @@ virDomainPCIAddressFlagsCompatible(virPCIDeviceAddressPtr 
addr,
          */
         if (devFlags & VIR_PCI_CONNECT_HOTPLUGGABLE)
             busFlags |= VIR_PCI_CONNECT_HOTPLUGGABLE;
+        /* if the device is a pci-bridge, allow manually
+         * assigning to any bus that would also accept a
+         * standard PCI device.
+         */
+        if (devFlags & VIR_PCI_CONNECT_TYPE_PCI_BRIDGE)
+            devFlags |= VIR_PCI_CONNECT_TYPE_PCI_DEVICE;
     }
 
     /* If this bus doesn't allow the type of connection (PCI
@@ -138,6 +140,8 @@ virDomainPCIAddressFlagsCompatible(virPCIDeviceAddressPtr 
addr,
             connectStr = "pci-expander-bus";
         } else if (devFlags & VIR_PCI_CONNECT_TYPE_PCIE_EXPANDER_BUS) {
             connectStr = "pcie-expander-bus";
+        } else if (devFlags & VIR_PCI_CONNECT_TYPE_PCI_BRIDGE) {
+            connectStr = "pci-bridge";
         } else {
             /* this should never happen. If it does, there is a
              * bug in the code that sets the flag bits for devices.
@@ -247,19 +251,22 @@ virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr 
bus,
     case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
         bus->flags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
                       VIR_PCI_CONNECT_TYPE_PCI_DEVICE |
+                      VIR_PCI_CONNECT_TYPE_PCI_BRIDGE |
                       VIR_PCI_CONNECT_TYPE_PCI_EXPANDER_BUS);
         bus->minSlot = 1;
         bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
         break;
     case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
         bus->flags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
-                      VIR_PCI_CONNECT_TYPE_PCI_DEVICE);
+                      VIR_PCI_CONNECT_TYPE_PCI_DEVICE |
+                      VIR_PCI_CONNECT_TYPE_PCI_BRIDGE);
         bus->minSlot = 1;
         bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
         break;
     case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS:
         bus->flags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
-                      VIR_PCI_CONNECT_TYPE_PCI_DEVICE);
+                      VIR_PCI_CONNECT_TYPE_PCI_DEVICE |
+                      VIR_PCI_CONNECT_TYPE_PCI_BRIDGE);
         bus->minSlot = 0;
         bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
         break;
@@ -280,7 +287,8 @@ virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr 
bus,
     case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
         /* slots 0 - 31, standard PCI slots,
          * but *not* hot-pluggable */
-        bus->flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE;
+        bus->flags = (VIR_PCI_CONNECT_TYPE_PCI_DEVICE |
+                      VIR_PCI_CONNECT_TYPE_PCI_BRIDGE);
         bus->minSlot = 0;
         bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
         break;
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
index 596cd4c..0072a08 100644
--- a/src/conf/domain_addr.h
+++ b/src/conf/domain_addr.h
@@ -43,6 +43,7 @@ typedef enum {
    VIR_PCI_CONNECT_TYPE_DMI_TO_PCI_BRIDGE = 1 << 6,
    VIR_PCI_CONNECT_TYPE_PCI_EXPANDER_BUS = 1 << 7,
    VIR_PCI_CONNECT_TYPE_PCIE_EXPANDER_BUS = 1 << 8,
+   VIR_PCI_CONNECT_TYPE_PCI_BRIDGE = 1 << 9,
 } virDomainPCIConnectFlags;
 
 /* a combination of all bits that describe the type of connections
@@ -55,7 +56,8 @@ typedef enum {
     VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT | \
     VIR_PCI_CONNECT_TYPE_DMI_TO_PCI_BRIDGE | \
     VIR_PCI_CONNECT_TYPE_PCI_EXPANDER_BUS | \
-    VIR_PCI_CONNECT_TYPE_PCIE_EXPANDER_BUS)
+    VIR_PCI_CONNECT_TYPE_PCIE_EXPANDER_BUS | \
+    VIR_PCI_CONNECT_TYPE_PCI_BRIDGE)
 
 /* combination of all bits that could be used to connect a normal
  * endpoint device (i.e. excluding the connection possible between an
-- 
2.7.4

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

Reply via email to