aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/probe.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 490031fd2108..b47c2dd5b9e1 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -984,6 +984,43 @@ void set_pcie_hotplug_bridge(struct pci_dev *pdev)
984 984
985 985
986/** 986/**
987 * pci_ext_cfg_is_aliased - is ext config space just an alias of std config?
988 * @dev: PCI device
989 *
990 * PCI Express to PCI/PCI-X Bridge Specification, rev 1.0, 4.1.4 says that
991 * when forwarding a type1 configuration request the bridge must check that
992 * the extended register address field is zero. The bridge is not permitted
993 * to forward the transactions and must handle it as an Unsupported Request.
994 * Some bridges do not follow this rule and simply drop the extended register
995 * bits, resulting in the standard config space being aliased, every 256
996 * bytes across the entire configuration space. Test for this condition by
997 * comparing the first dword of each potential alias to the vendor/device ID.
998 * Known offenders:
999 * ASM1083/1085 PCIe-to-PCI Reversible Bridge (1b21:1080, rev 01 & 03)
1000 * AMD/ATI SBx00 PCI to PCI Bridge (1002:4384, rev 40)
1001 */
1002static bool pci_ext_cfg_is_aliased(struct pci_dev *dev)
1003{
1004#ifdef CONFIG_PCI_QUIRKS
1005 int pos;
1006 u32 header, tmp;
1007
1008 pci_read_config_dword(dev, PCI_VENDOR_ID, &header);
1009
1010 for (pos = PCI_CFG_SPACE_SIZE;
1011 pos < PCI_CFG_SPACE_EXP_SIZE; pos += PCI_CFG_SPACE_SIZE) {
1012 if (pci_read_config_dword(dev, pos, &tmp) != PCIBIOS_SUCCESSFUL
1013 || header != tmp)
1014 return false;
1015 }
1016
1017 return true;
1018#else
1019 return false;
1020#endif
1021}
1022
1023/**
987 * pci_cfg_space_size - get the configuration space size of the PCI device. 1024 * pci_cfg_space_size - get the configuration space size of the PCI device.
988 * @dev: PCI device 1025 * @dev: PCI device
989 * 1026 *
@@ -1001,7 +1038,7 @@ static int pci_cfg_space_size_ext(struct pci_dev *dev)
1001 1038
1002 if (pci_read_config_dword(dev, pos, &status) != PCIBIOS_SUCCESSFUL) 1039 if (pci_read_config_dword(dev, pos, &status) != PCIBIOS_SUCCESSFUL)
1003 goto fail; 1040 goto fail;
1004 if (status == 0xffffffff) 1041 if (status == 0xffffffff || pci_ext_cfg_is_aliased(dev))
1005 goto fail; 1042 goto fail;
1006 1043
1007 return PCI_CFG_SPACE_EXP_SIZE; 1044 return PCI_CFG_SPACE_EXP_SIZE;