@@ -193,6 +193,7 @@
enum pci_bus_flags {
PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1,
PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2,
+ PCI_BUS_FLAGS_COMPAT_CFG_SPACE = (__force pci_bus_flags_t) 4,
};
/* These values come from the PCI Express Spec */
@@ -827,6 +827,28 @@
child->primary = primary;
pci_bus_insert_busn_res(child, secondary, subordinate);
child->bridge_ctl = bctl;
+
+ {
+ int pos;
+ u32 status;
+ bool pci_compat_cfg_space = false;
+
+ if (!pci_is_pcie(dev) || (pci_pcie_type(dev) == PCI_EXP_TYPE_PCIE_BRIDGE) || (pci_pcie_type(dev) == PCI_EXP_TYPE_PCI_BRIDGE)) {
+ /* for PCI/PCI bridges, or PCIe/PCI bridge in forward or reverse mode, we have to check for PCI-X capabilities */
+ pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+ if (pos) {
+ pci_read_config_dword(dev, pos + PCI_X_STATUS, &status);
+ if (!(status & (PCI_X_STATUS_266MHZ | PCI_X_STATUS_533MHZ)))
+ pci_compat_cfg_space = true;
+ } else {
+ pci_compat_cfg_space = true;
+ }
+ if (pci_compat_cfg_space) {
+ dev_info(&dev->dev, "[%04x:%04x] Child bus limited to PCI-Compatible config space\n", dev->vendor, dev->device);
+ child->bus_flags |= PCI_BUS_FLAGS_COMPAT_CFG_SPACE;
+ }
+ }
+ }
}
cmax = pci_scan_child_bus(child);
@@ -1098,6 +1120,11 @@
goto fail;
}
+ if (dev->bus->bus_flags & PCI_BUS_FLAGS_COMPAT_CFG_SPACE) {
+ dev_info(&dev->dev, "[%04x:%04x] PCI-Compatible config space only due to parent bus(es)\n", dev->vendor, dev->device);
+ return PCI_CFG_SPACE_SIZE;
+ }
+
return pci_cfg_space_size_ext(dev);
fail: