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: Greg Kurz <groug@kaod.org>
Message-Id: <
155414130271.574858.
4253514266378127489.stgit@bahia.lan>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
return NUMA_NODE_UNASSIGNED;
}
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);
static void pci_bus_class_init(ObjectClass *klass, void *data)
{
BusClass *k = BUS_CLASS(klass);
pbc->is_root = pcibus_is_root;
pbc->bus_num = pcibus_num;
pbc->numa_node = pcibus_numa_node;
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 = {
}
static const TypeInfo pci_bus_info = {
.parent = TYPE_INTERFACE,
};
.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,
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);
};
static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
return PCI_BUS_GET_CLASS(bus)->is_root(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,
void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
const char *name,
MemoryRegion *address_space_mem,
static void pci_adjust_config_limit(PCIBus *bus, uint32_t *limit)
{
if (*limit > PCI_CONFIG_SPACE_SIZE) {
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;
}
*limit = PCI_CONFIG_SPACE_SIZE;
return;
}
bool pci_bus_is_express(PCIBus *bus);
bool pci_bus_is_root(PCIBus *bus);
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,
void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
const char *name,
MemoryRegion *address_space_mem,
bool (*is_root)(PCIBus *bus);
int (*bus_num)(PCIBus *bus);
uint16_t (*numa_node)(PCIBus *bus);
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 {
} PCIBusClass;
struct PCIBus {