Re: [PATCH v6 10/17] qemu: auto-add pcie-root-port/dmi-to-pci-bridge controllers as needed

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]