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 <b...@kernel.crashing.org>
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; >