aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/pci/mmconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/pci/mmconfig.c')
-rw-r--r--arch/i386/pci/mmconfig.c74
1 files changed, 4 insertions, 70 deletions
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index 5700220dcf5f..97dcaaa0de0f 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -15,21 +15,13 @@
15#include <asm/e820.h> 15#include <asm/e820.h>
16#include "pci.h" 16#include "pci.h"
17 17
18/* aperture is up to 256MB but BIOS may reserve less */
19#define MMCONFIG_APER_MIN (2 * 1024*1024)
20#define MMCONFIG_APER_MAX (256 * 1024*1024)
21
22/* Assume systems with more busses have correct MCFG */ 18/* Assume systems with more busses have correct MCFG */
23#define MAX_CHECK_BUS 16
24
25#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) 19#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
26 20
27/* The base address of the last MMCONFIG device accessed */ 21/* The base address of the last MMCONFIG device accessed */
28static u32 mmcfg_last_accessed_device; 22static u32 mmcfg_last_accessed_device;
29static int mmcfg_last_accessed_cpu; 23static int mmcfg_last_accessed_cpu;
30 24
31static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);
32
33/* 25/*
34 * Functions for accessing PCI configuration space with MMCONFIG accesses 26 * Functions for accessing PCI configuration space with MMCONFIG accesses
35 */ 27 */
@@ -38,8 +30,8 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
38 int cfg_num = -1; 30 int cfg_num = -1;
39 struct acpi_mcfg_allocation *cfg; 31 struct acpi_mcfg_allocation *cfg;
40 32
41 if (seg == 0 && bus < MAX_CHECK_BUS && 33 if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
42 test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots)) 34 test_bit(PCI_SLOT(devfn) + 32*bus, pci_mmcfg_fallback_slots))
43 return 0; 35 return 0;
44 36
45 while (1) { 37 while (1) {
@@ -158,67 +150,9 @@ static struct pci_raw_ops pci_mmcfg = {
158 .write = pci_mmcfg_write, 150 .write = pci_mmcfg_write,
159}; 151};
160 152
161/* K8 systems have some devices (typically in the builtin northbridge) 153int __init pci_mmcfg_arch_init(void)
162 that are only accessible using type1
163 Normally this can be expressed in the MCFG by not listing them
164 and assigning suitable _SEGs, but this isn't implemented in some BIOS.
165 Instead try to discover all devices on bus 0 that are unreachable using MM
166 and fallback for them. */
167static __init void unreachable_devices(void)
168{ 154{
169 int i, k;
170 unsigned long flags;
171
172 for (k = 0; k < MAX_CHECK_BUS; k++) {
173 for (i = 0; i < 32; i++) {
174 u32 val1;
175 u32 addr;
176
177 pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1);
178 if (val1 == 0xffffffff)
179 continue;
180
181 /* Locking probably not needed, but safer */
182 spin_lock_irqsave(&pci_config_lock, flags);
183 addr = get_base_addr(0, k, PCI_DEVFN(i, 0));
184 if (addr != 0)
185 pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
186 if (addr == 0 ||
187 readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
188 set_bit(i + 32*k, fallback_slots);
189 printk(KERN_NOTICE
190 "PCI: No mmconfig possible on %x:%x\n", k, i);
191 }
192 spin_unlock_irqrestore(&pci_config_lock, flags);
193 }
194 }
195}
196
197void __init pci_mmcfg_init(int type)
198{
199 if ((pci_probe & PCI_PROBE_MMCONF) == 0)
200 return;
201
202 acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
203 if ((pci_mmcfg_config_num == 0) ||
204 (pci_mmcfg_config == NULL) ||
205 (pci_mmcfg_config[0].address == 0))
206 return;
207
208 /* Only do this check when type 1 works. If it doesn't work
209 assume we run on a Mac and always use MCFG */
210 if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].address,
211 pci_mmcfg_config[0].address + MMCONFIG_APER_MIN,
212 E820_RESERVED)) {
213 printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %lx is not E820-reserved\n",
214 (unsigned long)pci_mmcfg_config[0].address);
215 printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
216 return;
217 }
218
219 printk(KERN_INFO "PCI: Using MMCONFIG\n"); 155 printk(KERN_INFO "PCI: Using MMCONFIG\n");
220 raw_pci_ops = &pci_mmcfg; 156 raw_pci_ops = &pci_mmcfg;
221 pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; 157 return 1;
222
223 unreachable_devices();
224} 158}