Commit 1c685a90 authored by Greg Kurz's avatar Greg Kurz Committed by David Gibson
Browse files

pci: Allow PCI bus subtypes to support extended config space accesses



Some PHB implementations, eg. PAPR used on pseries machine, act like
a regular PCI bus rather than a PCIe bus, but allow access to the
PCIe extended config space anyway.

Introduce a new PCI bus class method to modelize this behaviour and
use it when adjusting the config space size limit during accesses.

No behaviour change for existing PCI bus types.

Signed-off-by: default avatarGreg Kurz <groug@kaod.org>
Message-Id: <155414130271.574858.4253514266378127489.stgit@bahia.lan>
Signed-off-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
parent 5263724b
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -147,6 +147,11 @@ static uint16_t pcibus_numa_node(PCIBus *bus)
    return NUMA_NODE_UNASSIGNED;
}

static bool pcibus_allows_extended_config_space(PCIBus *bus)
{
    return false;
}

static void pci_bus_class_init(ObjectClass *klass, void *data)
{
    BusClass *k = BUS_CLASS(klass);
@@ -162,6 +167,7 @@ static void pci_bus_class_init(ObjectClass *klass, void *data)
    pbc->is_root = pcibus_is_root;
    pbc->bus_num = pcibus_num;
    pbc->numa_node = pcibus_numa_node;
    pbc->allows_extended_config_space = pcibus_allows_extended_config_space;
}

static const TypeInfo pci_bus_info = {
@@ -182,9 +188,22 @@ static const TypeInfo conventional_pci_interface_info = {
    .parent        = TYPE_INTERFACE,
};

static bool pciebus_allows_extended_config_space(PCIBus *bus)
{
    return true;
}

static void pcie_bus_class_init(ObjectClass *klass, void *data)
{
    PCIBusClass *pbc = PCI_BUS_CLASS(klass);

    pbc->allows_extended_config_space = pciebus_allows_extended_config_space;
}

static const TypeInfo pcie_bus_info = {
    .name = TYPE_PCIE_BUS,
    .parent = TYPE_PCI_BUS,
    .class_init = pcie_bus_class_init,
};

static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
@@ -401,6 +420,11 @@ bool pci_bus_is_root(PCIBus *bus)
    return PCI_BUS_GET_CLASS(bus)->is_root(bus);
}

bool pci_bus_allows_extended_config_space(PCIBus *bus)
{
    return PCI_BUS_GET_CLASS(bus)->allows_extended_config_space(bus);
}

void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
                              const char *name,
                              MemoryRegion *address_space_mem,
+1 −1
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr)
static void pci_adjust_config_limit(PCIBus *bus, uint32_t *limit)
{
    if (*limit > PCI_CONFIG_SPACE_SIZE) {
        if (!pci_bus_is_express(bus)) {
        if (!pci_bus_allows_extended_config_space(bus)) {
            *limit = PCI_CONFIG_SPACE_SIZE;
            return;
        }
+2 −0
Original line number Diff line number Diff line
@@ -396,6 +396,8 @@ typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin);

bool pci_bus_is_express(PCIBus *bus);
bool pci_bus_is_root(PCIBus *bus);
bool pci_bus_allows_extended_config_space(PCIBus *bus);

void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
                              const char *name,
                              MemoryRegion *address_space_mem,
+1 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ typedef struct PCIBusClass {
    bool (*is_root)(PCIBus *bus);
    int (*bus_num)(PCIBus *bus);
    uint16_t (*numa_node)(PCIBus *bus);
    bool (*allows_extended_config_space)(PCIBus *bus);
} PCIBusClass;

struct PCIBus {