qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH RFC 1/2] hw/pci: delay bus_master_enable_region init


From: Marcel Apfelbaum
Subject: [Qemu-devel] [PATCH RFC 1/2] hw/pci: delay bus_master_enable_region initialization
Date: Mon, 23 May 2016 17:01:29 +0300

Skip bus_master_enable region creation on PCI devices init
in order to be sure the IOMMU device (if present) would
be created in advance. Add this memory region at machine_done time.

Signed-off-by: Marcel Apfelbaum <address@hidden>
---
 hw/i386/pc.c         | 17 +++++++++++++++++
 hw/pci/pci.c         | 22 ++++++++++++----------
 include/hw/pci/pci.h |  2 ++
 3 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 99437e0..f9ac543 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -32,6 +32,7 @@
 #include "hw/ide.h"
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/timer/hpet.h"
 #include "hw/smbios/smbios.h"
@@ -1156,12 +1157,26 @@ typedef struct PcRomPciInfo {
     uint64_t w64_max;
 } PcRomPciInfo;
 
+static void pci_bus_enable_bus_master(PCIBus *bus, PCIDevice *dev, void 
*opaque)
+{
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+
+    pci_init_bus_master(dev);
+
+    if (pc->is_bridge) {
+        PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(dev));
+        pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
+                            pci_bus_enable_bus_master, opaque);
+    }
+}
+
 static
 void pc_machine_done(Notifier *notifier, void *data)
 {
     PCMachineState *pcms = container_of(notifier,
                                         PCMachineState, machine_done);
     PCIBus *bus = pcms->bus;
+    pci_for_each_device(bus, pci_bus_num(bus), pci_bus_enable_bus_master, 
NULL);
 
     if (bus) {
         int extra_hosts = 0;
@@ -1169,6 +1184,8 @@ void pc_machine_done(Notifier *notifier, void *data)
         QLIST_FOREACH(bus, &bus->child, sibling) {
             /* look for expander root buses */
             if (pci_bus_is_root(bus)) {
+                pci_for_each_device(bus, pci_bus_num(bus),
+                                    pci_bus_enable_bus_master, NULL);
                 extra_hosts++;
             }
         }
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index bb605ef..e22b1c8 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -828,6 +828,18 @@ static void pci_config_free(PCIDevice *pci_dev)
     g_free(pci_dev->used);
 }
 
+void pci_init_bus_master(PCIDevice *pci_dev)
+{
+    AddressSpace *dma_as = pci_device_iommu_address_space(pci_dev);
+
+    memory_region_init_alias(&pci_dev->bus_master_enable_region,
+                             OBJECT(pci_dev), "bus master",
+                             dma_as->root, 0, 
memory_region_size(dma_as->root));
+    memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
+    address_space_init(&pci_dev->bus_master_as, 
&pci_dev->bus_master_enable_region,
+                       pci_dev->name);
+}
+
 static void do_pci_unregister_device(PCIDevice *pci_dev)
 {
     pci_dev->bus->devices[pci_dev->devfn] = NULL;
@@ -845,7 +857,6 @@ static PCIDevice *do_pci_register_device(PCIDevice 
*pci_dev, PCIBus *bus,
     PCIConfigReadFunc *config_read = pc->config_read;
     PCIConfigWriteFunc *config_write = pc->config_write;
     Error *local_err = NULL;
-    AddressSpace *dma_as;
     DeviceState *dev = DEVICE(pci_dev);
 
     pci_dev->bus = bus;
@@ -885,15 +896,6 @@ static PCIDevice *do_pci_register_device(PCIDevice 
*pci_dev, PCIBus *bus,
     }
 
     pci_dev->devfn = devfn;
-    dma_as = pci_device_iommu_address_space(pci_dev);
-
-    memory_region_init_alias(&pci_dev->bus_master_enable_region,
-                             OBJECT(pci_dev), "bus master",
-                             dma_as->root, 0, 
memory_region_size(dma_as->root));
-    memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
-    address_space_init(&pci_dev->bus_master_as, 
&pci_dev->bus_master_enable_region,
-                       name);
-
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
     pci_dev->irq_state = 0;
     pci_config_alloc(pci_dev);
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index ef6ba51..95a930f 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -343,6 +343,8 @@ int pci_device_load(PCIDevice *s, QEMUFile *f);
 MemoryRegion *pci_address_space(PCIDevice *dev);
 MemoryRegion *pci_address_space_io(PCIDevice *dev);
 
+void pci_init_bus_master(PCIDevice *dev);
+
 /*
  * Should not normally be used by devices. For use by sPAPR target
  * where QEMU emulates firmware.
-- 
2.4.3




reply via email to

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