summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2006-01-27 04:03:50 +0300
committerGreg Kroah-Hartman <gregkh@suse.de>2006-02-01 05:00:13 +0300
commit3103039cc2a8dc6ababc29afac5c3cadbfa69af9 (patch)
treef89e6a1ca25281fbf78f6438c0463d06251ae3a3
parent877be3f0304de16a77f11b2b47f1291b800d5479 (diff)
downloadlinux-3103039cc2a8dc6ababc29afac5c3cadbfa69af9.tar.xz
[PATCH] PCI: handle bogus MCFG entries
Handle more bogus MCFG entries Some Asus P4 boards seem to have broken MCFG tables with only a single entry for busses 0-0. Special case these and assume they mean all busses can be accessed. Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--arch/i386/pci/mmconfig.c15
-rw-r--r--arch/x86_64/pci/mmconfig.c19
2 files changed, 27 insertions, 7 deletions
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index 4bb4d4b0f73a..0ee8a983708c 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -36,8 +36,7 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
while (1) {
++cfg_num;
if (cfg_num >= pci_mmcfg_config_num) {
- /* Not found - fallback to type 1 */
- return 0;
+ break;
}
cfg = &pci_mmcfg_config[cfg_num];
if (cfg->pci_segment_group_number != seg)
@@ -46,6 +45,18 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
(cfg->end_bus_number >= bus))
return cfg->base_address;
}
+
+ /* Handle more broken MCFG tables on Asus etc.
+ They only contain a single entry for bus 0-0. Assume
+ this applies to all busses. */
+ cfg = &pci_mmcfg_config[0];
+ if (pci_mmcfg_config_num == 1 &&
+ cfg->pci_segment_group_number == 0 &&
+ (cfg->start_bus_number | cfg->end_bus_number) == 0)
+ return cfg->base_address;
+
+ /* Fall back to type 0 */
+ return 0;
}
static inline void pci_exp_set_dev_base(unsigned int base, int bus, int devfn)
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index f16c0d57c552..00d4ddbf980c 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -29,11 +29,8 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
while (1) {
++cfg_num;
- if (cfg_num >= pci_mmcfg_config_num) {
- /* Not found - fall back to type 1. This happens
- e.g. on the internal devices of a K8 northbridge. */
- return NULL;
- }
+ if (cfg_num >= pci_mmcfg_config_num)
+ break;
cfg = pci_mmcfg_virt[cfg_num].cfg;
if (cfg->pci_segment_group_number != seg)
continue;
@@ -41,6 +38,18 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
(cfg->end_bus_number >= bus))
return pci_mmcfg_virt[cfg_num].virt;
}
+
+ /* Handle more broken MCFG tables on Asus etc.
+ They only contain a single entry for bus 0-0. Assume
+ this applies to all busses. */
+ cfg = &pci_mmcfg_config[0];
+ if (pci_mmcfg_config_num == 1 &&
+ cfg->pci_segment_group_number == 0 &&
+ (cfg->start_bus_number | cfg->end_bus_number) == 0)
+ return cfg->base_address;
+
+ /* Fall back to type 0 */
+ return 0;
}
static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)