Previously PCI bus setup was done in 3 steps:
1) create a PCI bus, configure DMA
2) create PCI devices on the bus
3) populate a PCI bus node in the Device Tree

As some bus parameters can be configured only when some or all
the devices got attached to the bus and initialized,
the spapr_finalize_pci_setup has been introduced.

As an example, such a handler can setup DMA window parameters taken from
an IOMMU file descriptor available from a VFIO PCI device.

Signed-off-by: Alexey Kardashevskiy <a...@ozlabs.ru>
---
 hw/spapr.c     |    7 +++++++
 hw/spapr_pci.c |   13 ++++++++++---
 hw/spapr_pci.h |    2 ++
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/hw/spapr.c b/hw/spapr.c
index b83f83b..688a135 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -516,7 +516,14 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
     }
 
     QLIST_FOREACH(phb, &spapr->phbs, list) {
+        ret = spapr_finalize_pci_setup(phb);
+        if (ret < 0) {
+            break;
+        }
         ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt);
+        if (ret < 0) {
+            break;
+        }
     }
 
     if (ret < 0) {
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 014297b..5f89003 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -573,9 +573,6 @@ static int spapr_phb_init(SysBusDevice *s)
     phb->host_state.bus = bus;
 
     phb->dma_liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16);
-    phb->dma_window_start = 0;
-    phb->dma_window_size = 0x40000000;
-    phb->dma = spapr_tce_new_dma_context(phb->dma_liobn, phb->dma_window_size);
     pci_setup_iommu(bus, spapr_pci_dma_context_fn, phb);
 
     QLIST_INSERT_HEAD(&spapr->phbs, phb, list);
@@ -639,6 +636,16 @@ void spapr_create_phb(sPAPREnvironment *spapr,
     qdev_init_nofail(dev);
 }
 
+/* Finalize PCI setup, called when all devices are already created */
+int spapr_finalize_pci_setup(sPAPRPHBState *phb)
+{
+    phb->dma_window_start = 0;
+    phb->dma_window_size = 0x40000000;
+    phb->dma = spapr_tce_new_dma_context(phb->dma_liobn,
+                                         phb->dma_window_size);
+    return 0;
+}
+
 /* Macros to operate with address in OF binding to PCI */
 #define b_x(x, p, l)    (((x) & ((1<<(l))-1)) << (p))
 #define b_n(x)          b_x((x), 31, 1) /* 0 if relocatable */
diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h
index 145071c..3aae273 100644
--- a/hw/spapr_pci.h
+++ b/hw/spapr_pci.h
@@ -68,6 +68,8 @@ void spapr_create_phb(sPAPREnvironment *spapr,
                       uint64_t mem_win_addr, uint64_t mem_win_size,
                       uint64_t io_win_addr, uint64_t msi_win_addr);
 
+int spapr_finalize_pci_setup(sPAPRPHBState *phb);
+
 int spapr_populate_pci_dt(sPAPRPHBState *phb,
                           uint32_t xics_phandle,
                           void *fdt);
-- 
1.7.10


Reply via email to