On 11/11/2015 01:27, Benjamin Herrenschmidt wrote:
> This adds a devfn_max field to PCIBus and adds a pci_can_add_device()
> function which, if no "addr" (aka devfn) is specified, will tell whether
> there is any slot free between devfn_min and devfn_max.
>
> This will be used by some PCI root complex implementations that support
> only one direct child to avoid having qemu put dumb devices at different
> slot numbers.
>
> Signed-off-by: Benjamin Herrenschmidt <[email protected]>
CCing maintainer.
Paolo
> ---
> hw/pci/pci.c | 22 ++++++++++++++++++++++
> include/hw/pci/pci_bus.h | 1 +
> 2 files changed, 23 insertions(+)
>
> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index 168b9cc..7003f7c 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -108,6 +108,27 @@ static uint16_t pcibus_numa_node(PCIBus *bus)
> return NUMA_NODE_UNASSIGNED;
> }
>
> +static bool pci_can_add_device(BusState *bus, QemuOpts *opts)
> +{
> + unsigned int devfn, max;
> + PCIBus *pbus = PCI_BUS(bus);
> +
> + /* If address is specified, say yes and let it fail if that doesn't work
> */
> + if (qemu_opt_get(opts, "addr") != NULL) {
> + return true;
> + }
> + max = ARRAY_SIZE(pbus->devices);
> + if (pbus->devfn_max && pbus->devfn_max < max) {
> + max = pbus->devfn_max;
> + }
> + for (devfn = pbus->devfn_min ; devfn < max; devfn += PCI_FUNC_MAX) {
> + if (!pbus->devices[devfn]) {
> + break;
> + }
> + }
> + return devfn < max;
> +}
> +
> static void pci_bus_class_init(ObjectClass *klass, void *data)
> {
> BusClass *k = BUS_CLASS(klass);
> @@ -119,6 +140,7 @@ static void pci_bus_class_init(ObjectClass *klass, void
> *data)
> k->realize = pci_bus_realize;
> k->unrealize = pci_bus_unrealize;
> k->reset = pcibus_reset;
> + k->can_add_device = pci_can_add_device;
>
> pbc->is_root = pcibus_is_root;
> pbc->bus_num = pcibus_num;
> diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h
> index 403fec6..02055d4 100644
> --- a/include/hw/pci/pci_bus.h
> +++ b/include/hw/pci/pci_bus.h
> @@ -23,6 +23,7 @@ struct PCIBus {
> PCIIOMMUFunc iommu_fn;
> void *iommu_opaque;
> uint8_t devfn_min;
> + uint8_t devfn_max;
> pci_set_irq_fn set_irq;
> pci_map_irq_fn map_irq;
> pci_route_irq_fn route_intx_to_irq;
>