diff options
-rw-r--r-- | arch/i386/pci/mmconfig.c | 52 | ||||
-rw-r--r-- | arch/x86_64/pci/mmconfig.c | 39 |
2 files changed, 54 insertions, 37 deletions
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index ee815c7d3e4c..2002c741a383 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c | |||
@@ -17,12 +17,15 @@ | |||
17 | 17 | ||
18 | #define MMCONFIG_APER_SIZE (256*1024*1024) | 18 | #define MMCONFIG_APER_SIZE (256*1024*1024) |
19 | 19 | ||
20 | /* Assume systems with more busses have correct MCFG */ | ||
21 | #define MAX_CHECK_BUS 16 | ||
22 | |||
20 | #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) | 23 | #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) |
21 | 24 | ||
22 | /* The base address of the last MMCONFIG device accessed */ | 25 | /* The base address of the last MMCONFIG device accessed */ |
23 | static u32 mmcfg_last_accessed_device; | 26 | static u32 mmcfg_last_accessed_device; |
24 | 27 | ||
25 | static DECLARE_BITMAP(fallback_slots, 32); | 28 | static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32); |
26 | 29 | ||
27 | /* | 30 | /* |
28 | * Functions for accessing PCI configuration space with MMCONFIG accesses | 31 | * Functions for accessing PCI configuration space with MMCONFIG accesses |
@@ -32,8 +35,8 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn) | |||
32 | int cfg_num = -1; | 35 | int cfg_num = -1; |
33 | struct acpi_table_mcfg_config *cfg; | 36 | struct acpi_table_mcfg_config *cfg; |
34 | 37 | ||
35 | if (seg == 0 && bus == 0 && | 38 | if (seg == 0 && bus < MAX_CHECK_BUS && |
36 | test_bit(PCI_SLOT(devfn), fallback_slots)) | 39 | test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots)) |
37 | return 0; | 40 | return 0; |
38 | 41 | ||
39 | while (1) { | 42 | while (1) { |
@@ -149,29 +152,34 @@ static struct pci_raw_ops pci_mmcfg = { | |||
149 | Normally this can be expressed in the MCFG by not listing them | 152 | Normally this can be expressed in the MCFG by not listing them |
150 | and assigning suitable _SEGs, but this isn't implemented in some BIOS. | 153 | and assigning suitable _SEGs, but this isn't implemented in some BIOS. |
151 | Instead try to discover all devices on bus 0 that are unreachable using MM | 154 | Instead try to discover all devices on bus 0 that are unreachable using MM |
152 | and fallback for them. | 155 | and fallback for them. */ |
153 | We only do this for bus 0/seg 0 */ | ||
154 | static __init void unreachable_devices(void) | 156 | static __init void unreachable_devices(void) |
155 | { | 157 | { |
156 | int i; | 158 | int i, k; |
157 | unsigned long flags; | 159 | unsigned long flags; |
158 | 160 | ||
159 | for (i = 0; i < 32; i++) { | 161 | for (k = 0; k < MAX_CHECK_BUS; k++) { |
160 | u32 val1; | 162 | for (i = 0; i < 32; i++) { |
161 | u32 addr; | 163 | u32 val1; |
162 | 164 | u32 addr; | |
163 | pci_conf1_read(0, 0, PCI_DEVFN(i, 0), 0, 4, &val1); | 165 | |
164 | if (val1 == 0xffffffff) | 166 | pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1); |
165 | continue; | 167 | if (val1 == 0xffffffff) |
166 | 168 | continue; | |
167 | /* Locking probably not needed, but safer */ | 169 | |
168 | spin_lock_irqsave(&pci_config_lock, flags); | 170 | /* Locking probably not needed, but safer */ |
169 | addr = get_base_addr(0, 0, PCI_DEVFN(i, 0)); | 171 | spin_lock_irqsave(&pci_config_lock, flags); |
170 | if (addr != 0) | 172 | addr = get_base_addr(0, k, PCI_DEVFN(i, 0)); |
171 | pci_exp_set_dev_base(addr, 0, PCI_DEVFN(i, 0)); | 173 | if (addr != 0) |
172 | if (addr == 0 || readl((u32 __iomem *)mmcfg_virt_addr) != val1) | 174 | pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0)); |
173 | set_bit(i, fallback_slots); | 175 | if (addr == 0 || |
174 | spin_unlock_irqrestore(&pci_config_lock, flags); | 176 | readl((u32 __iomem *)mmcfg_virt_addr) != val1) { |
177 | set_bit(i, fallback_slots); | ||
178 | printk(KERN_NOTICE | ||
179 | "PCI: No mmconfig possible on %x:%x\n", k, i); | ||
180 | } | ||
181 | spin_unlock_irqrestore(&pci_config_lock, flags); | ||
182 | } | ||
175 | } | 183 | } |
176 | } | 184 | } |
177 | 185 | ||
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 | ||
18 | static DECLARE_BITMAP(fallback_slots, 32); | 21 | static 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 */ |
21 | struct mmcfg_virt { | 24 | struct mmcfg_virt { |
@@ -57,7 +60,8 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus) | |||
57 | static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) | 60 | static 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 */ | ||
136 | static __init void unreachable_devices(void) | 139 | static __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 | } |