diff options
Diffstat (limited to 'arch/x86_64/pci/mmconfig.c')
-rw-r--r-- | arch/x86_64/pci/mmconfig.c | 116 |
1 files changed, 30 insertions, 86 deletions
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c index faabb6e87f12..65d82736987e 100644 --- a/arch/x86_64/pci/mmconfig.c +++ b/arch/x86_64/pci/mmconfig.c | |||
@@ -13,16 +13,6 @@ | |||
13 | 13 | ||
14 | #include "pci.h" | 14 | #include "pci.h" |
15 | 15 | ||
16 | /* aperture is up to 256MB but BIOS may reserve less */ | ||
17 | #define MMCONFIG_APER_MIN (2 * 1024*1024) | ||
18 | #define MMCONFIG_APER_MAX (256 * 1024*1024) | ||
19 | |||
20 | /* Verify the first 16 busses. We assume that systems with more busses | ||
21 | get MCFG right. */ | ||
22 | #define MAX_CHECK_BUS 16 | ||
23 | |||
24 | static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS); | ||
25 | |||
26 | /* Static virtual mapping of the MMCONFIG aperture */ | 16 | /* Static virtual mapping of the MMCONFIG aperture */ |
27 | struct mmcfg_virt { | 17 | struct mmcfg_virt { |
28 | struct acpi_mcfg_allocation *cfg; | 18 | struct acpi_mcfg_allocation *cfg; |
@@ -32,30 +22,17 @@ static struct mmcfg_virt *pci_mmcfg_virt; | |||
32 | 22 | ||
33 | static char __iomem *get_virt(unsigned int seg, unsigned bus) | 23 | static char __iomem *get_virt(unsigned int seg, unsigned bus) |
34 | { | 24 | { |
35 | int cfg_num = -1; | ||
36 | struct acpi_mcfg_allocation *cfg; | 25 | struct acpi_mcfg_allocation *cfg; |
26 | int cfg_num; | ||
37 | 27 | ||
38 | while (1) { | 28 | for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) { |
39 | ++cfg_num; | ||
40 | if (cfg_num >= pci_mmcfg_config_num) | ||
41 | break; | ||
42 | cfg = pci_mmcfg_virt[cfg_num].cfg; | 29 | cfg = pci_mmcfg_virt[cfg_num].cfg; |
43 | if (cfg->pci_segment != seg) | 30 | if (cfg->pci_segment == seg && |
44 | continue; | 31 | (cfg->start_bus_number <= bus) && |
45 | if ((cfg->start_bus_number <= bus) && | ||
46 | (cfg->end_bus_number >= bus)) | 32 | (cfg->end_bus_number >= bus)) |
47 | return pci_mmcfg_virt[cfg_num].virt; | 33 | return pci_mmcfg_virt[cfg_num].virt; |
48 | } | 34 | } |
49 | 35 | ||
50 | /* Handle more broken MCFG tables on Asus etc. | ||
51 | They only contain a single entry for bus 0-0. Assume | ||
52 | this applies to all busses. */ | ||
53 | cfg = &pci_mmcfg_config[0]; | ||
54 | if (pci_mmcfg_config_num == 1 && | ||
55 | cfg->pci_segment == 0 && | ||
56 | (cfg->start_bus_number | cfg->end_bus_number) == 0) | ||
57 | return pci_mmcfg_virt[0].virt; | ||
58 | |||
59 | /* Fall back to type 0 */ | 36 | /* Fall back to type 0 */ |
60 | return NULL; | 37 | return NULL; |
61 | } | 38 | } |
@@ -63,8 +40,8 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus) | |||
63 | static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) | 40 | static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) |
64 | { | 41 | { |
65 | char __iomem *addr; | 42 | char __iomem *addr; |
66 | if (seg == 0 && bus < MAX_CHECK_BUS && | 43 | if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS && |
67 | test_bit(32*bus + PCI_SLOT(devfn), fallback_slots)) | 44 | test_bit(32*bus + PCI_SLOT(devfn), pci_mmcfg_fallback_slots)) |
68 | return NULL; | 45 | return NULL; |
69 | addr = get_virt(seg, bus); | 46 | addr = get_virt(seg, bus); |
70 | if (!addr) | 47 | if (!addr) |
@@ -135,79 +112,46 @@ static struct pci_raw_ops pci_mmcfg = { | |||
135 | .write = pci_mmcfg_write, | 112 | .write = pci_mmcfg_write, |
136 | }; | 113 | }; |
137 | 114 | ||
138 | /* K8 systems have some devices (typically in the builtin northbridge) | 115 | static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg) |
139 | that are only accessible using type1 | ||
140 | Normally this can be expressed in the MCFG by not listing them | ||
141 | and assigning suitable _SEGs, but this isn't implemented in some BIOS. | ||
142 | Instead try to discover all devices on bus 0 that are unreachable using MM | ||
143 | and fallback for them. */ | ||
144 | static __init void unreachable_devices(void) | ||
145 | { | 116 | { |
146 | int i, k; | 117 | void __iomem *addr; |
147 | /* Use the max bus number from ACPI here? */ | 118 | u32 size; |
148 | for (k = 0; k < MAX_CHECK_BUS; k++) { | 119 | |
149 | for (i = 0; i < 32; i++) { | 120 | size = (cfg->end_bus_number + 1) << 20; |
150 | u32 val1; | 121 | addr = ioremap_nocache(cfg->address, size); |
151 | char __iomem *addr; | 122 | if (addr) { |
152 | 123 | printk(KERN_INFO "PCI: Using MMCONFIG at %Lx - %Lx\n", | |
153 | pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1); | 124 | cfg->address, cfg->address + size - 1); |
154 | if (val1 == 0xffffffff) | ||
155 | continue; | ||
156 | addr = pci_dev_base(0, k, PCI_DEVFN(i, 0)); | ||
157 | if (addr == NULL|| readl(addr) != val1) { | ||
158 | set_bit(i + 32*k, fallback_slots); | ||
159 | printk(KERN_NOTICE "PCI: No mmconfig possible" | ||
160 | " on device %02x:%02x\n", k, i); | ||
161 | } | ||
162 | } | ||
163 | } | 125 | } |
126 | return addr; | ||
164 | } | 127 | } |
165 | 128 | ||
166 | void __init pci_mmcfg_init(int type) | 129 | int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus, |
130 | unsigned int devfn) | ||
167 | { | 131 | { |
168 | int i; | 132 | return pci_dev_base(seg, bus, devfn) != NULL; |
169 | 133 | } | |
170 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) | ||
171 | return; | ||
172 | |||
173 | acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg); | ||
174 | if ((pci_mmcfg_config_num == 0) || | ||
175 | (pci_mmcfg_config == NULL) || | ||
176 | (pci_mmcfg_config[0].address == 0)) | ||
177 | return; | ||
178 | |||
179 | /* Only do this check when type 1 works. If it doesn't work | ||
180 | assume we run on a Mac and always use MCFG */ | ||
181 | if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].address, | ||
182 | pci_mmcfg_config[0].address + MMCONFIG_APER_MIN, | ||
183 | E820_RESERVED)) { | ||
184 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %lx is not E820-reserved\n", | ||
185 | (unsigned long)pci_mmcfg_config[0].address); | ||
186 | printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); | ||
187 | return; | ||
188 | } | ||
189 | 134 | ||
190 | pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL); | 135 | int __init pci_mmcfg_arch_init(void) |
136 | { | ||
137 | int i; | ||
138 | pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * | ||
139 | pci_mmcfg_config_num, GFP_KERNEL); | ||
191 | if (pci_mmcfg_virt == NULL) { | 140 | if (pci_mmcfg_virt == NULL) { |
192 | printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n"); | 141 | printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n"); |
193 | return; | 142 | return 0; |
194 | } | 143 | } |
144 | |||
195 | for (i = 0; i < pci_mmcfg_config_num; ++i) { | 145 | for (i = 0; i < pci_mmcfg_config_num; ++i) { |
196 | pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i]; | 146 | pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i]; |
197 | pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].address, | 147 | pci_mmcfg_virt[i].virt = mcfg_ioremap(&pci_mmcfg_config[i]); |
198 | MMCONFIG_APER_MAX); | ||
199 | if (!pci_mmcfg_virt[i].virt) { | 148 | if (!pci_mmcfg_virt[i].virt) { |
200 | printk(KERN_ERR "PCI: Cannot map mmconfig aperture for " | 149 | printk(KERN_ERR "PCI: Cannot map mmconfig aperture for " |
201 | "segment %d\n", | 150 | "segment %d\n", |
202 | pci_mmcfg_config[i].pci_segment); | 151 | pci_mmcfg_config[i].pci_segment); |
203 | return; | 152 | return 0; |
204 | } | 153 | } |
205 | printk(KERN_INFO "PCI: Using MMCONFIG at %lx\n", | ||
206 | (unsigned long)pci_mmcfg_config[i].address); | ||
207 | } | 154 | } |
208 | |||
209 | unreachable_devices(); | ||
210 | |||
211 | raw_pci_ops = &pci_mmcfg; | 155 | raw_pci_ops = &pci_mmcfg; |
212 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; | 156 | return 1; |
213 | } | 157 | } |