From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56907) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZBWnz-00050H-LO for qemu-devel@nongnu.org; Sat, 04 Jul 2015 19:25:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZBWnu-0003wT-P9 for qemu-devel@nongnu.org; Sat, 04 Jul 2015 19:25:07 -0400 Received: from gate.crashing.org ([63.228.1.57]:40237) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZBWnu-0003vl-GR for qemu-devel@nongnu.org; Sat, 04 Jul 2015 19:25:02 -0400 Message-ID: <1436052298.3948.38.camel@kernel.crashing.org> From: Benjamin Herrenschmidt Date: Sun, 05 Jul 2015 09:24:58 +1000 Content-Type: text/plain; charset="UTF-8" Mime-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [RFC PATCH 2/2] pci: Use the new can_add_device() to enforce devfn_min/max List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Paolo Bonzini , "Michael S. Tsirkin" 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 --- I use this to avoid qemu putting devices in places they won't be probed, for example at a non-0 dev# under my PCIe root complex (my FW will never probe since it can't possibly happen on HW), and in fact, arguably, this should also be done for PCIe switch downstream ports. This is "RFC" however since there are cases with SR-IOV where we *do* want to make things appear at dev# != 0, if we ever implement emulation of SR-IOV that is. Without this, qemu has a tendency to just pile up PCI devices in places where it makes no sense to have them and they won't be probed however. 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 442f822..29f0b0f 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -107,6 +107,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); @@ -118,6 +139,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;