qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [RFC PATCH 2/2] pci: Use the new can_add_device() to enforc


From: Benjamin Herrenschmidt
Subject: [Qemu-devel] [RFC PATCH 2/2] pci: Use the new can_add_device() to enforce devfn_min/max
Date: Sun, 05 Jul 2015 09:24:58 +1000

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 <address@hidden>
---

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;





reply via email to

[Prev in Thread] Current Thread [Next in Thread]