From 91bcee7157b0a1c627705d5a24076a3058ea01a7 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:10 -0300 Subject: ppc/pnv: add PHB3 bus init helper The PnvPHB3 bus init consists of initializing the pci_io and pci_mmio regions, registering it via pci_register_root_bus() and then setup the iommu. We'll want to init the bus from outside pnv_phb3.c when the bus is removed from the PnvPHB3 device and put into a new parent PnvPHB device. The new pnv_phb3_bus_init() helper will be used by the parent to init the bus when using the PHB3 backend. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-2-danielhb413@gmail.com> --- hw/pci-host/pnv_phb3.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index d58d3c1..058cbab 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -986,6 +986,28 @@ static void pnv_phb3_instance_init(Object *obj) } +void pnv_phb3_bus_init(DeviceState *dev, PnvPHB3 *phb) +{ + PCIHostState *pci = PCI_HOST_BRIDGE(dev); + + /* + * PHB3 doesn't support IO space. However, qemu gets very upset if + * we don't have an IO region to anchor IO BARs onto so we just + * initialize one which we never hook up to anything + */ + memory_region_init(&phb->pci_io, OBJECT(phb), "pci-io", 0x10000); + memory_region_init(&phb->pci_mmio, OBJECT(phb), "pci-mmio", + PCI_MMIO_TOTAL_SIZE); + + pci->bus = pci_register_root_bus(dev, + dev->id ? dev->id : NULL, + pnv_phb3_set_irq, pnv_phb3_map_irq, phb, + &phb->pci_mmio, &phb->pci_io, + 0, 4, TYPE_PNV_PHB3_ROOT_BUS); + + pci_setup_iommu(pci->bus, pnv_phb3_dma_iommu, phb); +} + static void pnv_phb3_realize(DeviceState *dev, Error **errp) { PnvPHB3 *phb = PNV_PHB3(dev); @@ -1035,22 +1057,7 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp) memory_region_init_io(&phb->mr_regs, OBJECT(phb), &pnv_phb3_reg_ops, phb, "phb3-regs", 0x1000); - /* - * PHB3 doesn't support IO space. However, qemu gets very upset if - * we don't have an IO region to anchor IO BARs onto so we just - * initialize one which we never hook up to anything - */ - memory_region_init(&phb->pci_io, OBJECT(phb), "pci-io", 0x10000); - memory_region_init(&phb->pci_mmio, OBJECT(phb), "pci-mmio", - PCI_MMIO_TOTAL_SIZE); - - pci->bus = pci_register_root_bus(dev, - dev->id ? dev->id : NULL, - pnv_phb3_set_irq, pnv_phb3_map_irq, phb, - &phb->pci_mmio, &phb->pci_io, - 0, 4, TYPE_PNV_PHB3_ROOT_BUS); - - pci_setup_iommu(pci->bus, pnv_phb3_dma_iommu, phb); + pnv_phb3_bus_init(dev, phb); pnv_phb_attach_root_port(pci, TYPE_PNV_PHB3_ROOT_PORT, phb->phb_id, phb->chip_id); -- cgit v1.1 From e4e6db5283f775e44879246c6c93cb2462cf742f Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:11 -0300 Subject: ppc/pnv: add PnvPHB base/proxy device The PnvPHB device is going to be the base device for all other powernv PHBs. It consists of a device that has the same user API as the other PHB, namely being a PCIHostBridge and having chip-id and index properties. It also has a 'backend' pointer that will be initialized with the PHB implementation that the device is going to use. The initialization of the PHB backend is done by checking the PHB version via a 'version' attribute that can be set via a global machine property. The 'version' field will be used to make adjustments based on the running version, e.g. PHB3 uses a 'chip' reference while PHB4 uses 'pec'. To init the PnvPHB bus we'll rely on helpers for each version. The version 3 helper is already added (pnv_phb3_bus_init), the PHB4 helper will be added later on. For now let's add the basic logic of the PnvPHB object, which consists mostly of pnv_phb_realize() doing all the work of checking the phb->version set, initializing the proper backend, passing through its attributes to the chosen backend, finalizing the backend realize and adding a root port in the end. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-3-danielhb413@gmail.com> --- hw/pci-host/meson.build | 3 +- hw/pci-host/pnv_phb.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++ hw/pci-host/pnv_phb.h | 39 +++++++++++++++ 3 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 hw/pci-host/pnv_phb.c create mode 100644 hw/pci-host/pnv_phb.h (limited to 'hw/pci-host') diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build index c07596d..e832bab 100644 --- a/hw/pci-host/meson.build +++ b/hw/pci-host/meson.build @@ -35,5 +35,6 @@ specific_ss.add(when: 'CONFIG_PCI_POWERNV', if_true: files( 'pnv_phb3_msi.c', 'pnv_phb3_pbcq.c', 'pnv_phb4.c', - 'pnv_phb4_pec.c' + 'pnv_phb4_pec.c', + 'pnv_phb.c', )) diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c new file mode 100644 index 0000000..6fefff7 --- /dev/null +++ b/hw/pci-host/pnv_phb.c @@ -0,0 +1,124 @@ +/* + * QEMU PowerPC PowerNV Proxy PHB model + * + * Copyright (c) 2022, IBM Corporation. + * + * This code is licensed under the GPL version 2 or later. See the + * COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/visitor.h" +#include "qapi/error.h" +#include "hw/pci-host/pnv_phb.h" +#include "hw/pci-host/pnv_phb3.h" +#include "hw/pci-host/pnv_phb4.h" +#include "hw/ppc/pnv.h" +#include "hw/qdev-properties.h" +#include "qom/object.h" + + +static void pnv_phb_realize(DeviceState *dev, Error **errp) +{ + PnvPHB *phb = PNV_PHB(dev); + PCIHostState *pci = PCI_HOST_BRIDGE(dev); + g_autofree char *phb_typename = NULL; + g_autofree char *phb_rootport_typename = NULL; + + if (!phb->version) { + error_setg(errp, "version not specified"); + return; + } + + switch (phb->version) { + case 3: + phb_typename = g_strdup(TYPE_PNV_PHB3); + phb_rootport_typename = g_strdup(TYPE_PNV_PHB3_ROOT_PORT); + break; + case 4: + phb_typename = g_strdup(TYPE_PNV_PHB4); + phb_rootport_typename = g_strdup(TYPE_PNV_PHB4_ROOT_PORT); + break; + case 5: + phb_typename = g_strdup(TYPE_PNV_PHB5); + phb_rootport_typename = g_strdup(TYPE_PNV_PHB5_ROOT_PORT); + break; + default: + g_assert_not_reached(); + } + + phb->backend = object_new(phb_typename); + object_property_add_child(OBJECT(dev), "phb-backend", phb->backend); + + /* Passthrough child device properties to the proxy device */ + object_property_set_uint(phb->backend, "index", phb->phb_id, errp); + object_property_set_uint(phb->backend, "chip-id", phb->chip_id, errp); + object_property_set_link(phb->backend, "phb-base", OBJECT(phb), errp); + + if (phb->version == 3) { + object_property_set_link(phb->backend, "chip", + OBJECT(phb->chip), errp); + } else { + object_property_set_link(phb->backend, "pec", OBJECT(phb->pec), errp); + } + + if (!qdev_realize(DEVICE(phb->backend), NULL, errp)) { + return; + } + + if (phb->version == 3) { + pnv_phb3_bus_init(dev, PNV_PHB3(phb->backend)); + } + + pnv_phb_attach_root_port(pci, phb_rootport_typename, + phb->phb_id, phb->chip_id); +} + +static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge, + PCIBus *rootbus) +{ + PnvPHB *phb = PNV_PHB(host_bridge); + + snprintf(phb->bus_path, sizeof(phb->bus_path), "00%02x:%02x", + phb->chip_id, phb->phb_id); + return phb->bus_path; +} + +static Property pnv_phb_properties[] = { + DEFINE_PROP_UINT32("index", PnvPHB, phb_id, 0), + DEFINE_PROP_UINT32("chip-id", PnvPHB, chip_id, 0), + DEFINE_PROP_UINT32("version", PnvPHB, version, 0), + + DEFINE_PROP_LINK("chip", PnvPHB, chip, TYPE_PNV_CHIP, PnvChip *), + + DEFINE_PROP_LINK("pec", PnvPHB, pec, TYPE_PNV_PHB4_PEC, + PnvPhb4PecState *), + + DEFINE_PROP_END_OF_LIST(), +}; + +static void pnv_phb_class_init(ObjectClass *klass, void *data) +{ + PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + hc->root_bus_path = pnv_phb_root_bus_path; + dc->realize = pnv_phb_realize; + device_class_set_props(dc, pnv_phb_properties); + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->user_creatable = false; +} + +static void pnv_phb_register_type(void) +{ + static const TypeInfo pnv_phb_type_info = { + .name = TYPE_PNV_PHB, + .parent = TYPE_PCIE_HOST_BRIDGE, + .instance_size = sizeof(PnvPHB), + .class_init = pnv_phb_class_init, + }; + + type_register_static(&pnv_phb_type_info); +} +type_init(pnv_phb_register_type) diff --git a/hw/pci-host/pnv_phb.h b/hw/pci-host/pnv_phb.h new file mode 100644 index 0000000..a7cc861 --- /dev/null +++ b/hw/pci-host/pnv_phb.h @@ -0,0 +1,39 @@ +/* + * QEMU PowerPC PowerNV Proxy PHB model + * + * Copyright (c) 2022, IBM Corporation. + * + * This code is licensed under the GPL version 2 or later. See the + * COPYING file in the top-level directory. + */ + +#ifndef PCI_HOST_PNV_PHB_H +#define PCI_HOST_PNV_PHB_H + +#include "hw/pci/pcie_host.h" +#include "hw/pci/pcie_port.h" +#include "qom/object.h" + +typedef struct PnvChip PnvChip; +typedef struct PnvPhb4PecState PnvPhb4PecState; + +struct PnvPHB { + PCIExpressHost parent_obj; + + uint32_t chip_id; + uint32_t phb_id; + uint32_t version; + char bus_path[8]; + + PnvChip *chip; + + PnvPhb4PecState *pec; + + /* The PHB backend (PnvPHB3, PnvPHB4 ...) being used */ + Object *backend; +}; + +#define TYPE_PNV_PHB "pnv-phb" +OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB, PNV_PHB) + +#endif /* PCI_HOST_PNV_PHB_H */ -- cgit v1.1 From 1f5d6b2ad14df9daad17e81d9e247bd1fd2fd5fc Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:12 -0300 Subject: ppc/pnv: turn PnvPHB3 into a PnvPHB backend We need a handful of changes that needs to be done in a single swoop to turn PnvPHB3 into a PnvPHB backend. In the PnvPHB3, since the PnvPHB device implements PCIExpressHost and will hold the PCI bus, change PnvPHB3 parent to TYPE_DEVICE. There are a couple of instances in pnv_phb3.c that needs to access the PCI bus, so a phb_base pointer is added to allow access to the parent PnvPHB. The PnvPHB3 root port will now be connected to a PnvPHB object. In pnv.c, the powernv8 machine chip8 will now hold an array of PnvPHB objects. pnv_get_phb3_child() needs to be adapted to return the PnvPHB3 backend from the PnvPHB child. A global property is added in pnv_machine_power8_class_init() to ensure that all PnvPHBs are created with phb->version = 3. After all these changes we're still able to boot a powernv8 machine with default settings. The real gain will come with user created PnvPHB devices, coming up next. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-4-danielhb413@gmail.com> --- hw/pci-host/pnv_phb3.c | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index 058cbab..ad9e983 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -11,6 +11,7 @@ #include "qapi/visitor.h" #include "qapi/error.h" #include "hw/pci-host/pnv_phb3_regs.h" +#include "hw/pci-host/pnv_phb.h" #include "hw/pci-host/pnv_phb3.h" #include "hw/pci/pcie_host.h" #include "hw/pci/pcie_port.h" @@ -26,7 +27,7 @@ static PCIDevice *pnv_phb3_find_cfg_dev(PnvPHB3 *phb) { - PCIHostState *pci = PCI_HOST_BRIDGE(phb); + PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base); uint64_t addr = phb->regs[PHB_CONFIG_ADDRESS >> 3]; uint8_t bus, devfn; @@ -590,7 +591,7 @@ void pnv_phb3_reg_write(void *opaque, hwaddr off, uint64_t val, unsigned size) uint64_t pnv_phb3_reg_read(void *opaque, hwaddr off, unsigned size) { PnvPHB3 *phb = opaque; - PCIHostState *pci = PCI_HOST_BRIDGE(phb); + PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base); uint64_t val; if ((off & 0xfffc) == PHB_CONFIG_DATA) { @@ -1011,7 +1012,6 @@ void pnv_phb3_bus_init(DeviceState *dev, PnvPHB3 *phb) static void pnv_phb3_realize(DeviceState *dev, Error **errp) { PnvPHB3 *phb = PNV_PHB3(dev); - PCIHostState *pci = PCI_HOST_BRIDGE(dev); PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); int i; @@ -1056,11 +1056,6 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp) /* Controller Registers */ memory_region_init_io(&phb->mr_regs, OBJECT(phb), &pnv_phb3_reg_ops, phb, "phb3-regs", 0x1000); - - pnv_phb3_bus_init(dev, phb); - - pnv_phb_attach_root_port(pci, TYPE_PNV_PHB3_ROOT_PORT, - phb->phb_id, phb->chip_id); } void pnv_phb3_update_regions(PnvPHB3 *phb) @@ -1085,38 +1080,26 @@ void pnv_phb3_update_regions(PnvPHB3 *phb) pnv_phb3_check_all_m64s(phb); } -static const char *pnv_phb3_root_bus_path(PCIHostState *host_bridge, - PCIBus *rootbus) -{ - PnvPHB3 *phb = PNV_PHB3(host_bridge); - - snprintf(phb->bus_path, sizeof(phb->bus_path), "00%02x:%02x", - phb->chip_id, phb->phb_id); - return phb->bus_path; -} - static Property pnv_phb3_properties[] = { DEFINE_PROP_UINT32("index", PnvPHB3, phb_id, 0), DEFINE_PROP_UINT32("chip-id", PnvPHB3, chip_id, 0), DEFINE_PROP_LINK("chip", PnvPHB3, chip, TYPE_PNV_CHIP, PnvChip *), + DEFINE_PROP_LINK("phb-base", PnvPHB3, phb_base, TYPE_PNV_PHB, PnvPHB *), DEFINE_PROP_END_OF_LIST(), }; static void pnv_phb3_class_init(ObjectClass *klass, void *data) { - PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - hc->root_bus_path = pnv_phb3_root_bus_path; dc->realize = pnv_phb3_realize; device_class_set_props(dc, pnv_phb3_properties); - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->user_creatable = false; } static const TypeInfo pnv_phb3_type_info = { .name = TYPE_PNV_PHB3, - .parent = TYPE_PCIE_HOST_BRIDGE, + .parent = TYPE_DEVICE, .instance_size = sizeof(PnvPHB3), .class_init = pnv_phb3_class_init, .instance_init = pnv_phb3_instance_init, -- cgit v1.1 From fe5bfd4bb816faa1b3fa8c3c23165cdbadfa5c91 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:13 -0300 Subject: ppc/pnv: add PHB4 bus init helper Similar to what we already did for the PnvPHB3 device, let's add a helper to init the bus when using a PnvPHB4. This helper will be used by PnvPHb when PnvPHB4 turns into a backend. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-5-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 2 ++ hw/pci-host/pnv_phb4.c | 39 +++++++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 16 deletions(-) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index 6fefff7..abcbcca 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -69,6 +69,8 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) if (phb->version == 3) { pnv_phb3_bus_init(dev, PNV_PHB3(phb->backend)); + } else { + pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend)); } pnv_phb_attach_root_port(pci, phb_rootport_typename, diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 67ddde4..a742592 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1528,30 +1528,16 @@ static void pnv_phb4_instance_init(Object *obj) object_initialize_child(obj, "source", &phb->xsrc, TYPE_XIVE_SOURCE); } -static void pnv_phb4_realize(DeviceState *dev, Error **errp) +void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb) { - PnvPHB4 *phb = PNV_PHB4(dev); - PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(phb->pec); PCIHostState *pci = PCI_HOST_BRIDGE(dev); - XiveSource *xsrc = &phb->xsrc; - int nr_irqs; char name[32]; - /* Set the "big_phb" flag */ - phb->big_phb = phb->phb_id == 0 || phb->phb_id == 3; - - /* Controller Registers */ - snprintf(name, sizeof(name), "phb4-%d.%d-regs", phb->chip_id, - phb->phb_id); - memory_region_init_io(&phb->mr_regs, OBJECT(phb), &pnv_phb4_reg_ops, phb, - name, 0x2000); - /* * PHB4 doesn't support IO space. However, qemu gets very upset if * we don't have an IO region to anchor IO BARs onto so we just * initialize one which we never hook up to anything */ - snprintf(name, sizeof(name), "phb4-%d.%d-pci-io", phb->chip_id, phb->phb_id); memory_region_init(&phb->pci_io, OBJECT(phb), name, 0x10000); @@ -1561,12 +1547,33 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) memory_region_init(&phb->pci_mmio, OBJECT(phb), name, PCI_MMIO_TOTAL_SIZE); - pci->bus = pci_register_root_bus(dev, dev->id, + pci->bus = pci_register_root_bus(dev, dev->id ? dev->id : NULL, pnv_phb4_set_irq, pnv_phb4_map_irq, phb, &phb->pci_mmio, &phb->pci_io, 0, 4, TYPE_PNV_PHB4_ROOT_BUS); pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb); pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; +} + +static void pnv_phb4_realize(DeviceState *dev, Error **errp) +{ + PnvPHB4 *phb = PNV_PHB4(dev); + PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(phb->pec); + PCIHostState *pci = PCI_HOST_BRIDGE(dev); + XiveSource *xsrc = &phb->xsrc; + int nr_irqs; + char name[32]; + + /* Set the "big_phb" flag */ + phb->big_phb = phb->phb_id == 0 || phb->phb_id == 3; + + /* Controller Registers */ + snprintf(name, sizeof(name), "phb4-%d.%d-regs", phb->chip_id, + phb->phb_id); + memory_region_init_io(&phb->mr_regs, OBJECT(phb), &pnv_phb4_reg_ops, phb, + name, 0x2000); + + pnv_phb4_bus_init(dev, phb); /* Add a single Root port if running with defaults */ pnv_phb_attach_root_port(pci, pecc->rp_model, -- cgit v1.1 From 210aacb3b92707ecc5de811c743322ca395c0fa6 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:14 -0300 Subject: ppc/pnv: turn PnvPHB4 into a PnvPHB backend Change the parent type of the PnvPHB4 device to TYPE_PARENT since the PCI bus is going to be initialized by the PnvPHB parent. Functions that needs to access the bus via a PnvPHB4 object can do so via the phb4->phb_base pointer. pnv_phb4_pec now creates a PnvPHB object. The powernv9 machine class will create PnvPHB devices with version '4'. powernv10 will create using version '5'. Both are using global machine properties in their class_init() to do that. These changes will benefit us when adding PnvPHB user creatable devices for powernv9 and powernv10. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-6-danielhb413@gmail.com> --- hw/pci-host/pnv_phb4.c | 30 +++++------------------------- hw/pci-host/pnv_phb4_pec.c | 3 +-- 2 files changed, 6 insertions(+), 27 deletions(-) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index a742592..144c437 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -33,7 +33,7 @@ static PCIDevice *pnv_phb4_find_cfg_dev(PnvPHB4 *phb) { - PCIHostState *pci = PCI_HOST_BRIDGE(phb); + PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base); uint64_t addr = phb->regs[PHB_CONFIG_ADDRESS >> 3]; uint8_t bus, devfn; @@ -129,7 +129,7 @@ static uint64_t pnv_phb4_config_read(PnvPHB4 *phb, unsigned off, static void pnv_phb4_rc_config_write(PnvPHB4 *phb, unsigned off, unsigned size, uint64_t val) { - PCIHostState *pci = PCI_HOST_BRIDGE(phb); + PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base); PCIDevice *pdev; if (size != 4) { @@ -150,7 +150,7 @@ static void pnv_phb4_rc_config_write(PnvPHB4 *phb, unsigned off, static uint64_t pnv_phb4_rc_config_read(PnvPHB4 *phb, unsigned off, unsigned size) { - PCIHostState *pci = PCI_HOST_BRIDGE(phb); + PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base); PCIDevice *pdev; uint64_t val; @@ -1558,8 +1558,6 @@ void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb) static void pnv_phb4_realize(DeviceState *dev, Error **errp) { PnvPHB4 *phb = PNV_PHB4(dev); - PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(phb->pec); - PCIHostState *pci = PCI_HOST_BRIDGE(dev); XiveSource *xsrc = &phb->xsrc; int nr_irqs; char name[32]; @@ -1573,12 +1571,6 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) memory_region_init_io(&phb->mr_regs, OBJECT(phb), &pnv_phb4_reg_ops, phb, name, 0x2000); - pnv_phb4_bus_init(dev, phb); - - /* Add a single Root port if running with defaults */ - pnv_phb_attach_root_port(pci, pecc->rp_model, - phb->phb_id, phb->chip_id); - /* Setup XIVE Source */ if (phb->big_phb) { nr_irqs = PNV_PHB4_MAX_INTs; @@ -1598,16 +1590,6 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) pnv_phb4_xscom_realize(phb); } -static const char *pnv_phb4_root_bus_path(PCIHostState *host_bridge, - PCIBus *rootbus) -{ - PnvPHB4 *phb = PNV_PHB4(host_bridge); - - snprintf(phb->bus_path, sizeof(phb->bus_path), "00%02x:%02x", - phb->chip_id, phb->phb_id); - return phb->bus_path; -} - /* * Address base trigger mode (POWER10) * @@ -1692,19 +1674,17 @@ static Property pnv_phb4_properties[] = { DEFINE_PROP_UINT32("chip-id", PnvPHB4, chip_id, 0), DEFINE_PROP_LINK("pec", PnvPHB4, pec, TYPE_PNV_PHB4_PEC, PnvPhb4PecState *), + DEFINE_PROP_LINK("phb-base", PnvPHB4, phb_base, TYPE_PNV_PHB, PnvPHB *), DEFINE_PROP_END_OF_LIST(), }; static void pnv_phb4_class_init(ObjectClass *klass, void *data) { - PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); XiveNotifierClass *xfc = XIVE_NOTIFIER_CLASS(klass); - hc->root_bus_path = pnv_phb4_root_bus_path; dc->realize = pnv_phb4_realize; device_class_set_props(dc, pnv_phb4_properties); - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->user_creatable = false; xfc->notify = pnv_phb4_xive_notify; @@ -1712,7 +1692,7 @@ static void pnv_phb4_class_init(ObjectClass *klass, void *data) static const TypeInfo pnv_phb4_type_info = { .name = TYPE_PNV_PHB4, - .parent = TYPE_PCIE_HOST_BRIDGE, + .parent = TYPE_DEVICE, .instance_init = pnv_phb4_instance_init, .instance_size = sizeof(PnvPHB4), .class_init = pnv_phb4_class_init, diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index c9aaf1c..4a0a9fb 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -115,8 +115,7 @@ static void pnv_pec_default_phb_realize(PnvPhb4PecState *pec, int stack_no, Error **errp) { - PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); - PnvPHB4 *phb = PNV_PHB4(qdev_new(pecc->phb_type)); + PnvPHB *phb = PNV_PHB(qdev_new(TYPE_PNV_PHB)); int phb_id = pnv_phb4_pec_get_phb_id(pec, stack_no); object_property_add_child(OBJECT(pec), "phb[*]", OBJECT(phb)); -- cgit v1.1 From 5ba76b61a2d3c90daa264bbaa14464eb3c49caa9 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:15 -0300 Subject: ppc/pnv: add pnv-phb-root-port device We have two very similar root-port devices, pnv-phb3-root-port and pnv-phb4-root-port. Both consist of a wrapper around the PCIESlot device that, until now, has no additional attributes. The main difference between the PHB3 and PHB4 root ports is that pnv-phb4-root-port has the pnv_phb4_root_port_reset() callback. All other differences can be merged in a single device without too much trouble. This patch introduces the unified pnv-phb-root-port that, in time, will be used as the default root port for the pnv-phb device. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-7-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++---- hw/pci-host/pnv_phb.h | 16 +++++++ 2 files changed, 123 insertions(+), 8 deletions(-) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index abcbcca..5e61f85 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -112,15 +112,114 @@ static void pnv_phb_class_init(ObjectClass *klass, void *data) dc->user_creatable = false; } -static void pnv_phb_register_type(void) +static void pnv_phb_root_port_reset(DeviceState *dev) { - static const TypeInfo pnv_phb_type_info = { - .name = TYPE_PNV_PHB, - .parent = TYPE_PCIE_HOST_BRIDGE, - .instance_size = sizeof(PnvPHB), - .class_init = pnv_phb_class_init, - }; + PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); + PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(dev); + PCIDevice *d = PCI_DEVICE(dev); + uint8_t *conf = d->config; + rpc->parent_reset(dev); + + if (phb_rp->version == 3) { + return; + } + + /* PHB4 and later requires these extra reset steps */ + pci_byte_test_and_set_mask(conf + PCI_IO_BASE, + PCI_IO_RANGE_MASK & 0xff); + pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT, + PCI_IO_RANGE_MASK & 0xff); + pci_set_word(conf + PCI_MEMORY_BASE, 0); + pci_set_word(conf + PCI_MEMORY_LIMIT, 0xfff0); + pci_set_word(conf + PCI_PREF_MEMORY_BASE, 0x1); + pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, 0xfff1); + pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */ + pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0xffffffff); + pci_config_set_interrupt_pin(conf, 0); +} + +static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp) +{ + PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); + PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(dev); + PCIDevice *pci = PCI_DEVICE(dev); + uint16_t device_id = 0; + Error *local_err = NULL; + + rpc->parent_realize(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + switch (phb_rp->version) { + case 3: + device_id = PNV_PHB3_DEVICE_ID; + break; + case 4: + device_id = PNV_PHB4_DEVICE_ID; + break; + case 5: + device_id = PNV_PHB5_DEVICE_ID; + break; + default: + g_assert_not_reached(); + } + + pci_config_set_device_id(pci->config, device_id); + pci_config_set_interrupt_pin(pci->config, 0); +} + +static Property pnv_phb_root_port_properties[] = { + DEFINE_PROP_UINT32("version", PnvPHBRootPort, version, 0), + + DEFINE_PROP_END_OF_LIST(), +}; + +static void pnv_phb_root_port_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass); + + dc->desc = "IBM PHB PCIE Root Port"; + + device_class_set_props(dc, pnv_phb_root_port_properties); + device_class_set_parent_realize(dc, pnv_phb_root_port_realize, + &rpc->parent_realize); + device_class_set_parent_reset(dc, pnv_phb_root_port_reset, + &rpc->parent_reset); + dc->reset = &pnv_phb_root_port_reset; + dc->user_creatable = false; + + k->vendor_id = PCI_VENDOR_ID_IBM; + /* device_id will be written during realize() */ + k->device_id = 0; + k->revision = 0; + + rpc->exp_offset = 0x48; + rpc->aer_offset = 0x100; +} + +static const TypeInfo pnv_phb_type_info = { + .name = TYPE_PNV_PHB, + .parent = TYPE_PCIE_HOST_BRIDGE, + .instance_size = sizeof(PnvPHB), + .class_init = pnv_phb_class_init, +}; + +static const TypeInfo pnv_phb_root_port_info = { + .name = TYPE_PNV_PHB_ROOT_PORT, + .parent = TYPE_PCIE_ROOT_PORT, + .instance_size = sizeof(PnvPHBRootPort), + .class_init = pnv_phb_root_port_class_init, +}; + +static void pnv_phb_register_types(void) +{ type_register_static(&pnv_phb_type_info); + type_register_static(&pnv_phb_root_port_info); } -type_init(pnv_phb_register_type) + +type_init(pnv_phb_register_types) diff --git a/hw/pci-host/pnv_phb.h b/hw/pci-host/pnv_phb.h index a7cc861..58ebd6d 100644 --- a/hw/pci-host/pnv_phb.h +++ b/hw/pci-host/pnv_phb.h @@ -36,4 +36,20 @@ struct PnvPHB { #define TYPE_PNV_PHB "pnv-phb" OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB, PNV_PHB) +/* + * PHB PCIe Root port + */ +#define PNV_PHB3_DEVICE_ID 0x03dc +#define PNV_PHB4_DEVICE_ID 0x04c1 +#define PNV_PHB5_DEVICE_ID 0x0652 + +typedef struct PnvPHBRootPort { + PCIESlot parent_obj; + + uint32_t version; +} PnvPHBRootPort; + +#define TYPE_PNV_PHB_ROOT_PORT "pnv-phb-root-port" +OBJECT_DECLARE_SIMPLE_TYPE(PnvPHBRootPort, PNV_PHB_ROOT_PORT) + #endif /* PCI_HOST_PNV_PHB_H */ -- cgit v1.1 From 805150619e47eea910c760e1fde8d3e7e61a3a24 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:16 -0300 Subject: ppc/pnv: remove pnv-phb3-root-port The unified pnv-phb-root-port can be used in its place. There is no ABI breakage in doing so because no official QEMU release introduced user creatable pnv-phb3-root-port devices. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-8-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 2 +- hw/pci-host/pnv_phb3.c | 42 ------------------------------------------ 2 files changed, 1 insertion(+), 43 deletions(-) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index 5e61f85..cdddc6a 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -34,7 +34,7 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) switch (phb->version) { case 3: phb_typename = g_strdup(TYPE_PNV_PHB3); - phb_rootport_typename = g_strdup(TYPE_PNV_PHB3_ROOT_PORT); + phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT); break; case 4: phb_typename = g_strdup(TYPE_PNV_PHB4); diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index ad9e983..d4c04a2 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -1122,51 +1122,9 @@ static const TypeInfo pnv_phb3_root_bus_info = { .class_init = pnv_phb3_root_bus_class_init, }; -static void pnv_phb3_root_port_realize(DeviceState *dev, Error **errp) -{ - PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); - PCIDevice *pci = PCI_DEVICE(dev); - Error *local_err = NULL; - - rpc->parent_realize(dev, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - pci_config_set_interrupt_pin(pci->config, 0); -} - -static void pnv_phb3_root_port_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass); - - dc->desc = "IBM PHB3 PCIE Root Port"; - - device_class_set_parent_realize(dc, pnv_phb3_root_port_realize, - &rpc->parent_realize); - dc->user_creatable = false; - - k->vendor_id = PCI_VENDOR_ID_IBM; - k->device_id = 0x03dc; - k->revision = 0; - - rpc->exp_offset = 0x48; - rpc->aer_offset = 0x100; -} - -static const TypeInfo pnv_phb3_root_port_info = { - .name = TYPE_PNV_PHB3_ROOT_PORT, - .parent = TYPE_PCIE_ROOT_PORT, - .instance_size = sizeof(PnvPHB3RootPort), - .class_init = pnv_phb3_root_port_class_init, -}; - static void pnv_phb3_register_types(void) { type_register_static(&pnv_phb3_root_bus_info); - type_register_static(&pnv_phb3_root_port_info); type_register_static(&pnv_phb3_type_info); type_register_static(&pnv_phb3_iommu_memory_region_info); } -- cgit v1.1 From c8d14603e998ee41313e989cec590c3ec8ddc923 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:17 -0300 Subject: ppc/pnv: remove pnv-phb4-root-port The unified pnv-phb-root-port can be used instead. The phb4-root-port device isn't exposed to the user in any official QEMU release so there's no ABI breakage in removing it. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-9-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 4 +-- hw/pci-host/pnv_phb4.c | 85 ---------------------------------------------- hw/pci-host/pnv_phb4_pec.c | 4 +-- 3 files changed, 4 insertions(+), 89 deletions(-) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index cdddc6a..da729e8 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -38,11 +38,11 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) break; case 4: phb_typename = g_strdup(TYPE_PNV_PHB4); - phb_rootport_typename = g_strdup(TYPE_PNV_PHB4_ROOT_PORT); + phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT); break; case 5: phb_typename = g_strdup(TYPE_PNV_PHB5); - phb_rootport_typename = g_strdup(TYPE_PNV_PHB5_ROOT_PORT); + phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT); break; default: g_assert_not_reached(); diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 144c437..b98c394 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1725,94 +1725,9 @@ static const TypeInfo pnv_phb4_root_bus_info = { .class_init = pnv_phb4_root_bus_class_init, }; -static void pnv_phb4_root_port_reset(DeviceState *dev) -{ - PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); - PCIDevice *d = PCI_DEVICE(dev); - uint8_t *conf = d->config; - - rpc->parent_reset(dev); - - pci_byte_test_and_set_mask(conf + PCI_IO_BASE, - PCI_IO_RANGE_MASK & 0xff); - pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT, - PCI_IO_RANGE_MASK & 0xff); - pci_set_word(conf + PCI_MEMORY_BASE, 0); - pci_set_word(conf + PCI_MEMORY_LIMIT, 0xfff0); - pci_set_word(conf + PCI_PREF_MEMORY_BASE, 0x1); - pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, 0xfff1); - pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */ - pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0xffffffff); - pci_config_set_interrupt_pin(conf, 0); -} - -static void pnv_phb4_root_port_realize(DeviceState *dev, Error **errp) -{ - PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); - Error *local_err = NULL; - - rpc->parent_realize(dev, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } -} - -static void pnv_phb4_root_port_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass); - - dc->desc = "IBM PHB4 PCIE Root Port"; - dc->user_creatable = false; - - device_class_set_parent_realize(dc, pnv_phb4_root_port_realize, - &rpc->parent_realize); - device_class_set_parent_reset(dc, pnv_phb4_root_port_reset, - &rpc->parent_reset); - - k->vendor_id = PCI_VENDOR_ID_IBM; - k->device_id = PNV_PHB4_DEVICE_ID; - k->revision = 0; - - rpc->exp_offset = 0x48; - rpc->aer_offset = 0x100; - - dc->reset = &pnv_phb4_root_port_reset; -} - -static const TypeInfo pnv_phb4_root_port_info = { - .name = TYPE_PNV_PHB4_ROOT_PORT, - .parent = TYPE_PCIE_ROOT_PORT, - .instance_size = sizeof(PnvPHB4RootPort), - .class_init = pnv_phb4_root_port_class_init, -}; - -static void pnv_phb5_root_port_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - dc->desc = "IBM PHB5 PCIE Root Port"; - dc->user_creatable = false; - - k->vendor_id = PCI_VENDOR_ID_IBM; - k->device_id = PNV_PHB5_DEVICE_ID; -} - -static const TypeInfo pnv_phb5_root_port_info = { - .name = TYPE_PNV_PHB5_ROOT_PORT, - .parent = TYPE_PNV_PHB4_ROOT_PORT, - .instance_size = sizeof(PnvPHB4RootPort), - .class_init = pnv_phb5_root_port_class_init, -}; - static void pnv_phb4_register_types(void) { type_register_static(&pnv_phb4_root_bus_info); - type_register_static(&pnv_phb5_root_port_info); - type_register_static(&pnv_phb4_root_port_info); type_register_static(&pnv_phb4_type_info); type_register_static(&pnv_phb5_type_info); type_register_static(&pnv_phb4_iommu_memory_region_info); diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index 4a0a9fb..0ef66b9 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -260,7 +260,7 @@ static void pnv_pec_class_init(ObjectClass *klass, void *data) pecc->version = PNV_PHB4_VERSION; pecc->phb_type = TYPE_PNV_PHB4; pecc->num_phbs = pnv_pec_num_phbs; - pecc->rp_model = TYPE_PNV_PHB4_ROOT_PORT; + pecc->rp_model = TYPE_PNV_PHB_ROOT_PORT; } static const TypeInfo pnv_pec_type_info = { @@ -313,7 +313,7 @@ static void pnv_phb5_pec_class_init(ObjectClass *klass, void *data) pecc->version = PNV_PHB5_VERSION; pecc->phb_type = TYPE_PNV_PHB5; pecc->num_phbs = pnv_phb5_pec_num_stacks; - pecc->rp_model = TYPE_PNV_PHB5_ROOT_PORT; + pecc->rp_model = TYPE_PNV_PHB_ROOT_PORT; } static const TypeInfo pnv_phb5_pec_type_info = { -- cgit v1.1 From 17c681e92ddd66b8a5c425ea6a1c6ec3a4e079d4 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:18 -0300 Subject: ppc/pnv: remove root port name from pnv_phb_attach_root_port() We support only a single root port, PNV_PHB_ROOT_PORT. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-10-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index da729e8..cc15a94 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -24,7 +24,6 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) PnvPHB *phb = PNV_PHB(dev); PCIHostState *pci = PCI_HOST_BRIDGE(dev); g_autofree char *phb_typename = NULL; - g_autofree char *phb_rootport_typename = NULL; if (!phb->version) { error_setg(errp, "version not specified"); @@ -34,15 +33,12 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) switch (phb->version) { case 3: phb_typename = g_strdup(TYPE_PNV_PHB3); - phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT); break; case 4: phb_typename = g_strdup(TYPE_PNV_PHB4); - phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT); break; case 5: phb_typename = g_strdup(TYPE_PNV_PHB5); - phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT); break; default: g_assert_not_reached(); @@ -73,8 +69,7 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend)); } - pnv_phb_attach_root_port(pci, phb_rootport_typename, - phb->phb_id, phb->chip_id); + pnv_phb_attach_root_port(pci, phb->phb_id, phb->chip_id); } static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge, -- cgit v1.1 From cb6a5c26446f797252a479f456da030dc7febb20 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:19 -0300 Subject: ppc/pnv: remove pecc->rp_model The attribute is unused. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-11-danielhb413@gmail.com> --- hw/pci-host/pnv_phb4_pec.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index 0ef66b9..8dc363d 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -260,7 +260,6 @@ static void pnv_pec_class_init(ObjectClass *klass, void *data) pecc->version = PNV_PHB4_VERSION; pecc->phb_type = TYPE_PNV_PHB4; pecc->num_phbs = pnv_pec_num_phbs; - pecc->rp_model = TYPE_PNV_PHB_ROOT_PORT; } static const TypeInfo pnv_pec_type_info = { @@ -313,7 +312,6 @@ static void pnv_phb5_pec_class_init(ObjectClass *klass, void *data) pecc->version = PNV_PHB5_VERSION; pecc->phb_type = TYPE_PNV_PHB5; pecc->num_phbs = pnv_phb5_pec_num_stacks; - pecc->rp_model = TYPE_PNV_PHB_ROOT_PORT; } static const TypeInfo pnv_phb5_pec_type_info = { -- cgit v1.1 From e5ea94360eba4818467283a259d8d681f0da799f Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:21 -0300 Subject: ppc/pnv: move attach_root_port helper to pnv-phb.c The helper is only used in this file. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-13-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index cc15a94..c47ed92 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -18,6 +18,30 @@ #include "hw/qdev-properties.h" #include "qom/object.h" +/* + * Attach a root port device. + * + * 'index' will be used both as a PCIE slot value and to calculate + * QOM id. 'chip_id' is going to be used as PCIE chassis for the + * root port. + */ +static void pnv_phb_attach_root_port(PCIHostState *pci, int index, int chip_id) +{ + PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT); + g_autofree char *default_id = g_strdup_printf("%s[%d]", + TYPE_PNV_PHB_ROOT_PORT, + index); + const char *dev_id = DEVICE(root)->id; + + object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id, + OBJECT(root)); + + /* Set unique chassis/slot values for the root port */ + qdev_prop_set_uint8(DEVICE(root), "chassis", chip_id); + qdev_prop_set_uint16(DEVICE(root), "slot", index); + + pci_realize_and_unref(root, pci->bus, &error_fatal); +} static void pnv_phb_realize(DeviceState *dev, Error **errp) { -- cgit v1.1 From 8ec1e4f1ef974e901b416fef6c3b38a5cc2eeffa Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 11 Aug 2022 13:39:40 -0300 Subject: ppc/pnv: add phb-id/chip-id PnvPHB3RootBus properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We rely on the phb-id and chip-id, which are PHB properties, to assign chassis and slot to the root port. For default devices this is no big deal: the root port is being created under pnv_phb_realize() and the values are being passed on via the 'index' and 'chip-id' of the pnv_phb_attach_root_port() helper. If we want to implement user created root ports we have a problem. The user created root port will not be aware of which PHB it belongs to, unless we're willing to violate QOM best practices and access the PHB via dev->parent_bus->parent. What we can do is to access the root bus parent bus. Since we're already assigning the root port as QOM child of the bus, and the bus is initiated using PHB properties, let's add phb-id and chip-id as properties of the bus. This will allow us trivial access to them, for both user-created and default root ports, without doing anything too shady with QOM. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220811163950.578927-2-danielhb413@gmail.com> --- hw/pci-host/pnv_phb3.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index d4c04a2..af8575c 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -1006,6 +1006,11 @@ void pnv_phb3_bus_init(DeviceState *dev, PnvPHB3 *phb) &phb->pci_mmio, &phb->pci_io, 0, 4, TYPE_PNV_PHB3_ROOT_BUS); + object_property_set_int(OBJECT(pci->bus), "phb-id", phb->phb_id, + &error_abort); + object_property_set_int(OBJECT(pci->bus), "chip-id", phb->chip_id, + &error_abort); + pci_setup_iommu(pci->bus, pnv_phb3_dma_iommu, phb); } @@ -1105,10 +1110,55 @@ static const TypeInfo pnv_phb3_type_info = { .instance_init = pnv_phb3_instance_init, }; +static void pnv_phb3_root_bus_get_prop(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) +{ + PnvPHB3RootBus *bus = PNV_PHB3_ROOT_BUS(obj); + uint64_t value = 0; + + if (strcmp(name, "phb-id") == 0) { + value = bus->phb_id; + } else { + value = bus->chip_id; + } + + visit_type_size(v, name, &value, errp); +} + +static void pnv_phb3_root_bus_set_prop(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) + +{ + PnvPHB3RootBus *bus = PNV_PHB3_ROOT_BUS(obj); + uint64_t value; + + if (!visit_type_size(v, name, &value, errp)) { + return; + } + + if (strcmp(name, "phb-id") == 0) { + bus->phb_id = value; + } else { + bus->chip_id = value; + } +} + static void pnv_phb3_root_bus_class_init(ObjectClass *klass, void *data) { BusClass *k = BUS_CLASS(klass); + object_class_property_add(klass, "phb-id", "int", + pnv_phb3_root_bus_get_prop, + pnv_phb3_root_bus_set_prop, + NULL, NULL); + + object_class_property_add(klass, "chip-id", "int", + pnv_phb3_root_bus_get_prop, + pnv_phb3_root_bus_set_prop, + NULL, NULL); + /* * PHB3 has only a single root complex. Enforce the limit on the * parent bus -- cgit v1.1 From b7c1750dc440bb46ddc38dd0c391d6394db7bdb1 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 11 Aug 2022 13:39:41 -0300 Subject: ppc/pnv: add phb-id/chip-id PnvPHB4RootBus properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The same rationale provided in the PHB3 bus case applies here. Note: we could have merged both buses in a single object, like we did with the root ports, and spare some boilerplate. The reason we opted to preserve both buses objects is twofold: - there's not user side advantage in doing so. Unifying the root ports presents a clear user QOL change when we enable user created devices back. The buses objects, aside from having a different QOM name, is transparent to the user; - we leave a door opened in case we want to increase the root port limit for phb4/5 later on without having to deal with phb3 code. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220811163950.578927-3-danielhb413@gmail.com> --- hw/pci-host/pnv_phb4.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index b98c394..824e1a7 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1551,6 +1551,12 @@ void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb) pnv_phb4_set_irq, pnv_phb4_map_irq, phb, &phb->pci_mmio, &phb->pci_io, 0, 4, TYPE_PNV_PHB4_ROOT_BUS); + + object_property_set_int(OBJECT(pci->bus), "phb-id", phb->phb_id, + &error_abort); + object_property_set_int(OBJECT(pci->bus), "chip-id", phb->chip_id, + &error_abort); + pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb); pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; } @@ -1708,10 +1714,55 @@ static const TypeInfo pnv_phb5_type_info = { .instance_size = sizeof(PnvPHB4), }; +static void pnv_phb4_root_bus_get_prop(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) +{ + PnvPHB4RootBus *bus = PNV_PHB4_ROOT_BUS(obj); + uint64_t value = 0; + + if (strcmp(name, "phb-id") == 0) { + value = bus->phb_id; + } else { + value = bus->chip_id; + } + + visit_type_size(v, name, &value, errp); +} + +static void pnv_phb4_root_bus_set_prop(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) + +{ + PnvPHB4RootBus *bus = PNV_PHB4_ROOT_BUS(obj); + uint64_t value; + + if (!visit_type_size(v, name, &value, errp)) { + return; + } + + if (strcmp(name, "phb-id") == 0) { + bus->phb_id = value; + } else { + bus->chip_id = value; + } +} + static void pnv_phb4_root_bus_class_init(ObjectClass *klass, void *data) { BusClass *k = BUS_CLASS(klass); + object_class_property_add(klass, "phb-id", "int", + pnv_phb4_root_bus_get_prop, + pnv_phb4_root_bus_set_prop, + NULL, NULL); + + object_class_property_add(klass, "chip-id", "int", + pnv_phb4_root_bus_get_prop, + pnv_phb4_root_bus_set_prop, + NULL, NULL); + /* * PHB4 has only a single root complex. Enforce the limit on the * parent bus -- cgit v1.1 From c2f3f78af5fd664f95748ebc918ae86463690249 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 11 Aug 2022 13:39:42 -0300 Subject: ppc/pnv: set root port chassis and slot using Bus properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For default root ports we have a way of accessing chassis and slot, before root_port_realize(), via pnv_phb_attach_root_port(). For the future user created root ports this won't be the case: we can't use this helper because we don't have access to the PHB phb-id/chip-id values. In earlier patches we've added phb-id and chip-id to pnv-phb-root-bus objects. We're now able to use the bus to retrieve them. The bus is reachable for both user created and default devices, so we're changing all the code paths. This also allow us to validate these changes with the existing default devices. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220811163950.578927-4-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index c47ed92..826c0c1 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -25,21 +25,19 @@ * QOM id. 'chip_id' is going to be used as PCIE chassis for the * root port. */ -static void pnv_phb_attach_root_port(PCIHostState *pci, int index, int chip_id) +static void pnv_phb_attach_root_port(PCIHostState *pci) { PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT); - g_autofree char *default_id = g_strdup_printf("%s[%d]", - TYPE_PNV_PHB_ROOT_PORT, - index); const char *dev_id = DEVICE(root)->id; + g_autofree char *default_id = NULL; + int index; + + index = object_property_get_int(OBJECT(pci->bus), "phb-id", &error_fatal); + default_id = g_strdup_printf("%s[%d]", TYPE_PNV_PHB_ROOT_PORT, index); object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id, OBJECT(root)); - /* Set unique chassis/slot values for the root port */ - qdev_prop_set_uint8(DEVICE(root), "chassis", chip_id); - qdev_prop_set_uint16(DEVICE(root), "slot", index); - pci_realize_and_unref(root, pci->bus, &error_fatal); } @@ -93,7 +91,7 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend)); } - pnv_phb_attach_root_port(pci, phb->phb_id, phb->chip_id); + pnv_phb_attach_root_port(pci); } static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge, @@ -162,9 +160,18 @@ static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp) { PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(dev); + PCIBus *bus = PCI_BUS(qdev_get_parent_bus(dev)); PCIDevice *pci = PCI_DEVICE(dev); uint16_t device_id = 0; Error *local_err = NULL; + int chip_id, index; + + chip_id = object_property_get_int(OBJECT(bus), "chip-id", &error_fatal); + index = object_property_get_int(OBJECT(bus), "phb-id", &error_fatal); + + /* Set unique chassis/slot values for the root port */ + qdev_prop_set_uint8(dev, "chassis", chip_id); + qdev_prop_set_uint16(dev, "slot", index); rpc->parent_realize(dev, &local_err); if (local_err) { -- cgit v1.1 From ba47c3a4f888e99dedde1fed740927e973f9bc32 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 11 Aug 2022 13:39:43 -0300 Subject: ppc/pnv: add helpers for pnv-phb user devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pnv_parent_qom_fixup() and pnv_parent_bus_fixup() are versions of the helpers that were reverted by commit 9c10d86fee "ppc/pnv: Remove user-created PHB{3,4,5} devices". They are needed to amend the QOM and bus hierarchies of user created pnv-phbs, matching them with default pnv-phbs. A new helper pnv_phb_user_device_init() is created to handle user-created devices setup. We're going to call it inside pnv_phb_realize() in case we're realizing an user created device. This will centralize all user device realated in a single spot, leaving the realize functions of the phb3/phb4 backends untouched. Another helper called pnv_chip_add_phb() was added to handle the particularities of each chip version when adding a new PHB. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Reviewed-by: Frederic Barrat Message-Id: <20220811163950.578927-5-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index 826c0c1..5dc44f4 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -18,6 +18,38 @@ #include "hw/qdev-properties.h" #include "qom/object.h" + +/* + * Set the QOM parent of an object child. If the device state + * associated with the child has an id, use it as QOM id. Otherwise + * use object_typename[index] as QOM id. + */ +static void pnv_parent_qom_fixup(Object *parent, Object *child, int index) +{ + g_autofree char *default_id = + g_strdup_printf("%s[%d]", object_get_typename(child), index); + const char *dev_id = DEVICE(child)->id; + + if (child->parent == parent) { + return; + } + + object_ref(child); + object_unparent(child); + object_property_add_child(parent, dev_id ? dev_id : default_id, child); + object_unref(child); +} + +static void pnv_parent_bus_fixup(DeviceState *parent, DeviceState *child, + Error **errp) +{ + BusState *parent_bus = qdev_get_parent_bus(parent); + + if (!qdev_set_parent_bus(child, parent_bus, errp)) { + return; + } +} + /* * Attach a root port device. * @@ -41,6 +73,39 @@ static void pnv_phb_attach_root_port(PCIHostState *pci) pci_realize_and_unref(root, pci->bus, &error_fatal); } +/* + * User created devices won't have the initial setup that default + * devices have. This setup consists of assigning a parent device + * (chip for PHB3, PEC for PHB4/5) that will be the QOM/bus parent + * of the PHB. + */ +static bool pnv_phb_user_device_init(PnvPHB *phb, Error **errp) +{ + PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); + PnvChip *chip = pnv_get_chip(pnv, phb->chip_id); + Object *parent = NULL; + + if (!chip) { + error_setg(errp, "invalid chip id: %d", phb->chip_id); + return false; + } + + parent = pnv_chip_add_phb(chip, phb, errp); + if (!parent) { + return false; + } + + /* + * Reparent user created devices to the chip to build + * correctly the device tree. pnv_xscom_dt() needs every + * PHB to be a child of the chip to build the DT correctly. + */ + pnv_parent_qom_fixup(parent, OBJECT(phb), phb->phb_id); + pnv_parent_bus_fixup(DEVICE(chip), DEVICE(phb), errp); + + return true; +} + static void pnv_phb_realize(DeviceState *dev, Error **errp) { PnvPHB *phb = PNV_PHB(dev); @@ -74,6 +139,16 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) object_property_set_uint(phb->backend, "chip-id", phb->chip_id, errp); object_property_set_link(phb->backend, "phb-base", OBJECT(phb), errp); + /* + * Handle user created devices. User devices will not have a + * pointer to a chip (PHB3) and a PEC (PHB4/5). + */ + if (!phb->chip && !phb->pec) { + if (!pnv_phb_user_device_init(phb, errp)) { + return; + } + } + if (phb->version == 3) { object_property_set_link(phb->backend, "chip", OBJECT(phb->chip), errp); -- cgit v1.1 From 892c3ad0d5d6bb9b1e414d61118e93362ecab782 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 11 Aug 2022 13:39:45 -0300 Subject: ppc/pnv: enable user created pnv-phb for powernv8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bulk of the work was already done by previous patches. Use defaults_enabled() to determine whether we need to create the default devices or not. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220811163950.578927-7-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index 5dc44f4..1f53ff7 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -17,6 +17,7 @@ #include "hw/ppc/pnv.h" #include "hw/qdev-properties.h" #include "qom/object.h" +#include "sysemu/sysemu.h" /* @@ -166,6 +167,10 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend)); } + if (phb->version == 3 && !defaults_enabled()) { + return; + } + pnv_phb_attach_root_port(pci); } @@ -201,7 +206,7 @@ static void pnv_phb_class_init(ObjectClass *klass, void *data) dc->realize = pnv_phb_realize; device_class_set_props(dc, pnv_phb_properties); set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - dc->user_creatable = false; + dc->user_creatable = true; } static void pnv_phb_root_port_reset(DeviceState *dev) @@ -292,7 +297,7 @@ static void pnv_phb_root_port_class_init(ObjectClass *klass, void *data) device_class_set_parent_reset(dc, pnv_phb_root_port_reset, &rpc->parent_reset); dc->reset = &pnv_phb_root_port_reset; - dc->user_creatable = false; + dc->user_creatable = true; k->vendor_id = PCI_VENDOR_ID_IBM; /* device_id will be written during realize() */ -- cgit v1.1 From d786be3fe7466ff96db96b86e6fee437136d63d7 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 11 Aug 2022 13:39:47 -0300 Subject: ppc/pnv: enable user created pnv-phb for powernv9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable pnv-phb user created devices for powernv9 now that we have everything in place. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220811163950.578927-9-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 2 +- hw/pci-host/pnv_phb4_pec.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index 1f53ff7..17d9960 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -167,7 +167,7 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend)); } - if (phb->version == 3 && !defaults_enabled()) { + if (!defaults_enabled()) { return; } diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index 8dc363d..9871f46 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -146,8 +146,10 @@ static void pnv_pec_realize(DeviceState *dev, Error **errp) pec->num_phbs = pecc->num_phbs[pec->index]; /* Create PHBs if running with defaults */ - for (i = 0; i < pec->num_phbs; i++) { - pnv_pec_default_phb_realize(pec, i, errp); + if (defaults_enabled()) { + for (i = 0; i < pec->num_phbs; i++) { + pnv_pec_default_phb_realize(pec, i, errp); + } } /* Initialize the XSCOM regions for the PEC registers */ -- cgit v1.1 From 3466bb50ec7c49a63b4a146c82d4030742451f40 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 19 Aug 2022 06:47:47 -0300 Subject: ppc/pnv: consolidate pnv_parent_*_fixup() helpers We have 2 helpers that amends the QOM and parent bus of a given object, repectively. These 2 helpers are called together, and not by accident. Due to QOM internals, doing an object_unparent() will result in the device being removed from its parent bus. This means that changing the QOM parent requires reassigning the parent bus again. Create a single helper called pnv_parent_fixup(), documenting some of the QOM specifics that we're dealing with the unparenting/parenting mechanics, and handle both the QOM and the parent bus assignment. Next patch will make use of this function to handle a case where we need to change the QOM parent while keeping the same parent bus assigned beforehand. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220819094748.400578-2-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index 17d9960..4ea33fb 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -21,34 +21,45 @@ /* - * Set the QOM parent of an object child. If the device state - * associated with the child has an id, use it as QOM id. Otherwise - * use object_typename[index] as QOM id. + * Set the QOM parent and parent bus of an object child. If the device + * state associated with the child has an id, use it as QOM id. + * Otherwise use object_typename[index] as QOM id. + * + * This helper does both operations at the same time because seting + * a new QOM child will erase the bus parent of the device. This happens + * because object_unparent() will call object_property_del_child(), + * which in turn calls the property release callback prop->release if + * it's defined. In our case this callback is set to + * object_finalize_child_property(), which was assigned during the + * first object_property_add_child() call. This callback will end up + * calling device_unparent(), and this function removes the device + * from its parent bus. + * + * The QOM and parent bus to be set aren´t necessarily related, so + * let's receive both as arguments. */ -static void pnv_parent_qom_fixup(Object *parent, Object *child, int index) +static bool pnv_parent_fixup(Object *parent, BusState *parent_bus, + Object *child, int index, + Error **errp) { g_autofree char *default_id = g_strdup_printf("%s[%d]", object_get_typename(child), index); const char *dev_id = DEVICE(child)->id; if (child->parent == parent) { - return; + return true; } object_ref(child); object_unparent(child); object_property_add_child(parent, dev_id ? dev_id : default_id, child); object_unref(child); -} - -static void pnv_parent_bus_fixup(DeviceState *parent, DeviceState *child, - Error **errp) -{ - BusState *parent_bus = qdev_get_parent_bus(parent); - if (!qdev_set_parent_bus(child, parent_bus, errp)) { - return; + if (!qdev_set_parent_bus(DEVICE(child), parent_bus, errp)) { + return false; } + + return true; } /* @@ -101,8 +112,10 @@ static bool pnv_phb_user_device_init(PnvPHB *phb, Error **errp) * correctly the device tree. pnv_xscom_dt() needs every * PHB to be a child of the chip to build the DT correctly. */ - pnv_parent_qom_fixup(parent, OBJECT(phb), phb->phb_id); - pnv_parent_bus_fixup(DEVICE(chip), DEVICE(phb), errp); + if (!pnv_parent_fixup(parent, qdev_get_parent_bus(DEVICE(chip)), + OBJECT(phb), phb->phb_id, errp)) { + return false; + } return true; } -- cgit v1.1 From 6a1e1ce2efb9c22723f9f7cada5d5a31842eb37d Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 19 Aug 2022 06:47:48 -0300 Subject: ppc/pnv: fix QOM parenting of user creatable root ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User creatable root ports are being parented by the 'peripheral' or the 'peripheral-anon' container. This happens because this is the regular QOM schema for sysbus devices that are added via the command line. Let's make this QOM hierarchy similar to what we have with default root ports, i.e. the root port must be parented by the pnv-root-bus. To do that we change the qom and bus parent of the root port during root_port_realize(). The realize() is shared by the default root port code path, so we can remove the code inside pnv_phb_attach_root_port() that was adding the root port as a child of the bus as well. After all that, remove pnv_phb_attach_root_port() and create the root port explictly in the 'default_enabled()' case of pnv_phb_realize(). Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Reviewed-by: Frederic Barrat Message-Id: <20220819094748.400578-3-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 47 ++++++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 27 deletions(-) (limited to 'hw/pci-host') diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index 4ea33fb..7b11f1e 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -63,29 +63,6 @@ static bool pnv_parent_fixup(Object *parent, BusState *parent_bus, } /* - * Attach a root port device. - * - * 'index' will be used both as a PCIE slot value and to calculate - * QOM id. 'chip_id' is going to be used as PCIE chassis for the - * root port. - */ -static void pnv_phb_attach_root_port(PCIHostState *pci) -{ - PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT); - const char *dev_id = DEVICE(root)->id; - g_autofree char *default_id = NULL; - int index; - - index = object_property_get_int(OBJECT(pci->bus), "phb-id", &error_fatal); - default_id = g_strdup_printf("%s[%d]", TYPE_PNV_PHB_ROOT_PORT, index); - - object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id, - OBJECT(root)); - - pci_realize_and_unref(root, pci->bus, &error_fatal); -} - -/* * User created devices won't have the initial setup that default * devices have. This setup consists of assigning a parent device * (chip for PHB3, PEC for PHB4/5) that will be the QOM/bus parent @@ -180,11 +157,11 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend)); } - if (!defaults_enabled()) { - return; - } + if (defaults_enabled()) { + PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT); - pnv_phb_attach_root_port(pci); + pci_realize_and_unref(root, pci->bus, errp); + } } static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge, @@ -259,6 +236,11 @@ static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp) Error *local_err = NULL; int chip_id, index; + /* + * 'index' will be used both as a PCIE slot value and to calculate + * QOM id. 'chip_id' is going to be used as PCIE chassis for the + * root port. + */ chip_id = object_property_get_int(OBJECT(bus), "chip-id", &error_fatal); index = object_property_get_int(OBJECT(bus), "phb-id", &error_fatal); @@ -266,6 +248,17 @@ static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp) qdev_prop_set_uint8(dev, "chassis", chip_id); qdev_prop_set_uint16(dev, "slot", index); + /* + * User created root ports are QOM parented to one of + * the peripheral containers but it's already at the right + * parent bus. Change the QOM parent to be the same as the + * parent bus it's already assigned to. + */ + if (!pnv_parent_fixup(OBJECT(bus), BUS(bus), OBJECT(dev), + index, errp)) { + return; + } + rpc->parent_realize(dev, &local_err); if (local_err) { error_propagate(errp, local_err); -- cgit v1.1