aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/pci/mmconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/pci/mmconfig.c')
-rw-r--r--arch/x86_64/pci/mmconfig.c39
1 files changed, 24 insertions, 15 deletions
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index dfe84c322552..d4e25f38287d 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -14,8 +14,11 @@
14#include "pci.h" 14#include "pci.h"
15 15
16#define MMCONFIG_APER_SIZE (256*1024*1024) 16#define MMCONFIG_APER_SIZE (256*1024*1024)
17/* Verify the first 16 busses. We assume that systems with more busses
18 get MCFG right. */
19#define MAX_CHECK_BUS 16
17 20
18static DECLARE_BITMAP(fallback_slots, 32); 21static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS);
19 22
20/* Static virtual mapping of the MMCONFIG aperture */ 23/* Static virtual mapping of the MMCONFIG aperture */
21struct mmcfg_virt { 24struct mmcfg_virt {
@@ -57,7 +60,8 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
57static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) 60static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
58{ 61{
59 char __iomem *addr; 62 char __iomem *addr;
60 if (seg == 0 && bus == 0 && test_bit(PCI_SLOT(devfn), fallback_slots)) 63 if (seg == 0 && bus < MAX_CHECK_BUS &&
64 test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
61 return NULL; 65 return NULL;
62 addr = get_virt(seg, bus); 66 addr = get_virt(seg, bus);
63 if (!addr) 67 if (!addr)
@@ -131,21 +135,26 @@ static struct pci_raw_ops pci_mmcfg = {
131 Normally this can be expressed in the MCFG by not listing them 135 Normally this can be expressed in the MCFG by not listing them
132 and assigning suitable _SEGs, but this isn't implemented in some BIOS. 136 and assigning suitable _SEGs, but this isn't implemented in some BIOS.
133 Instead try to discover all devices on bus 0 that are unreachable using MM 137 Instead try to discover all devices on bus 0 that are unreachable using MM
134 and fallback for them. 138 and fallback for them. */
135 We only do this for bus 0/seg 0 */
136static __init void unreachable_devices(void) 139static __init void unreachable_devices(void)
137{ 140{
138 int i; 141 int i, k;
139 for (i = 0; i < 32; i++) { 142 /* Use the max bus number from ACPI here? */
140 u32 val1; 143 for (k = 0; i < MAX_CHECK_BUS; k++) {
141 char __iomem *addr; 144 for (i = 0; i < 32; i++) {
142 145 u32 val1;
143 pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1); 146 char __iomem *addr;
144 if (val1 == 0xffffffff) 147
145 continue; 148 pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
146 addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0)); 149 if (val1 == 0xffffffff)
147 if (addr == NULL|| readl(addr) != val1) { 150 continue;
148 set_bit(i, fallback_slots); 151 addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
152 if (addr == NULL|| readl(addr) != val1) {
153 set_bit(i + 32*k, fallback_slots);
154 printk(KERN_NOTICE
155 "PCI: No mmconfig possible on device %x:%x\n",
156 k, i);
157 }
149 } 158 }
150 } 159 }
151} 160}