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