pxb-pcie resides in pci domain 0 by default and users can not specify the domain number. This patch adds 2 new property 'domain_nr' and 'max_bus' to pxb-pcie device.
The first property allows user to choose a non-zero pci domain so that they can hopefully add more pcie devices without being restricted by the 256 bus number of a single pci domain. The second property max_bus allows user to specify the desired busses to be used in the new domain. Since each pcie bus needs 1MB config space, a full pci domain occupies 256MB, which is quite expensive. But most times user may only want a sub-range of busses(e.g. [3,9]), this is when max_bus becomes useful. By reducing the memory each domain consumes, we can support more domains in a limited space. Signed-off-by: Zihan Yang <whois.zihan.y...@gmail.com> --- hw/pci-bridge/pci_expander_bridge.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/hw/pci-bridge/pci_expander_bridge.c b/hw/pci-bridge/pci_expander_bridge.c index a052c4c..20fec50 100644 --- a/hw/pci-bridge/pci_expander_bridge.c +++ b/hw/pci-bridge/pci_expander_bridge.c @@ -42,6 +42,8 @@ typedef struct PXBBus { #define TYPE_PXB_PCIE_DEVICE "pxb-pcie" #define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_PCIE_DEVICE) +#define PROP_PXB_PCIE_DOMAIN_NR "domain_nr" +#define PROP_PXB_PCIE_MAX_BUS "max_bus" #define PROP_PXB_BUS_NR "bus_nr" #define PROP_PXB_NUMA_NODE "numa_node" @@ -52,6 +54,8 @@ typedef struct PXBDev { uint8_t bus_nr; uint16_t numa_node; + uint32_t domain_nr; /* PCI domain, non-zero means separate domain */ + uint8_t max_bus; /* max bus number to use(including this one) */ } PXBDev; #define TYPE_PXB_PCIE_HOST "pxb-pcie-host" @@ -81,6 +85,14 @@ static int pxb_bus_num(PCIBus *bus) return pxb->bus_nr; } +static int pxb_domain_num(PCIBus *bus) +{ + PXBDev *pxb = convert_to_pxb(bus->parent_dev); + + /* for pxb, this should always be zero */ + return pxb->domain_nr; +} + static bool pxb_is_root(PCIBus *bus) { return true; /* by definition */ @@ -122,7 +134,7 @@ static const char *pxb_host_root_bus_path(PCIHostState *host_bridge, 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)); + snprintf(bus->bus_path, 8, "%04x:%02x", pxb_domain_num(rootbus), pxb_bus_num(rootbus)); return bus->bus_path; } @@ -275,7 +287,10 @@ static gint pxb_compare(gconstpointer a, gconstpointer b) { const PXBDev *pxb_a = a, *pxb_b = b; - return pxb_a->bus_nr < pxb_b->bus_nr ? -1 : + /* compare domain_nr first, then bus_nr */ + return pxb_a->domain_nr < pxb_b->domain_nr ? -1 : + pxb_a->domain_nr > pxb_b->domain_nr ? 1 : + pxb_a->bus_nr < pxb_b->bus_nr ? -1 : pxb_a->bus_nr > pxb_b->bus_nr ? 1 : 0; } @@ -299,6 +314,7 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool pcie, Error **errp) } if (pcie) { + g_assert (pxb->domain_nr == 0 || pxb->max_bus >= pxb->bus_nr); ds = qdev_create(NULL, TYPE_PXB_PCIE_HOST); bus = pci_root_bus_new(ds, dev_name, NULL, NULL, 0, TYPE_PXB_PCIE_BUS); } else { @@ -368,6 +384,9 @@ static Property pxb_dev_properties[] = { static Property pxb_pcie_dev_properties[] = { DEFINE_PROP_UINT8(PROP_PXB_BUS_NR, PXBDev, bus_nr, 0), DEFINE_PROP_UINT16(PROP_PXB_NUMA_NODE, PXBDev, numa_node, NUMA_NODE_UNASSIGNED), + DEFINE_PROP_UINT32(PROP_PXB_PCIE_DOMAIN_NR, PXBDev, domain_nr, 0), + /* set a small default value, bus range is [bus_nr, max_bus] */ + DEFINE_PROP_UINT8(PROP_PXB_PCIE_MAX_BUS, PXBDev, max_bus, 15), DEFINE_PROP_END_OF_LIST(), }; -- 2.7.4