On Mon, 2016-11-07 at 14:50 -0500, Laine Stump wrote:
> Previously libvirt would only add pci-bridge devices automatically
> when an address was requested for a device that required a legacy PCI
> slot and none was available. This patch expands that support to
> dmi-to-pci-bridge (which is needed in order to add a pci-bridge on a
> machine with a pcie-root), and pcie-root-port (which is needed to add
> a hotpluggable PCIe device). It does *not* automatically add
> pcie-switch-upstream-ports or pcie-switch-downstream-ports (and
> currently there are no plans for that).
[...]
> Although libvirt will now automatically create a dmi-to-pci-bridge
> when it's needed, the code still remains for now that forces a
> dmi-to-pci-bridge on all domains with pcie-root (in
> qemuDomainDefAddDefaultDevices()). That will be removed in the next
> patch.
s/in the next/in a future/
> For now, the pcie-root-ports are added one to a slot, which is a bit
> wasteful and means it will fail after 31 total PCIe devices (30 if
> there are also some PCI devices), but helps keep the changeset down
> for this patch. A future patch will have 8 pcie-root-ports sharing the
> functions on a single slot.
[...]
> @@ -82,6 +82,30 @@
> virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model)
> return 0;
> }
>
> +
> +static int
> +virDomainPCIControllerConnectTypeToModel(virDomainPCIConnectFlags flags)
> +{
> + if (flags & VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT)
> + return VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT;
Maybe adding an empty line between each branch would make
this a little more readable? Just a thought.
Also too bad these are flags and we can't use a switch()
statement here - the compiler will not warn us if we forget
to handle a VIR_PCI_CONNECT_TYPE in the future :(
[...]
> @@ -351,32 +372,73 @@ virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr
> addrs,
> {
> int add;
> size_t i;
> + int model;
> + bool needDMIToPCIBridge = false;
>
> add = addr->bus - addrs->nbuses + 1;
> - i = addrs->nbuses;
> if (add <= 0)
> return 0;
>
> - /* auto-grow only works when we're adding plain PCI devices */
> - if (!(flags & VIR_PCI_CONNECT_TYPE_PCI_DEVICE)) {
> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> - _("Cannot automatically add a new PCI bus for a "
> - "device requiring a slot other than standard
> PCI."));
> + if (flags & VIR_PCI_CONNECT_TYPE_PCI_DEVICE) {
> + model = VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE;
> +
> + /* if there aren't yet any buses that will accept a
> + * pci-bridge, and the caller is asking for one, we'll need to
> + * add a dmi-to-pci-bridge first.
> + */
> + needDMIToPCIBridge = true;
> + for (i = 0; i < addrs->nbuses; i++) {
> + if (addrs->buses[i].flags & VIR_PCI_CONNECT_TYPE_PCI_BRIDGE) {
> + needDMIToPCIBridge = false;
> + break;
> + }
> + }
> + if (needDMIToPCIBridge && add == 1) {
> + /* we need to add at least two buses - one dmi-to-pci,
> + * and the other the requested pci-bridge
> + */
> + add++;
> + addr->bus++;
> + }
This last part got me confused for a bit, so I wouldn't mind
having a more detailed comment here. Something like
We need to add a single pci-bridge to provide the bus our
legacy PCI device will be plugged into; however, we have
also determined that the pci-bridge we're about to add
itself needs to be plugged into a dmi-to-pci-bridge. To
accomodate both requirements, we're going to add both a
dmi-to-pci-bridge and a pci-bridge, and we're going to
bump the bus number of the device by one to account for
the extra controller.
Yeah, that's quite a mouthful :/
> + } else if (flags & VIR_PCI_CONNECT_TYPE_PCI_BRIDGE &&
> + addrs->buses[0].model ==
> VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) {
> + model = VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE;
Mh, what about the case where we want to add a pci-bridge
but the machine has a pci-root instead of a pcie-root?
Shouldn't that case be handled as well?
> + } else if (flags & (VIR_PCI_CONNECT_TYPE_PCIE_DEVICE |
> + VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT)) {
> + model = VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT;
> + } else {
> + int existingContModel =
> virDomainPCIControllerConnectTypeToModel(flags);
> +
> + if (existingContModel >= 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("a PCI slot is needed to connect a PCI
> controller "
> + "model='%s', but none is available, and it "
> + "cannot be automatically added"),
> +
> virDomainControllerModelPCITypeToString(existingContModel));
> + } else {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("Cannot automatically add a new PCI bus for a "
> + "device with connect flags %.2x"), flags);
> + }
So we error out for dmi-to-pci-bridge and
pci{,e}-expander-bus... Shouldn't we be able to plug either
into into pcie-root or pci-root?
> return -1;
> }
>
> + i = addrs->nbuses;
> +
> if (VIR_EXPAND_N(addrs->buses, addrs->nbuses, add) < 0)
> return -1;
>
> - for (; i < addrs->nbuses; i++) {
> - /* Any time we auto-add a bus, we will want a multi-slot
> - * bus. Currently the only type of bus we will auto-add is a
> - * pci-bridge, which is hot-pluggable and provides standard
> - * PCI slots.
> + if (needDMIToPCIBridge) {
> + /* first of the new buses is dmi-to-pci-bridge, the
> + * rest are of the requested type
> */
> - virDomainPCIAddressBusSetModel(&addrs->buses[i],
> -
> VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE);
> + virDomainPCIAddressBusSetModel(&addrs->buses[i++],
> +
> VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE);
virDomainPCIAddressBusSetModel() can fail, yet you're not
checking the return value neither here...
> }
> +
> + for (; i < addrs->nbuses; i++)
> + virDomainPCIAddressBusSetModel(&addrs->buses[i], model);
... nor here.
[...]
> @@ -947,7 +934,43 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
>
> if (virDomainPCIAddressBusSetModel(&addrs->buses[idx], cont->model)
>< 0)
> goto error;
> - }
> +
> + if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT)
> + hasPCIeRoot = true;
> + }
> +
> + if (nbuses > 0 && !addrs->buses[0].model) {
> + /* This is just here to replicate a safety measure already in
> + * an older version of this code. In practice, the root bus
> + * should have already been added at index 0 prior to
> + * assigning addresses to devices.
> + */
> + if (virDomainPCIAddressBusSetModel(&addrs->buses[0],
> +
> VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) < 0)
> + goto error;
> + }
> +
> + /* Now fill in a reasonable model for all the buses in the set
> + * that don't yet have a corresponding controller in the domain
> + * config.
> + */
> +
No empty line here.
Rest looks good, but no ACK for you quite yet :)
--
Andrea Bolognani / Red Hat / Virtualization
--
libvir-list mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/libvir-list