The sPAPR PHB device can only work with pseries machine types. This
is currently checked in the realize function with a dynamic cast of
qdev_get_machine(). Some other places also need to reach out to the
machine using qdev_get_machine().

Make this dependency explicit by introducing an "spapr" link
property which officialy points to the machine. This link is
set by pseries machine types only in the pre-plug handler. This
allows to drop some users of qdev_get_machine().

Signed-off-by: Greg Kurz <gr...@kaod.org>
---
 include/hw/pci-host/spapr.h |  1 +
 hw/ppc/spapr.c              |  4 ++++
 hw/ppc/spapr_pci.c          | 17 +++++++----------
 hw/ppc/spapr_pci_nvlink2.c  |  2 +-
 4 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index 4f58f0223b56..622a4f1a07c6 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -76,6 +76,7 @@ struct SpaprPhbState {
     SpaprPciMsiMig *msi_devs;
 
     QLIST_ENTRY(SpaprPhbState) list;
+    SpaprMachineState *spapr;
 
     bool ddw_enabled;
     uint64_t page_size_mask;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 4cc51723c62e..aca7d7af283a 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -3892,6 +3892,10 @@ static bool spapr_phb_pre_plug(HotplugHandler 
*hotplug_dev, DeviceState *dev,
     const unsigned windows_supported = spapr_phb_windows_supported(sphb);
     SpaprDrc *drc;
 
+    /* Required by spapr_phb_realize() */
+    object_property_set_link(OBJECT(dev), "spapr", OBJECT(hotplug_dev),
+                             &error_abort);
+
     if (dev->hotplugged && !smc->dr_phb_enabled) {
         error_setg(errp, "PHB hotplug not supported for this machine");
         return false;
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index e946bd5055cc..2d9b88b93122 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -722,7 +722,7 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, 
int level)
      * corresponding qemu_irq.
      */
     SpaprPhbState *phb = opaque;
-    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
+    SpaprMachineState *spapr = phb->spapr;
 
     trace_spapr_pci_lsi_set(phb->dtbusname, irq_num, 
phb->lsi_table[irq_num].irq);
     qemu_set_irq(spapr_qirq(spapr, phb->lsi_table[irq_num].irq), level);
@@ -1743,10 +1743,10 @@ static void spapr_phb_finalizefn(Object *obj)
 
 static void spapr_phb_unrealize(DeviceState *dev)
 {
-    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
     SysBusDevice *s = SYS_BUS_DEVICE(dev);
     PCIHostState *phb = PCI_HOST_BRIDGE(s);
     SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(phb);
+    SpaprMachineState *spapr = sphb->spapr;
     SpaprTceTable *tcet;
     int i;
     const unsigned windows_supported = spapr_phb_windows_supported(sphb);
@@ -1817,15 +1817,9 @@ static void spapr_phb_destroy_msi(gpointer opaque)
 static void spapr_phb_realize(DeviceState *dev, Error **errp)
 {
     ERRP_GUARD();
-    /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user
-     * tries to add a sPAPR PHB to a non-pseries machine.
-     */
-    SpaprMachineState *spapr =
-        (SpaprMachineState *) object_dynamic_cast(qdev_get_machine(),
-                                                  TYPE_SPAPR_MACHINE);
-    SpaprMachineClass *smc = spapr ? SPAPR_MACHINE_GET_CLASS(spapr) : NULL;
     SysBusDevice *s = SYS_BUS_DEVICE(dev);
     SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
+    SpaprMachineState *spapr = sphb->spapr;
     PCIHostState *phb = PCI_HOST_BRIDGE(s);
     MachineState *ms = MACHINE(spapr);
     char *namebuf;
@@ -1835,6 +1829,7 @@ static void spapr_phb_realize(DeviceState *dev, Error 
**errp)
     SpaprTceTable *tcet;
     const unsigned windows_supported = spapr_phb_windows_supported(sphb);
 
+    /* Set in spapr_phb_pre_plug() */
     if (!spapr) {
         error_setg(errp, TYPE_SPAPR_PCI_HOST_BRIDGE " needs a pseries 
machine");
         return;
@@ -1986,7 +1981,7 @@ static void spapr_phb_realize(DeviceState *dev, Error 
**errp)
     for (i = 0; i < PCI_NUM_PINS; i++) {
         int irq = SPAPR_IRQ_PCI_LSI + sphb->index * PCI_NUM_PINS + i;
 
-        if (smc->legacy_irq_allocation) {
+        if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
             irq = spapr_irq_findone(spapr, errp);
             if (irq < 0) {
                 error_prepend(errp, "can't allocate LSIs: ");
@@ -2109,6 +2104,8 @@ static Property spapr_phb_properties[] = {
     DEFINE_PROP_UINT64("atsd", SpaprPhbState, nv2_atsd_win_addr, 0),
     DEFINE_PROP_BOOL("pre-5.1-associativity", SpaprPhbState,
                      pre_5_1_assoc, false),
+    DEFINE_PROP_LINK("spapr", SpaprPhbState, spapr, TYPE_SPAPR_MACHINE,
+                     SpaprMachineState *),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/ppc/spapr_pci_nvlink2.c b/hw/ppc/spapr_pci_nvlink2.c
index 8ef9b40a18dc..ce62318a6d73 100644
--- a/hw/ppc/spapr_pci_nvlink2.c
+++ b/hw/ppc/spapr_pci_nvlink2.c
@@ -368,7 +368,7 @@ void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, 
void *fdt)
         _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
         _FDT((fdt_setprop(fdt, off, "reg", mem_reg, sizeof(mem_reg))));
 
-        spapr_numa_write_associativity_dt(SPAPR_MACHINE(qdev_get_machine()),
+        spapr_numa_write_associativity_dt(sphb->spapr,
                                           fdt, off, nvslot->numa_id);
 
         _FDT((fdt_setprop_string(fdt, off, "compatible",
-- 
2.26.2


Reply via email to