hw/pci: Add pcie_count_ds_port() and pcie_find_port_first() helpers

These two helpers enable host bridges to operate differently depending on
the number of downstream ports, in particular if there is only a single
port.

Useful for CXL where HDM address decoders are allowed to be implicit in
the host bridge if there is only a single root port.

Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20230227153128.8164-2-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Jonathan Cameron 2023-02-27 15:31:27 +00:00 committed by Michael S. Tsirkin
parent 415442a1b4
commit 84344ee2da
2 changed files with 40 additions and 0 deletions

View File

@ -161,6 +161,44 @@ PCIDevice *pcie_find_port_by_pn(PCIBus *bus, uint8_t pn)
return NULL;
}
/* Find first port in devfn number order */
PCIDevice *pcie_find_port_first(PCIBus *bus)
{
int devfn;
for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
PCIDevice *d = bus->devices[devfn];
if (!d || !pci_is_express(d) || !d->exp.exp_cap) {
continue;
}
if (object_dynamic_cast(OBJECT(d), TYPE_PCIE_PORT)) {
return d;
}
}
return NULL;
}
int pcie_count_ds_ports(PCIBus *bus)
{
int dsp_count = 0;
int devfn;
for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
PCIDevice *d = bus->devices[devfn];
if (!d || !pci_is_express(d) || !d->exp.exp_cap) {
continue;
}
if (object_dynamic_cast(OBJECT(d), TYPE_PCIE_PORT)) {
dsp_count++;
}
}
return dsp_count;
}
static bool pcie_slot_is_hotpluggbale_bus(HotplugHandler *plug_handler,
BusState *bus)
{

View File

@ -41,6 +41,8 @@ struct PCIEPort {
void pcie_port_init_reg(PCIDevice *d);
PCIDevice *pcie_find_port_by_pn(PCIBus *bus, uint8_t pn);
PCIDevice *pcie_find_port_first(PCIBus *bus);
int pcie_count_ds_ports(PCIBus *bus);
#define TYPE_PCIE_SLOT "pcie-slot"
OBJECT_DECLARE_SIMPLE_TYPE(PCIESlot, PCIE_SLOT)