X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=qemu%2Fhw%2Fpci-bridge%2Fpci_expander_bridge.c;fp=qemu%2Fhw%2Fpci-bridge%2Fpci_expander_bridge.c;h=ba320bd857fb9920e7f152b07d155b8de21dba3f;hb=437fd90c0250dee670290f9b714253671a990160;hp=57f8a3762b9667cade0b7de9cd7076abe55d5f91;hpb=5bbd6fe9b8bab2a93e548c5a53b032d1939eec05;p=kvmfornfv.git diff --git a/qemu/hw/pci-bridge/pci_expander_bridge.c b/qemu/hw/pci-bridge/pci_expander_bridge.c index 57f8a3762..ba320bd85 100644 --- a/qemu/hw/pci-bridge/pci_expander_bridge.c +++ b/qemu/hw/pci-bridge/pci_expander_bridge.c @@ -10,6 +10,7 @@ * See the COPYING file in the top-level directory. */ +#include "qemu/osdep.h" #include "hw/pci/pci.h" #include "hw/pci/pci_bus.h" #include "hw/pci/pci_host.h" @@ -23,6 +24,9 @@ #define TYPE_PXB_BUS "pxb-bus" #define PXB_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_BUS) +#define TYPE_PXB_PCIE_BUS "pxb-pcie-bus" +#define PXB_PCIE_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_PCIE_BUS) + typedef struct PXBBus { /*< private >*/ PCIBus parent_obj; @@ -34,6 +38,9 @@ typedef struct PXBBus { #define TYPE_PXB_DEVICE "pxb" #define PXB_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_DEVICE) +#define TYPE_PXB_PCIE_DEVICE "pxb-pcie" +#define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_PCIE_DEVICE) + typedef struct PXBDev { /*< private >*/ PCIDevice parent_obj; @@ -43,13 +50,18 @@ typedef struct PXBDev { uint16_t numa_node; } PXBDev; +static PXBDev *convert_to_pxb(PCIDevice *dev) +{ + return pci_bus_is_express(dev->bus) ? PXB_PCIE_DEV(dev) : PXB_DEV(dev); +} + static GList *pxb_dev_list; #define TYPE_PXB_HOST "pxb-host" static int pxb_bus_num(PCIBus *bus) { - PXBDev *pxb = PXB_DEV(bus->parent_dev); + PXBDev *pxb = convert_to_pxb(bus->parent_dev); return pxb->bus_nr; } @@ -61,7 +73,7 @@ static bool pxb_is_root(PCIBus *bus) static uint16_t pxb_bus_numa_node(PCIBus *bus) { - PXBDev *pxb = PXB_DEV(bus->parent_dev); + PXBDev *pxb = convert_to_pxb(bus->parent_dev); return pxb->numa_node; } @@ -82,10 +94,18 @@ static const TypeInfo pxb_bus_info = { .class_init = pxb_bus_class_init, }; +static const TypeInfo pxb_pcie_bus_info = { + .name = TYPE_PXB_PCIE_BUS, + .parent = TYPE_PCIE_BUS, + .instance_size = sizeof(PXBBus), + .class_init = pxb_bus_class_init, +}; + static const char *pxb_host_root_bus_path(PCIHostState *host_bridge, PCIBus *rootbus) { - PXBBus *bus = PXB_BUS(rootbus); + PXBBus *bus = pci_bus_is_express(rootbus) ? + PXB_PCIE_BUS(rootbus) : PXB_BUS(rootbus); snprintf(bus->bus_path, 8, "0000:%02x", pxb_bus_num(rootbus)); return bus->bus_path; @@ -103,7 +123,7 @@ static char *pxb_host_ofw_unit_address(const SysBusDevice *dev) pxb_host = PCI_HOST_BRIDGE(dev); pxb_bus = pxb_host->bus; - pxb_dev = PXB_DEV(pxb_bus->parent_dev); + pxb_dev = convert_to_pxb(pxb_bus->parent_dev); position = g_list_index(pxb_dev_list, pxb_dev); assert(position >= 0); @@ -193,10 +213,10 @@ static gint pxb_compare(gconstpointer a, gconstpointer b) 0; } -static int pxb_dev_initfn(PCIDevice *dev) +static int pxb_dev_init_common(PCIDevice *dev, bool pcie) { - PXBDev *pxb = PXB_DEV(dev); - DeviceState *ds, *bds; + PXBDev *pxb = convert_to_pxb(dev); + DeviceState *ds, *bds = NULL; PCIBus *bus; const char *dev_name = NULL; @@ -211,26 +231,31 @@ static int pxb_dev_initfn(PCIDevice *dev) } ds = qdev_create(NULL, TYPE_PXB_HOST); - bus = pci_bus_new(ds, "pxb-internal", NULL, NULL, 0, TYPE_PXB_BUS); + if (pcie) { + bus = pci_bus_new(ds, dev_name, NULL, NULL, 0, TYPE_PXB_PCIE_BUS); + } else { + bus = pci_bus_new(ds, "pxb-internal", NULL, NULL, 0, TYPE_PXB_BUS); + bds = qdev_create(BUS(bus), "pci-bridge"); + bds->id = dev_name; + qdev_prop_set_uint8(bds, PCI_BRIDGE_DEV_PROP_CHASSIS_NR, pxb->bus_nr); + qdev_prop_set_bit(bds, PCI_BRIDGE_DEV_PROP_SHPC, false); + } bus->parent_dev = dev; bus->address_space_mem = dev->bus->address_space_mem; bus->address_space_io = dev->bus->address_space_io; bus->map_irq = pxb_map_irq_fn; - bds = qdev_create(BUS(bus), "pci-bridge"); - bds->id = dev_name; - qdev_prop_set_uint8(bds, PCI_BRIDGE_DEV_PROP_CHASSIS_NR, pxb->bus_nr); - qdev_prop_set_bit(bds, PCI_BRIDGE_DEV_PROP_SHPC, false); - PCI_HOST_BRIDGE(ds)->bus = bus; if (pxb_register_bus(dev, bus)) { - return -EINVAL; + goto err_register_bus; } qdev_init_nofail(ds); - qdev_init_nofail(bds); + if (bds) { + qdev_init_nofail(bds); + } pci_word_test_and_set_mask(dev->config + PCI_STATUS, PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK); @@ -238,17 +263,33 @@ static int pxb_dev_initfn(PCIDevice *dev) pxb_dev_list = g_list_insert_sorted(pxb_dev_list, pxb, pxb_compare); return 0; + +err_register_bus: + object_unref(OBJECT(bds)); + object_unparent(OBJECT(bus)); + object_unref(OBJECT(ds)); + return -EINVAL; +} + +static int pxb_dev_initfn(PCIDevice *dev) +{ + if (pci_bus_is_express(dev->bus)) { + error_report("pxb devices cannot reside on a PCIe bus!"); + return -EINVAL; + } + + return pxb_dev_init_common(dev, false); } static void pxb_dev_exitfn(PCIDevice *pci_dev) { - PXBDev *pxb = PXB_DEV(pci_dev); + PXBDev *pxb = convert_to_pxb(pci_dev); pxb_dev_list = g_list_remove(pxb_dev_list, pxb); } static Property pxb_dev_properties[] = { - /* Note: 0 is not a legal a PXB bus number. */ + /* Note: 0 is not a legal PXB bus number. */ DEFINE_PROP_UINT8("bus_nr", PXBDev, bus_nr, 0), DEFINE_PROP_UINT16("numa_node", PXBDev, numa_node, NUMA_NODE_UNASSIGNED), DEFINE_PROP_END_OF_LIST(), @@ -267,6 +308,7 @@ static void pxb_dev_class_init(ObjectClass *klass, void *data) dc->desc = "PCI Expander Bridge"; dc->props = pxb_dev_properties; + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); } static const TypeInfo pxb_dev_info = { @@ -276,11 +318,46 @@ static const TypeInfo pxb_dev_info = { .class_init = pxb_dev_class_init, }; +static int pxb_pcie_dev_initfn(PCIDevice *dev) +{ + if (!pci_bus_is_express(dev->bus)) { + error_report("pxb-pcie devices cannot reside on a PCI bus!"); + return -EINVAL; + } + + return pxb_dev_init_common(dev, true); +} + +static void pxb_pcie_dev_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->init = pxb_pcie_dev_initfn; + k->exit = pxb_dev_exitfn; + k->vendor_id = PCI_VENDOR_ID_REDHAT; + k->device_id = PCI_DEVICE_ID_REDHAT_PXB_PCIE; + k->class_id = PCI_CLASS_BRIDGE_HOST; + + dc->desc = "PCI Express Expander Bridge"; + dc->props = pxb_dev_properties; + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); +} + +static const TypeInfo pxb_pcie_dev_info = { + .name = TYPE_PXB_PCIE_DEVICE, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(PXBDev), + .class_init = pxb_pcie_dev_class_init, +}; + static void pxb_register_types(void) { type_register_static(&pxb_bus_info); + type_register_static(&pxb_pcie_bus_info); type_register_static(&pxb_host_info); type_register_static(&pxb_dev_info); + type_register_static(&pxb_pcie_dev_info); } type_init(pxb_register_types)